this.loadMyModel = function(){
const loader2 = new THREE.GLTFLoader();
// Load a glTF resource
loader2.load(
// resource URL
'Duck.gltf',
// called when the resource is loaded
function ( gltf ) {
//alert('success');
this.scene.add( gltf.scene );
})
};
The js files have been included.
I got an error, but I don't know why:
TypeError:undefined is not an object (evaluating 'this,scene.add')
Inside of your callback function, this is not the same as outside of the function. For more information on how this works in JS, I'd suggest this article: http://www.digital-web.com/articles/scope_in_javascript/
To fix the issue, you should save a reference to the scene outside the callback:
var scene = this.scene;
this.loadMyModel = function () {
// ...
loader.load( 'foo.glb', function ( gltf ) {
scene.add( gltf.scene );
} );
}
Alternatively, using newer JS features like arrow functions will also get around this problem.
Related
I want to load a model in my scene, and the loading works well, but I want to keep a reference to it, so I can edit position and other variables later.
As you can see by the naming, the model is a boat. (not that that matters a whole bunch)
When I write the code like this it works, and I can edit the scale of the model:
function Boat(scene, loader) {
var boatObject;
this.SpawnBoat = function() {
loader.load('resources/SimpleBoat.gltf', handleLoad,
undefined, function (error) {
console.error(error);
});
}
function handleLoad(gltf) {
boatObject = gltf.scene;
scene.add(boatObject);
boatObject.scale.set(0.1,0.1,0.1);
} }
However, when I want to edit the variable after it's been loaded it says the variable is "undefined" and won't run the code.
function Boat(scene, loader) {
var boatObject;
this.SpawnBoat = function() {
loader.load('resources/SimpleBoat.gltf', handleLoad,
undefined, function (error) {
console.error(error);
});
boatObject.scale.set(0.1,0.1,0.1);
}
function handleLoad(gltf) {
boatObject = gltf.scene;
scene.add(boatObject);
} }
The boat function is called as followed, in a module that has reference to Three.js and GLTFLoader
const loader = new GLTFLoader();
const boat = new Boat(scene, loader);
const boatModel = boat.SpawnBoat();
Is there a way I can keep reference to the loaded model so I can edit proporties later?
been stuck for hours trying to figure out how to make my 3d model spin like a coin spinning. my code is below anything help i really appreciate you guys.
// add a light
const light = new THREE.AmbientLight(0xffffff,5)
scene.add(light);
// controls
// load object
const loader = new THREE.GLTFLoader();
loader.load('yattee.gltf', function (gltf) {
scene.add(gltf.scene);
})
const render = function() {
requestAnimationFrame(render)
// camera.rotation.z += .0010
renderer.render(scene, camera);
}
render();
Try it like so:
let myModel;
const loader = new GLTFLoader();
loader.load( 'model.gltf', function ( gltf ) {
myModel = gltf.scene;
scene.add( myModel );
} );
const render = function() {
requestAnimationFrame(render)
if ( myModel ) {
myModel.rotation.z += 0.01;
}
renderer.render(scene, camera);
}
The problem is, you are defining the model gltf inside a function, which means that it cannot be accessed from render(). In order to spin the model, you need to define the variable gltf prior to loading the model, so it can be stored inside of it:
const loader = new THREE.GLTFLoader();
var gltf; //By defining it prior to loading, it is now in global scope.
loader.load('yattee.gltf', function (gltf) {
scene.add(gltf.scene);
})
Then, you can add the flipping effect in the render() loop. Make sure that you add the given if statement so it doesn't crash before the model even loads!
const render = function() {
requestAnimationFrame(render);
if(gltf) {
gltf.rotation.z += .0010; //Make sure you rotate the gltf, not the camera.
}
renderer.render(scene, camera);
}
And that should do it!
Note: I've taken a look at some of the other answers, and it seems like they either don't work, or they don't explain what they are doing properly. I think that this should help you achieve what you want.
I've been hitting myself overhead with this one for the good three hours now..
My question is, would someone be kind enough to reorganize my example in such a way, that the object that I load comes with a color, any color
var loader = new THREE.OBJLoader()
loader.load( 'learning/exported1.obj', function ( object )
{
object.traverse( function (child)
{
if ( child instanceof THREE.Mesh )
{
child.material.color.setHex( 0xffffff );
}
}
var OBJBoundingBox = new THREE.Box3().setFromObject(object);
OBJBoundingBox.center(object.position);
object.position.multiplyScalar(-1);
object.position.x = object.position.x;
object.position.y = object.position.y;
object.position.z = object.position.z;
scene.add( object );
}, onProgress, onError );
If I throw the traverse part away the object is loaded successfully but is a simple white color, with it, the object does not appear on my screen...
<script src="../build/three.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/SMAAShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/SMAAPass.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
These are my imports in case you think the problem lies in here
Thanks so much in advance, this is a project which I'm developing independently and would love it if I can get it working!
I feel like an idiot but the thing I was missing was
);
at the end of object.traverse function
var loader = new THREE.OBJLoader()
loader.load( 'learning/exported1.obj', function ( object )
{
object.traverse( function (child)
{
if ( child instanceof THREE.Mesh )
{
child.material.color.setHex( 0xffffff );
}
});
// ^This over here^
var OBJBoundingBox = new THREE.Box3().setFromObject(object);
OBJBoundingBox.center(object.position);
object.position.multiplyScalar(-1);
object.position.x = object.position.x;
object.position.y = object.position.y;
object.position.z = object.position.z;
scene.add( object );
}, onProgress, onError );
Assigning a material now works perfectly with this code.
I try to use Jasmine to automatically test some functionality. The issue I have is that I want to test a class and for that need to load a geometry for all related tests. However due to asynchronous loading at time of execution of the tests the geometry has not been loaded and is undefined and thus test cases fail. Any idea how to make sure the geometry is loaded at time of test execution? Here the snipet to load the geometry
describe("Model Class", function() {
var geometry;
beforeAll(function() {
var loader = new THREE.STLLoader();
loader.load( '../tests/testdata/cube_big.stl', function ( geo ) {
geometry = geo;
});
});
I believe the beforeAll() function takes one argument that you can call when async operations are complete:
beforeAll(function(done) {
var loader = new THREE.STLLoader();
loader.load( '../tests/testdata/cube_big.stl', function ( geo ) {
geometry = geo;
done();
});
});
Does anybody knows how can i acess a object outside a OBJMTLLoader
var loader = new THREE.OBJMTLLoader();
loader.load( obj, mtl, function ( object ) {
object.position.set(0,0,0);
scene.add( object );
});
console.log(object);
inside of the function objects = THREE.Object3D but outside is equal do ObjectLoad.
Thanks for everybody.
The object is simply inside the scope of the undefined function.
Set the function to return the object
var loader = new THREE.OBJMTLLoader();
loader.load( obj, mtl, function ( object ) {
object.position.set(0,0,0);
return object;//here
});
scene.add( object );
console.log(object);