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
Related
I am trying to replace a cube mesh with a car mesh using .obj and .mtl files (using three.js)
But every everytime I got this error:
Uncaught TypeError: e.OBJMTLLoader is not a constructor
I made sure to include the library () and there is no typo.
This is how I load the mesh model:
var loader = new THREE.OBJMTLLoader();
loader.load('./toycar.obj', './toycar.mtl',
function (object) {
toycar = object;
toycar.rotateX(-12); //toycar.rotateZ(-10.99);
toycar.rotateY(4.718);
scene.add(toycar);
});
and this is how I use it to move the model on the y axis:
if (toycar != undefined){
toycar.position.y = disp * 0.07; // z for rightLeft, y for upDown
var relativeCameraOffset = new THREE.Vector3(5, 0, 0); // change camera offset
var cameraOffset = relativeCameraOffset.applyMatrix4(toycar.matrixWorld);
camera.position.x = cameraOffset.x;
camera.position.y = cameraOffset.y;
camera.position.z = cameraOffset.z;
camera.lookAt(toycar.position);
}
At this point, I am not sure what caused this error to happen.
THREE.OBJMTLLoader does not exist in the repository. There is only OBJLoader and MTLLoader. The latter one is only required if you want to load materials, too.
I suggest you study webgl_loader_obj_mtl to show how both are used. Typical code looks like so:
new MTLLoader().load( 'materials.mtl', function ( materials ) {
materials.preload();
new OBJLoader()
.setMaterials( materials )
.load( 'object.obj', function ( object ) {
scene.add( object );
} );
} );
I´m trying to load some STL files using Three.js. The models are loaded correctly, but there are too many triangles that I would like to merge/smooth.
I had successfully applied smooth loading terrains in other 3D formats, but I can´t do it with the BufferGeometry that results from loading an STL file with the STLLoader.
_
var material = new THREE.MeshLambertMaterial( { ... } );
var path = "./models/budah.stl";
var loader = new THREE.STLLoader();
loader.load( path, function ( object ) {
object.computeBoundingBox();
object.computeBoundingSphere();
object.computeFaceNormals();
object.computeVertexNormals();
object.normalizeNormals();
object.center();
// Apply smooth
var modifier = new THREE.SubdivisionModifier( 1);
var smooth = smooth = object.clone();
smooth.mergeVertices();
smooth.computeFaceNormals();
smooth.computeVertexNormals();
modifier.modify( smooth );
scene.add( smooth );
});
This is what I tried, it throws an error: Uncaught TypeError: smooth.mergeVertices is not a function
If I comment the "mergeVertices()" line, what I get is a different error: Uncaught TypeError: Cannot read property 'length' of undefined in SubdivisionsModifier, line 156.
It seems that the sample codes I´m trying are outdated (this is happenning a lot recently due to the massive changes in the Three.JS library). Or maybe I´m forgetting something. The fact is that the vertices seems to be null..?
Thanks in advance!
It seems I was looking in the wrong direction: smoothing the triangles has nothing to do with the SubdivisionsModifier... What I needed was easier than that, just compute the vertex BEFORE applying the material, so it can use SmoothShading instead of FlatShading (did I got it right?).
The problem here was that the BufferGeometry returned by the STLLoader has not calculated vertices/vertex, so I had to do it manually. After that, apply mergeVertices() just before computeVertexNormals() and voilà! The triangles dissappear and everything is smooth:
var material = new THREE.MeshLambertMaterial( { ... } );
var path = "./models/budah.stl";
var loader = new THREE.STLLoader();
loader.load( path, function ( object ) {
object.computeBoundingBox();
object.computeVertexNormals();
object.center();
///////////////////////////////////////////////////////////////
var attrib = object.getAttribute('position');
if(attrib === undefined) {
throw new Error('a given BufferGeometry object must have a position attribute.');
}
var positions = attrib.array;
var vertices = [];
for(var i = 0, n = positions.length; i < n; i += 3) {
var x = positions[i];
var y = positions[i + 1];
var z = positions[i + 2];
vertices.push(new THREE.Vector3(x, y, z));
}
var faces = [];
for(var i = 0, n = vertices.length; i < n; i += 3) {
faces.push(new THREE.Face3(i, i + 1, i + 2));
}
var geometry = new THREE.Geometry();
geometry.vertices = vertices;
geometry.faces = faces;
geometry.computeFaceNormals();
geometry.mergeVertices()
geometry.computeVertexNormals();
///////////////////////////////////////////////////////////////
var mesh = new THREE.Mesh(geometry, material);
scene.add( mesh );
});
Than, you can convert it back to BufferGeometry, because it's more GPU/CPU efficient for more complex models:
var geometry = new THREE.Geometry();
geometry.vertices = vertices;
geometry.faces = faces;
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
var buffer_g = new THREE.BufferGeometry();
buffer_g.fromGeometry(geometry);
var mesh = new THREE.Mesh(buffer_g, material);
scene.add( mesh )
Happened this issue for me while loading an obj file. If you have a 3d software like 3dsmax:
Open the obj file,
Go to polygons selection mode and select all polygons.
Under the Surface properties panel, click 'Auto Smooth' button.
Export the model back to obj format
Now you won't have to call the functions geometry.mergeVertices() and geometry.computeVertexNormals();. Just load the obj and add to the scene, mesh will be smooth.
EDIT:
My obj files had meshphongmaterial by default and on changing the shading property to value 2 the mesh became smooth.
child.material.shading = 2
STL does not support vertex index.
That is reason it has duplicated vertex of all triangles.
Each vertex has its normal as triangle normal.
As a result, at same position( multiple very closed vertices), there is multiple normal value.
This leads to non-smooth surface of geometry when using Normal for lighting calculation.
I wish to group loaded json models in THREE.js but am getting an error...
THREE.Object3D.add: object not an instance of THREE.Object3D
I'm using the example code of...
var group = new THREE.Object3D();
and then...
group.add(model1);
group.add(model2);
I load model1 and model2 previously - these render out fine when I add them to the scene individually, but when I add the group I get the error...
scene.add( group );
I've tried a combination of different techniques such as THREE.Mesh() or adding json models to other json models eg. model1.add(model2).
R72
The problem is asynchronous loading of the models - trying to perform actions on the models before they are loaded.
group = new THREE.Mesh(); //global to add transforms
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "model1.json", function(geometry,materials) {
var mesh = createMesh(geometry,materials); //function to create generic mesh properties
group.add(mesh);
});
jsonLoader.load( "model2.json", function(geometry,materials) {
var mesh = createMesh(geometry,materials); //function to create generic mesh properties
group.add(mesh);
});
scene.add( group );
function createMesh( geometry, materials )
{
var material = new THREE.MeshFaceMaterial( materials );
mesh = new THREE.Mesh( geometry, material );
return mesh;
};
I have a 3D object of a chair made in Blender and exported as a .obj and .mtl. First of all, the load time is a horrendous 40+ seconds; I have no idea why (Visual Studio possibly?) Second, the images textures are not loading properly. With no ambient or directional lighting I get a silhouette. With the lighting I get a slight hint of gray to give a little depth but nothing close to the many colors in the original object. I have only been working with ThreeJS for a few days now so I'm quite new to it. Hence, I am at a loss. I have read several artciles related to my issue but none seem to solve the problem. I even went so far as to add an addon to Blender to export to .js. I could not get it to even load properly (I assume it had to do with the fact I kept the same loader info from the .OBJMTLLoader and the .JSONLoader doesn't support or needs more than what I gave; I just am not familiar enough with it know). Any ideas/suggestions? Here is my script:
`
<script src="js/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/loaders/OBJMTLLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if (!Detector.webgl) Detector.addGetWebGLMessage();
var container;
var camera, controls, scene, renderer;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.01, 1e10);
camera.position.z = 2;
//controls
controls = new THREE.TrackballControls(camera);
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.panSpeed = 2;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
scene = new THREE.Scene();
scene.add(camera);
//lights
var ambient = new THREE.AmbientLight(0xCCCCCC);
scene.add(ambient);
var directionalLight = new THREE.DirectionalLight(0xCCCCCC);
directionalLight.position.set(0, 0, 2).normalize();
scene.add(directionalLight);
//main img
var material = new THREE.MeshBasicMaterial({ color: '0xCCCCCC' });
var loader = new THREE.OBJMTLLoader();
loader.addEventListener('load', function (event) {
var geometry = event.content;
//var mesh = new THREE.Mesh(geometry);
scene.add(geometry, material);
});
loader.load('chair.obj', 'chair.mtl');
// renderer
renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
}
function render() {
var timer = Date.now() * 0.0005;
renderer.render(scene, camera);
}
</script>
`
Well, you are defining a gray MeshBasicMaterial to use with your obj instead of using the material(s) that the loader will create for you, i guess.
Just use this. The "object" should have the material defined in your mtl-file.
loader.addEventListener( 'load', function ( event ) {
var object = event.content;
scene.add( object );
});
loader.load( 'chair.obj', 'chair.mtl' );
Concerning your load time: Could be your local server. Also, be aware that the obj file format ist quite big in raw ascii format. Also, if the mtl-file defines textures, they are maybe quite big in file size, too.
#GuyGood was correct in my case for the long load time. I was using the python simplehttpserver and switch to a node server and no more slow texture loading problems. Check out the threejs wiki for other local server options.
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