Ok I have an fbx successfully loaded into Three.js exported from blender with all animation boxes checked. Ive tried all export settings from blender so that's not it.
This is how I bring the model in, and I am able to accurately determine whether the fbx has animations or not:
var geoFromScene = new THREE.Geometry();
var FBXLoader = require('three-fbx-loader');
var loader = new FBXLoader();
loader.load(string, function ( object ) {
object.traverse( function ( child ) {
if ( child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
geoFromScene = (new THREE.Geometry()).fromBufferGeometry(child.geometry);
}
} );
var theModel = new THREE.Mesh();
theModel.geometry = geoFromScene;
theModel.material = material;
theModel.position.set(5,5,-8);
//theModel.rotation.set(new THREE.Vector3( 0, MATH.pi/2, 0));
theModel.scale.set(0.1, 0.1, 0.1);
localThis.scene.add(theModel);
localThis.mixer = new THREE.AnimationMixer(theModel);
if(theModel.animations[0])
{
var action = localThis.mixer.clipAction(theModel.animations[0]);
action.play();
} else {
console.log("No animations");
}
} );
In update (which does work, because I can print the animation.time):
this.mixer.update(this.clock.getDelta());
And yet the model is just static. Whats wrong here?
UPDATE:
code from example copy pasted-
var geoFromScene = new THREE.Geometry();
var FBXLoader = require('three-fbx-loader');
var loader = new FBXLoader();
loader.load( string, function ( object ) {
localThis.mixer = new THREE.AnimationMixer( object );
var action = localThis.mixer.clipAction( object.animations[ 0 ] );
action.play();
object.traverse( function ( child ) {
if ( child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
} );
object.position.set(5,5,-8)
object.scale.set(0.1, 0.1, 0.1);
localThis.scene.add( object );
} );
in animate-
this.mixer.update(this.clock.getDelta());
All I get is the model armature it seems -
New approach:
var FBXLoader = require('wge-three-fbx-loader'); //https://www.npmjs.com/package/wge-three-fbx-loader
var loader = new FBXLoader();
loader.load( string, function ( object ) {
Related
I'm trying to load this GBL file and play the animation. This code returns the following error:
TypeError: Cannot read property 'length' of undefined at Function.CreateFromMorphTargetSequence
function Animate() {
if(window.anim_flag)
{
// Hotspot_Ring_Anim();
requestAnimationFrame(Animate);
renderer.clear();
TWEEN.update();
orbit.update();
if (mixer.length > 0) {
var delta = clock.getDelta();
for (var i = 0; i < mixer.length; i++) {
mixer[i].update(delta);
}
}
renderer.render(scene, camera);
}
}
function Add_Hotspot_Rings(id,px,py,pz,rx,ry,rz,sx,sy,sz) {
const loader = new GLTFLoader();
// Optional: Provide a DRACOLoader instance to decode compressed mesh data
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath( '../jsm/draco/' );
loader.setDRACOLoader( dracoLoader );
loader.load( '../Models/ABB_Clinic_AnimatedRings_Lowpoly_02.glb', function ( gltf ) {
const model = gltf.scene;
model.name = 'hotspot_rings';
model.position.set(px,py,pz);
model.rotation.set(0,ry,rz);
model.scale.set(0.90, 0.3, 0.90);
scene.add(model);
// MORPH
const mixerr = new THREE.AnimationMixer( model );
const clips = model.animations;
const morphClip = THREE.AnimationClip.CreateFromMorphTargetSequence( 'RingsRising', model.morphTargets );
mixerr.clipAction(morphClip).setDuration(1).play();
mixer.push(mixerr);
window.anim_flag= true;
Animate();
}, undefined, function ( error ) {
console.error( error );
} );
}
How can I resolve this error and load the model with the animation playing?
const morphClip = THREE.AnimationClip.CreateFromMorphTargetSequence( 'RingsRising', model.morphTargets );
Instances of Object3D do not have a morphTargets property.
Playing an animation from a glTF asset should look like so:
const animations = gltf.animations;
const mixer = new THREE.AnimationMixer( model );
mixer.clipAction( animations[ 0 ] ).setDuration( 1 ).play();
Live example: https://threejs.org/examples/webgl_morphtargets_horse
The most important part in my code is in JavaScript. I want that my objects can move when I press "down" or "right" or etc. The problem is that object from .json file is moving, but object from .obj file is not. Is it possible to fix that?
This is my code:
<script>
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var keyboard = new KeyboardState();
var galva;
init();
animate();
render();
function init()
{
var spgeometry = new THREE.SphereGeometry( 30, 32, 32 );
var spmaterial = new THREE.MeshBasicMaterial( {color: 0x00000} );
galva = new THREE.Mesh( spgeometry, spmaterial );
galva.position.set(125, 150, 90);
scene.add( galva );
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "models/android.js", addModelToScene );
var loader = new THREE.OBJLoader();
loader.load("models/teaport.obj", function ( object ) {
var material = new THREE.MeshLambertMaterial( );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
}
} );
object.scale.set(50,50,50);
scene.add( object );
} );
}
function addModelToScene( geometry, materials )
{
var material = new THREE.MeshLambertMaterial( materials );
c = new THREE.Mesh( geometry, material );
c.scale.set(50,50,50);
scene.add( c );
}
function update()
{
keyboard.update();
if ( keyboard.down("left") ){
galva.translateX( -50 );
}
if ( keyboard.down("right") ){
c.translateX( 50 );
galva.translateX( 50 );
object.translateX( 50 );
}
controls.update();
stats.update();
}
If you put together a jsfiddle or something similar - it could be easier to figure out. I think you end up with variable shadowing, and your "object" is simply undefined. Try following change.
var loader = new THREE.OBJLoader();
loader.load("models/teaport.obj", function ( o ) {
var material = new THREE.MeshLambertMaterial( );
o.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
}
} );
o.scale.set(50,50,50);
scene.add( o );
object = o; // <-- important
How to multiple textures material use in Three.js?.Here three textures using and one 3D sofa.obj format file. I tried a lot of time. Below my code. What do I mistake in my code?
var loader = new THREE.OBJLoader();
var textureLoader = new THREE.TextureLoader();
threeDTexture = new THREE.ImageUtils.loadTexture( 'models/Sofa/Texturses/paradis_beige.jpg' );
threeDTexture2 = new THREE.ImageUtils.loadTexture( 'models/Sofa/Texturses/1.jpg' );
threeDTexture3 = new THREE.ImageUtils.loadTexture( 'models/Sofa/Texturses/2.jpg' );
loader.load('models/Sofa/sofa.obj', function (object) {
var geo = object.children[0].geometry;
var mats = [threeDTexture, threeDTexture2,threeDTexture3];
objct = new THREE.Mesh(geo, mats);
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material = objct;
}
});
object.position.x = posX;
object.position.y = 0;
object.position.z = posZ;
var size = new THREE.Box3().setFromObject(object).getSize();
object.scale.set(width/size.x, height/size.y, depth/size.z);
scene1.add(object);
console.log(object);
console.log(size);
console.log(width/size.x, height/size.y, depth/size.z);
},
function ( xhr ) {
returnValue = ( xhr.loaded / xhr.total * 100 ) + '% loaded';
console.log(returnValue);
},
function ( error ) {
console.log( 'An error happened' );
}
);
break
first, the textureLoader declared on line-2 is not in use;
second, belowing mats is not an Material Array, you should new MeshBasicMaterial(...) to wrap a texture, see the document here.
var mats = [threeDTexture, threeDTexture2,threeDTexture3];
objct = new THREE.Mesh(geo, mats); // Mesh will not accept this mats param!
I have collada model (.dae) displayed by this code, and I add THREE.DoubleSide but it dose not work how can i fix this?
var loadingManager = new THREE.LoadingManager( function() {
scene.add( car );
} );
var loader = new THREE.ColladaLoader( loadingManager );
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('./model/car_Red.jpg');
loader.options.convertUpAxis = true;
loader.load( './car.dae', function ( collada ) {
car = collada.scene;
car.traverse(function (node) {
if (node.isMesh)
{
node.material.map = texture;
node.material.side = THREE.DoubleSide;
}
});
console.log(car);
I had loaded 3 external model with the name into my scene using json loader and now i want to get the name of the model/object by clicking it.
Below is the that i had used to load the model
var object_material = new THREE.MeshBasicMaterial({
color: 0xd6d6d6,
side: THREE.DoubleSide
});
var loader = new THREE.JSONLoader();
loader.load("models/"+file,
function(geometry, object_material)
{
var object = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(object_material));
model = new THREE.Object3D();
model.id=file;
model.name='sample'+file;
model.userData.id='sampledata'+file;
model.add(object);
model.position.set(obj_x,obj_y,obj_z);
model.mirroredLoop = true;
model.castShadow = true;
model.receiveShadow = true;
scene.add(model);
}
);
Below is my mouse down function
function onMouseDown(event) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
var pLocal = new THREE.Vector3(0, 0, -1);
var pWorld = pLocal.applyMatrix4(camera.matrixWorld);
var ray = new THREE.Raycaster(pWorld, vector.sub(pWorld).normalize());
// Get meshes from all objects
var getMeshes = function(children) {
var meshes = [];
for (var i = 0; i < children.length; i++)
{
if (children[i].children.length > 0) {
meshes = meshes.concat(getMeshes(children[i].children));
} else if (children[i] instanceof THREE.Mesh) {
meshes.push(children[i]);
}
}
return meshes;
};
function attributeValues(o)
{
var out = [];
for (var key in o) {
if (!o.hasOwnProperty(key))
continue;
out.push(o[key]);
}
return out;
}
var objects = attributeValues(this.o3dByEntityId);
var meshes = getMeshes(objects);
var intersects = ray.intersectObjects(meshes);
raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObjects( scene.children );
console.log(scene);
// this console displays all the objects under children - THREE.Object3D - name as name: "sample513.js"
if ( intersects.length > 0 )
{
// but for the clickedObject - the length is > 0 and name is empty
var clickedObject = intersects[0].object;
console.log(clickedObject.parent.userData.id); // return as undefined
if ( INTERSECTED != intersects[ 0 ].object )
{
INTERSECTED= intersects[ 0 ].object;
name = INTERSECTED.name;
}
} else {
console.log('intersects.length is 0');
}
}
Even-though i had provided the model name in the userData , i am not able to retrieve it . can any one guide me how to retrieve the name of the object when it is clicked
Try to make through this example. Look at messages in the console.
<script src="js/controls/EventsControls.js"></script>
EventsControls = new EventsControls( camera, renderer.domElement );
EventsControls.attachEvent( 'onclick', function() {
console.log( 'this.focused.name: ' + this.focused.name );
});
// if use drag and drop
EventsControls.attachEvent( 'dragAndDrop', function () {
this.container.style.cursor = 'move';
this.focused.position.y = this.previous.y;
});
EventsControls.attachEvent( 'mouseOut', function () {
this.container.style.cursor = 'auto';
});
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "models/Tux.js", addModelToScene );
function addModelToScene( geometry, materials ) {
var material = new THREE.MeshFaceMaterial( materials );
model = new THREE.Mesh( geometry, material );
model.scale.set( 10, 10, 10 ); model.name = 'Tux';
model.rotation.x = -Math.PI/2;
model.position.set( 175, 45, 125 );
scene.add( model );
EventsControls.attach( model );
}
The parent of the clickedObject is probably undefined. Perhaps you can console log the clickedObject and see which path you need to access the id.