I have the following code to export my STL file but it doesn't seems to work.
var loader = new THREE.STLLoader();
loader.load( './Mr_Jaws.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0x0692CE, specular: 0x111111, shininess: 100 } );
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( 1.2, 1.2, 1.2 );
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.set( 0, 0, 0 );
var box = new THREE.BoxHelper( mesh );
scene.add( box );
scene.add( mesh );
var export_stl = new THREE.STLExporter();
console.log(export_stl.parse(mesh));
});
What I get is the following:
solid exported
endsolid exported
Hope you can help me out.
Three.js version
Dev
[X ] r76
...
Related
How can I make the 3d objects that I load into the map using The WebGL overlay API, to cast shadows on the map tiles and on other loaded objects?
It seems to me that this is not supported yet( or this feature is removed) so is there any workaround?
Preferred WebGL framework: ThreeJs
A workaround with threeJS would be to put a thin box(it will not work with planeGeometry) on the ground that is completely transparent but receives the shadow. this can be achieved by shadowMaterial
Note: this would only show the shadows from meshes added to the webgloverlay, not from the buildings on the map
We do not have this option yet on google map , because overlay of map we get from "webgloverlayview" do not have receive shadow option.
I tried to create my own plane over google map and achieve the shadow
my plane opacity is very light like 0.3. I also added image below in of colorful plane to explain.
++
Please see #yosan_melese answer it prefect to use
ShadowMaterial
here is example code
import { Loader } from '#googlemaps/js-api-loader';
import * as THREE from 'three';
import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader.js';
const apiOptions = {
apiKey: 'A***********8',
version: "beta",
map_ids: [""]
};
let directionalLight = '';
const mapOptions = {
"tilt": 0,
"heading": 0,
"zoom": 18,
"center": { lat: 33.57404, lng: 73.1637 },
"mapId": "" ,
"mapTypeId": 'roadmap'
}
/*
roadmap: the default map that you usually see.
satellite: satellite view of Google Maps and Google Earth, when available.
hybrid: a mixture of roadmap and satellite view.
terrain: a map based on terrain information, such as mountains and valleys.
*/
async function initMap() {
const mapDiv = document.getElementById("map");
const apiLoader = new Loader(apiOptions);
await apiLoader.load();
return new google.maps.Map(mapDiv, mapOptions);
}
let scene, renderer, camera, loader,loader1,controls;
function initWebglOverlayView(map) {
const webglOverlayView = new google.maps.WebglOverlayView();
webglOverlayView.onAdd = () => {
// set up the scene
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera();
const ambientLight = new THREE.AmbientLight( 0xffffff, 0.75 ); // soft white light
scene.add(ambientLight);
directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.x += (-90)
directionalLight.position.y += 0
directionalLight.position.z += 20
directionalLight.castShadow = true
const d = 100;
directionalLight.shadow.camera.left = - d;
directionalLight.shadow.camera.right = d;
directionalLight.shadow.camera.top = d;
directionalLight.shadow.camera.bottom = - d;
scene.add(directionalLight);
scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );
// FLOOR
/*
const plane = new THREE.Mesh(new THREE.PlaneGeometry(2050, 2200, 300),
new THREE.MeshPhongMaterial({ color: 0xF3F4F5, opacity: 0.3, transparent: true}));
plane.rotation.x = 0;
plane.rotation.y = 0;
plane.rotation.z = 0;
plane.castShadow = true
plane.receiveShadow = true
scene.add(plane);
*/
//after yosan_melese answer i am using ShadowMaterial
const geometry = new THREE.PlaneGeometry( 2000, 2000 );
geometry.rotateX( - Math.PI / 2 );
const material = new THREE.ShadowMaterial();
material.opacity = 0.5;
const plane = new THREE.Mesh( geometry, material );
plane.rotation.x = 2;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
plane.receiveShadow = true;
scene.add( plane );
loader = new FBXLoader();
loader.load( 'model/name_model.fbx', function ( object ) {
object.scale.set( 1, 1, 1 );
object.rotation.x = 1.480;
object.rotation.y = 0.950;
object.rotation.z = 0.070;
object.castShadow = true;
object.receiveShadow = true;
object.name = "name_model";
object.traverse( function ( child ) {
if(child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
});
scene.add( object );
});
}
webglOverlayView.onContextRestored = (gl) => {
// create the three.js renderer, using the
// maps's WebGL rendering context.
renderer = new THREE.WebGLRenderer({
canvas: gl.canvas,
context: gl,
...gl.getContextAttributes(),
});
renderer.autoClear = false;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.receiveShadow = true;
renderer.castShadow = true;
}
webglOverlayView.onDraw = (gl, coordinateTransformer) => {
// update camera matrix to ensure the model is georeferenced correctly on the map
const matrix = coordinateTransformer.fromLatLngAltitude(mapOptions.center, 10);
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
webglOverlayView.requestRedraw();
renderer.render(scene, camera);
// always reset the GL state
renderer.resetState();
}
webglOverlayView.setMap(map);
}
(async () => {
const map = await initMap();
initWebglOverlayView(map);
})();
after #yosan_melese code
I can't seem to get this model to animate in three.js.
I've tried exporting it so many different ways, but I'm not sure if it's the model or the code. I'm getting a trace on the animations from the model, but nothing happens on the call-back. Any ideas?
new THREE.JSONLoader().load( 'assets/model/Gunnar.json', function ( model, material ) {
var mesh = new THREE.SkinnedMesh(model, material);
scene.add( mesh );
mesh.scale.x = mesh.scale.y = mesh.scale.z = 5;
var clips = model.animations;
mixer = new THREE.AnimationMixer( mesh );
mixer.clipAction( clips[0] ).play();
loaded = true;
animate();
} );
function animate() {
requestAnimationFrame( animate );
if (loaded) {
mixer.update(clock.getDelta());
}
renderer.render( scene, camera );
}
Blender/JSON files:
https://www.dropbox.com/s/lxy6q3wjydmtlhd/json_blender_files.zip?dl=0
I need help on using a material with a image texture
Using the 2.9 viewer files.
I see that it uses revision 71 of three.js
I have created a custom shape. A square out of vertices
I would like to use a image texture material
var shininess = 50, specular = 0x333333, bumpScale = 1, shading = THREE.SmoothShading;
var imgTexture = THREE.ImageUtils.loadTexture( "textures/UV_Grid_Sm.jpg" );
imgTexture.wrapS = imgTexture.wrapT = THREE.RepeatWrapping;
imgTexture.anisotropy = 16;
var material = new THREE.MeshLambertMaterial( { map: imgTexture, color: 0xffffff, shading: shading } );
viewer.impl.matman().addMaterial("FloorMaterial", material, true);
...
// Convert Array to Vector Array and World Space
var vectorWorldArray = convertFloatArrayToVectorWorldArray(viewer,
matrixWorld, floatArray);
var shape = new THREE.Shape(vectorWorldArray);
var geometry = new THREE.ShapeGeometry(shape);
geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );
geometry.faces.push( new THREE.Face3( 2, 3, 0 ) );
geometry.computeFaceNormals();
var mesh = new THREE.Mesh(geometry, material);
var scene = viewer.impl.scene;
// mesh.translateZ( 10 );
scene.add(mesh);
The texture just shows up as all black
Only thing that comes up in chrome (Version 52.0.2743.116 m)
[.Offscreen-For-WebGL-0B70AB98]RENDER WARNING: there is no texture bound to the unit 0
I know that the texture exists
Is there a easier/correcct way of adding the image texture material ?
Looks like lambert needs a light other then what comes with the viewer
I switched to using BasicMaterial now my texture shows up.
var material = new THREE.MeshBasicMaterial( { map: imgTexture, color: 0xffffff, shading: shading } );
I was wondering if its possible to add an object that is loaded via THREE.JSONLoader as public variable? Ideally, I'd like all my loaded textures, material creation, and geometry to be public variables at the top of my script for easy manipulation (I have strong 3D background but new to js and webGL). I'm finding that my public vars that are declared something - are no longer public once they're added as a parameter to a function - in this case the JSONLoader. However, just naming a var, without declaring its value "runs" but I get weird THREE.min.js error I can't comprehend. I've included my code below - know it has other issues - please feel free to let me know how bad it is - it helps me learn :)
//webGL
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0, 16, 25);
camera.rotation.x += -0.32;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
cubeCamera = new THREE.CubeCamera(1, 1000, 256); // parameters: near, far, resolution
cubeCamera.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter; // mipmap filter
scene.add(cubeCamera);
///LOADERS
var loadTexture = new THREE.TextureLoader();
var loaderJs = new THREE.JSONLoader();
///TEXTURES
var skyTexture = loadTexture.load("textures/background.jpg");
var seatTexture = loadTexture.load("textures/abc_Diffuse.jpg");
///MATERIALS
var skyMaterial = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide,
map: skyTexture
});
var frameMaterial = new THREE.MeshLambertMaterial({
//envMap: cubeCamera.renderTarget,
color: 0xffffff
});
var seatMaterial = new THREE.MeshLambertMaterial({
map: seatTexture
});
///GEOMETRY and MESHES
var frameGeo;
var skyGeo = new THREE.SphereGeometry(30, 30, 30);
var skySphere = new THREE.Mesh(skyGeo, skyMaterial);
scene.add(skySphere);
loaderJs.load("models/stoolFrame.js", function (){
frameGeo = new THREE.Mesh(frameGeo, frameMaterial);
frameGeo.scale.set(.5, .5, .5);
barStool.add(frameGeo);
});
loaderJs.load("models/stoolSeat.js", function (seatGeo){
seatGeo = new THREE.Mesh(seatGeo, seatMaterial);
seatGeo.scale.set(.5, .5, .5);
barStool.add(seatGeo);
});
var barStool = new THREE.Object3D();
scene.add(barStool);
var render = function () {
requestAnimationFrame(render);
barStool.rotation.y += 0.01;
frameGeo.visible = false;
cubeCamera.position.copy(frameGeo.position);
cubeCamera.updateCubeMap(renderer, scene);
frameGeo.visible = true;
renderer.render(scene, camera);
};
render();
When loading your stoolFrame, you forgot to add the parameters for the callback function, check the documentation example. The callback function takes a geometry and a material. When loading the stoolSeat you forgot the material aswell (provided you have a material for the stool)
var frameGeometry;
var frameMaterial;
var frameMesh;
loaderJs.load("models/stoolFrame.js", function (geometry, material){
frameGeometry = geometry;
frameMaterial = material
frameMesh = new THREE.Mesh(frameGeometry, frameMaterial);
frameMesh.scale.set(.5, .5, .5);
barStool.add(frameMesh);
});
Above is an example on how to make the geometry, material and mesh into global variables. However you probably dont need to save the geometry and material as global vars (you can access them from the mesh anyway: frameMesh.material; frameMesh.geometry).
If the parameter names are the same as a global variable name, javascript will use the parameter variable instead of the global one when trying to access it.
I'm a newbie, and I think I missed something.
Could someone check, please?
HTML page: http://xalien95.altervista.org/pkmnxy_engine/alisopoli.html
MODEL and TEXTURES: http://xalien95.altervista.org/pkmnxy_engine/alisopoli/
I can see the model (with weird colors), but not the textures (it's a mesh with multiple materials).
Thanks in advance!
EDIT:
I tried with all the materials types:
THREE.MeshBasicMaterial
THREE.MeshDepthMaterial
THREE.MeshLambertMaterial
THREE.MeshNormalMaterial
THREE.MeshPhongMaterial
But noone works, so I think I've missed something (or the materials path is different).
Here's the script:
var camera, scene, renderer, mesh, loader;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1000;
scene = new THREE.Scene();
loader = new THREE.JSONLoader();
loader.load( "./alisopoli/alisopoli.js", function( geometry, materials ) {
var faceMaterial = new THREE.MeshPhongMaterial( materials );
mesh = new THREE.Mesh( geometry, faceMaterial );
mesh.scale.set( 100, 100, 100 );
mesh.position.y = -150;
mesh.position.x = 0;
mesh.rotation.x = 60;
scene.add( mesh );
} );
var ambientLight = new THREE.AmbientLight(0x555555);
scene.add(ambientLight);
//var directionalLight = new THREE.DirectionalLight(0xffffff);
//directionalLight.position.set(1, 1, 1).normalize();
//scene.add(directionalLight);
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
//mesh.rotation.y += 0.005;
renderer.render( scene, camera );
}
Thanks in advance!
The weird colors are because you are assigning every mesh a "MeshNormalMaterial" during your load. You should check the three.js json loader examples or somehow get the correct material instead of assignen MeshNormalMaterials to the sub-meshes