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.
Related
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 tried to import a 3D model but I'm not sure if i m doing in right way.
var loader = new THREE.GLTFLoader();
loader.load('./CesiumMilkTruck.gltf',
function (gltf) {
scene.add(gltf.scene);
gltf.animations;
gltf.scene;
gltf.scenes;
gltf.cameras;
gltf.asset;
},
function (xhr) {
console.log((xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function (error) {
console.log( 'An error happened = ', error );
}
);
my html is
<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/GLTFLoader.js"></script>
I download the model on this page :
link
in particular i download the three files:
CesiumMilkTruck.gltf
CesiumMilkTruck.png
CesiumMilkTruck0.bin
I had this errors:
An error happened = SyntaxError: "JSON.parse: unexpected character at
line 7 column 1 of the JSON data" parse
file:///C:/Users/an/Desktop/master/js/GLTFLoader.js:157
load file:///C:/Users/an/Desktop/master/js/GLTFLoader.js:75
load file:///C:/Users/an/Desktop/master/js/three.min.js:715
What I m wrong?
Sorry for my question, but is my first time with Threejs.
It's possible you have an issue with the GLTF model, perhaps corrupted?. The error message would lead me to believe that the formatting of the GLTF file is incorrect (it's all numerical).
Here is a code excerpt from my flight simulator I'm building with Threejs and Konva.js: https://github.com/mpaccione/everest_flight_sim
In the code below I load in a helicopter model, turn it wireframe, and add it to a group which contains the first person camera so it seems you are flying a helicopter.
I'm using commonJS modules with browserfy for this project.
const GLTFLoader = require('three-gltf-loader'),
miniModelLoader = new GLTFLoader();
// Load Helicopter Model
miniModelLoader.load( './src/models/helicopter/scene.gltf', function(gltf){
miniModel = gltf.scene;
miniModel.name = "miniHeli"
miniModel.rotation.y = -90 * Math.PI / 180; // Radians
miniModel.position.set( 0, 0, 0 );
let miniModelMesh = miniModel.children[0].children[0].children[0],
miniModelMeshArr = [ miniModelMesh.children[0], miniModelMesh.children[1], miniModelMesh.children[2] ];
for (var i = miniModelMeshArr.length - 1; i >= 0; i--) {
miniModelMeshArr[i].material.wireframe = true;
}
miniHeliGroup.add( miniModel );
} )
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.
with the loader bellow the obj and mtl files are loaded, so how can I access the material and make it doublesided?
If I use mtlLoader.setMaterialOptions({side: THREE.DoubleSide}) as in the following threejs.org documentation page, it doesn't work -and I'm not getting any hinting from VScode about the .setMaterialOptions either.
https://threejs.org/docs/#examples/loaders/MTLLoader
Here's the main part of the obj+mtl loader:
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'female02/' );
//mtlloader.setMaterialOptions(side:THREE.DoubleSide)
mtlLoader.load( 'female02.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'female02/' );
objLoader.load( 'female02.obj', function ( object ) {
object.position.set( 0, -95, 0 );
sceneRTT.add( object );
}, onProgress, onError );
});
[and I can't add the main keyword "doublesided" because I lack... reputation]
In MTLLoader.setMaterialOptions( options ), the options argument is an object, so you must pass it as such.
loader.setMaterialOptions( { side: THREE.DoubleSide } );
three.js r.89
Hi, I have a problem with webgl and using requestAnimationFrame, if i continue in debug the animation is fine but as soon as i let the script run freely i get an unresponsive script error from the browser
here is my html :
<!DOCTYPE html>
<html>
<head>
<title>Earth to WebGL</title>
<script type="text/javascript" src="../Rec/three.min.js"></script>
<script type="text/javascript" src="../Rec/jquery-1.6.4.js"></script>
<script type="text/javascript" src="../Rec/RequestAnimationFrame.js"></script>
<script type="text/javascript" src="ex_loop.js"></script>
<script type="text/javascript" src="Earth.js"></script>
<script>
var loopProg = null;
var renderer = null;
var scene = null;
var camera = null;
var mesh = null;
var earth = null;
$(document).ready(
function() {
var container = document.getElementById("container");
renderer = new THREE.WebGLRenderer({ antialias: true } );
renderer.setSize(container.offsetWidth,container.offsetHeight);
container.appendChild(renderer.domElement)
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45,
container.offsetWidth / container.offsetHeight, 1, 4000 );
earth = new Earth();
scene.add(earth.getEarth);
camera.position.set( 0, 0, 3 );
loopProg = new loopProgram();
loopProg.add(function(){earth.update()});
loopProg.add(function(){renderer.render( scene, camera );});
loopProg.solarLoop();
}
);
</script>
my earth script file
function Earth()
{
this.getEarth = init();
function init()
{
var map = {map:THREE.ImageUtils.loadTexture("images/earth_surface_2048.jpg")};
var material = new THREE.MeshBasicMaterial(map);
var geometry = new THREE.SphereGeometry(1,32,32);
return new THREE.Mesh(geometry, material);
}
this.update = function()
{
this.getEarth.rotation.x += .01;
}
return this;
}
and the loop code :
function loopProgram()
{
this.functionsToRun = new Array();
this.solarLoop= function()
{
jQuery.each(this.functionsToRun, function(index,value)
{
value ? value() : null;
});
var loopRef = this;
requestAnimationFrame(loopRef.solarLoop());
}
this.add = function(func)
{
this.functionsToRun[this.functionsToRun.length] = func;
}
}
You're calling solarLoop recursively instead of passing just the callback function:
requestAnimationFrame(loopRef.solarLoop());
should be
requestAnimationFrame(loopRef.solarLoop);