So I am trying to clone the soldier model from the Three.js examples, because I want more than one later:
https://threejs.org/examples/webgl_animation_skinning_blending.html
I changed line 93 to read:
const loader = new GLTFLoader();
loader.load( 'https://threejs.org/examples/models/gltf/Soldier.glb', function ( gltf ) {
model = gltf.scene.clone();
scene.add( model );
model.traverse( function ( object ) {
if ( object.isMesh ) object.castShadow = true;
} );
But now the soldier is huge.
Why is this happening and is there a fix for it?
Here is a jsfiddle showing the problem:
https://jsfiddle.net/paranoidray/jLpzk374/22/
If you check out the jsfiddle and change line 93 and remove the clone() call.
Everything works again...
Any help would be very much appreciated.
Please clone gltf.scene like so:
model = SkeletonUtils.clone( gltf.scene );
Cloning of skinned meshes is not yet supported in the core. However, you can use SkeletonUtils.clone() to perform this task.
https://jsfiddle.net/yesxrq7g/
Related
I am using Three.js and I am loading an HDR as an environment map for the scene. Upon loading, I receive this error:
The line in questions is this:
I am assuming that the defined v1 causes an issue in this line because it is not undefined.
I am loading the HDR map like this:
return new Promise((resolve, reject) => {
new RGBELoader()
.setDataType(THREE.HalfFloatType)
.load(
path, // <-- hdr file
(texture) => {
// I tried fromEquirectangular and fromCubemap
// const envMap = this.pmremGenerator.fromEquirectangular(texture).texture;
const envMap = this.pmremGenerator.fromCubemap(texture).texture;
texture.needsUpdate = true;
resolve({ envMap });
},
undefined,
reject
);
});
Does anyone know what is causing this issue in THREE?
const envMap = this.pmremGenerator.fromCubemap(texture).texture;
I doubt this method call is correct. RGBELoader can not load textures in the cube map format. You probably want to use fromEquirectangular(). Before using this method, you need this line in your onLoad() callback:
texture.mapping = THREE.EquirectangularReflectionMapping;
Besides, please check if the usage of PMREMGenerator is actually necessary in your app. In latest releases, three.js internally uses PMREMGenerator to prepare environment maps for the usage with PBR materials.
I'm trying to get a threeJS Mesh from Autodek Forge objects using the function
'viewer.impl.getRenderProxy(viewer.model, fragId)'.
The problem that I encounter is if I put this function in a loop routine to get Meshs of multiple objects, I get just a random Mesh.
To find out the problem's origin, I used a similar function that is :
'viewer.impl.getFragmentProxy(viewer.model, fragId)'
and it worked just fine.
Her is the routine code that I use and the result :
for(let i = 0, len = nodNamee.length; i < (len); i = i+3){
var instanceTree = viewer.model.getData().instanceTree;
var fragIds = [];
instanceTree.enumNodeFragments(nodNamee[i+1], function(fragId){
fragIds.push(fragId);
});
fragIds.forEach(function(fragId) {
var renderProxy = viewer.impl.getRenderProxy(viewer.model, fragId);
fragtoMesh.push(renderProxy);
//var fragmentproxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
//fragtoProxy.push(fragmentproxy);
});
}
Result :
Arry of fragtoMesh
This is because the getFragmentProxy method always returns the same instance of THREE.Mesh, just with different properties. Basically, the method works like this under the hood:
let cachedMesh = new THREE.Mesh();
// ...
getRenderProxy(model, fragId) {
// Find the geometry, material, and other properties of the fragment
cachedMesh.geometry = fragGeometry;
cachedMesh.material = fragMaterial;
// ...
return cachedMesh;
}
// ...
Note that this is a performance optimization because if the getFragmentProxy (which is only meant for internal use) function returned a new instance every time it's called by other parts of Forge Viewer, it would cause a huge memory churn.
So in your case, if you really need to store all the THREE.Mesh instances in an array, you'll need to clone them or copy their individual properties into separate THREE.Mesh objects.
I am trying to load an external model using ObjectLoader. I am using the following code
loader.load( 'teapot.obj', function ( object ) {
globalobject=object;
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.map = texture;
console.log(child);
child.position.x = 3;
child.position.y = -6;
child.position.z = -17;
child.scale.x=.04;
child.scale.y=.04;
child.scale.z=.04;
child.name='tea';
scene.add( child );
}
});
But when I try to access this object in my render method using the following code it shows error
scene.getObjectByName('tea').rotation.z+=.01;
I saw using console that scene.getObjectByName('tea') is undefined
I can use all other standard Mesh objects using the above command but what is the problem with my object loaded using loader?
Can anyone help me to get the way?
If you have multiple childs in one obj file then append some number to differentiate between multiple mesh.
Then this should work:
scene.getObjectByName( "objectName" );
This answer may help
I have created a Blender model that uses an armature with bone constraints to animate the model. After exporting the model as a .fbx file and passing it through fbx-conv, my animation is split up into several animations.
Each animation ends up with an ID similar to "MyObject|MyAnimation".
In other words, I need to run all of these sub-animations at once to run my full animation.
I tried several AnimationController methods. First I tried calling AnimationController.setAnimation() for each of the animations, which doesn't work because it cancels the current animation each time it is called.
The AnimationController.animate() method sounds like it is supposed to do what I want, but I just get the same result as with .setAnimation().
Here is the code I tried:
instance = new ModelInstance( myModel );
controller = new AnimationController( instance );
for( Animation animation : instance.animations ) {
controller.animate( animation.id, 0 );
}
Is this not how .animate() is intended to work?
Also, I am not entirely certain of how to correctly use the second argument, transitionTime. Could that be the problem?
As Xoppa pointed out, the LibGDX docs on 3D Animations and Skinning says the following:
"If you want to apply multiple animations to the same ModelInstance, you can use multiple AnimationControllers, as long as they don't interfere with each other (don't affect the same nodes)."
Example:
ModelInstance myInstance = new ModelInstance( myModel );
AnimationController controllerOne = new AnimationController( myInstance );
AnimationController controllerTwo = new AnimationController( myInstance );
controllerOne.setAnimation( "FirstAnimationId", -1 );
controllerTwo.setAnimation( "SecondAnimationId", -1 );
Then in your render loop, you will also need to call .update(delta) on all of your AnimationControllers:
controllerOne.update( Gdx.graphics.getDeltaTime() );
controllerTwo.update( Gdx.graphics.getDeltaTime() );
I'm deply sory about ask this question again here. I know that the members os Stack Overflow are not for my exclusive
use but a realy need to find a solution to this problem.
Let me explain better because last time I was not that clear about what I wanted.
Iam using the THREE.JS to develop a RPG like game. What I have in mind is a game just like IronBane MMO but without
the web server function for now (just use for the single player).
I'm relative new to THREE.js and, in some point, I start to work in a library to handle the object loadings im
my level. Because I use the 3DStudio Max to make de models, I decide to use the OBJMTLLoader library provided.
I've nailed the function to load de static objects and its something like this.
function loadObject(obj,mtl,pos){ // Adiciona objeto sem vinculá-lo a uma variável
var loader = new THREE.OBJMTLLoader();
loader.load( obj, mtl, function ( object ) {
object.position.set(pos[0],pos[1],pos[2]);
scene.add( object );
});
}
The problem comes when I need to intance this object. I tried many things for example:
function addObject(obj,mtl){ // Declara e adiciona um objeto no mapa
var conteudo;
var loader = new THREE.OBJMTLLoader();
loader.load( obj,mtl, function( object ){
conteudo = object;
});
setTimeout(function(){
scene.add( conteudo );
},1000);
The conteudo variable came undefined of course. I understand then that I need to wait the object to load first. It
takes about 2 render cicles. For this I use then the setTimeout function. With the scene.add( conteudo ) the object
was sucessfuly added to the scene. I try then to use a
return conteudo;
and, when I call...
var objeto = new addObject('object path','material path')
I get a instance of addObject and not Object3D as I expected. I try also to declare a array outside de function and
push it from inside the addObject like this:
function addObject(obj,mtl,objectArray)
var loader = new THREE.OBJMTLLoader();
loader.load( obj,mtl, function( object ){
conteudo = object;
});
setTimeout(function(){
scene.add( conteudo );
objectArray.push( conteudo );
},1000);
In this second one when I console.log the array I get:
Array[1]
0 : THREE.Object3D
length : 1
but when I try to use Array[0] or console.log(Array.length) I get undefined and 0 respectivly.
I would realy appreciate if someone could help-me solve this one. That would be awesome. Thanks you!
consider waiting with adding the objects.
function init(next){
var loader = new THREE.OBJMTLLoader();
loader.load( obj, mtl, function ( object ) {
object.position.set(pos[0],pos[1],pos[2]);
conteudo = object;
next();
});
}
function next(){
scene.add( conteudo );
objectArray.push( conteudo );
console.log(objectArray)
... work from here, here you are sure that the model is loaded ...
}
init(next);
This waits until the object is loaded and then it will execute next.