Three.js Object3D division and custom coloring - javascript

I want to ask for some help with my project of temperature change on model. I'm using OBJLoader to load my model exported from autoCAD,
and I need to show temperature change on it by color change. I'm stuck on point, how to divide loaded object to smaller regions,
maybe set them some id and than set that region the particular color.
I will be grateful for any help or advice.
By now, I have this:
<body>
<div id="info">
three.js - Temperature model
</div>
<script src="../three.js-lib/build/three.min.js"></script>
<script src="../three.js-lib/examples/js/loaders/OBJLoader.js"></script>
<script src="../three.js-lib/examples/js/Detector.js"></script>
<script src="../three.js-lib/examples/js/controls/OrbitControls.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer;
var container;
init();
function init() {
container = document.getElementById("container");
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0x999999 ) );
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );
camera.up.set( 0, 0, 10 );
camera.position.set( 0, -150, 95 );
camera.add( new THREE.PointLight( 0xffffff, 0.8 ) );
scene.add( camera );
var grid = new THREE.GridHelper( 200, 10.0 );
grid.setColors( 0xffffff, 0x555555 );
grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
scene.add( grid );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0x999999 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//loader
loadModel();
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.target.set( 0, 1.2, 2 );
controls.update();
window.addEventListener( 'resize', onWindowResize, false );
}
function loadModel() {
var onProgress = function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function (xhr) {};
var manager = new THREE.LoadingManager();
manager.onProgress = function (item, loaded, total) {
console.log(item, loaded, total);
};
var loader = new THREE.OBJLoader(manager);
loader.load('temperature/suciastka.obj', function (object) {
object.traverse(function (child){
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshPhongMaterial({color: 0x451E0C, vertexColors: THREE.VertexColors});
}
})
scene.add(object);
render();
}, onProgress, onError);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>

Related

Rotate object with rotated parent in world space?

I'm using this function to rotate object Y axis in world space:
function rotateWorldYAxis( obj, angle ) {
quat.setFromAxisAngle( new THREE.Vector3(0,1,0), angle );
obj.quaternion.multiplyQuaternions(quat,obj.quaternion);
obj.updateMatrixWorld();
}
But it doesn't work with the object has rotated parent.
Here is example Fiddle:
Correct behavior when parent not rotated:
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container, stats;
var camera, scene, controls;
var renderer;
var quat = new THREE.Quaternion();
var axis = new THREE.Vector3();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// CAMERA
camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
camera.position.set( 0, 0, 500 );
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0xaaaaaa ) );
var light = new THREE.PointLight( 0xffffff );
light.position.set(100,100,100);
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.domElement.style.position = "relative";
container.appendChild( renderer.domElement );
//____________________________//
cube = new THREE.Mesh(
new THREE.CubeGeometry(50,100,50),
new THREE.MeshPhongMaterial()
);
cube.rotation.set(Math.PI/3, 0, 0);
cubeParent = new THREE.Object3D();
cubeParent.rotation.set(0,0,0) //Not rotated parent
cubeParent.add(cube)
scene.add(cubeParent)
//____________________________//
var grid = new THREE.Mesh(
new THREE.PlaneGeometry(200, 200, 10, 10),
new THREE.MeshBasicMaterial({wireframe: true})
)
grid.position.y = -100
grid.rotation.x = Math.PI/2
scene.add(grid);
window.addEventListener( 'resize', onWindowResize, false );
}
function rotateWorldYAxis( obj, angle ) {
quat.setFromAxisAngle( new THREE.Vector3(0,1,0), angle );
obj.quaternion.multiplyQuaternions(quat,obj.quaternion);
obj.updateMatrixWorld();
}
function animate() {
requestAnimationFrame( animate );
render();
rotateWorldYAxis(cube, 0.01)
}
function render() {
renderer.render( scene, camera );
}
function onWindowResize( event ) {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.js"></script>
<p style="position: fixed;z-index:1;top:0;text-align:center;color: #fff">This is correct behavior</p>
Wrong behavior when parent is rotated:
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container, stats;
var camera, scene, controls;
var renderer;
var quat = new THREE.Quaternion();
var axis = new THREE.Vector3();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// CAMERA
camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
camera.position.set( 0, 0, 500 );
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0xaaaaaa ) );
var light = new THREE.PointLight( 0xffffff );
light.position.set(100,100,100);
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.domElement.style.position = "relative";
container.appendChild( renderer.domElement );
//____________________________//
cube = new THREE.Mesh(
new THREE.CubeGeometry(50,100,50),
new THREE.MeshPhongMaterial()
);
cube.rotation.set(Math.PI/3, 0, 0);
cubeParent = new THREE.Object3D();
cubeParent.rotation.set(1,0,0) //Rotated parent
cubeParent.add(cube)
scene.add(cubeParent)
//____________________________//
var grid = new THREE.Mesh(
new THREE.PlaneGeometry(200, 200, 10, 10),
new THREE.MeshBasicMaterial({wireframe: true})
)
grid.position.y = -100
grid.rotation.x = Math.PI/2
scene.add(grid);
window.addEventListener( 'resize', onWindowResize, false );
}
function rotateWorldYAxis( obj, angle ) {
quat.setFromAxisAngle( new THREE.Vector3(0,1,0), angle );
obj.quaternion.multiplyQuaternions(quat,obj.quaternion);
obj.updateMatrixWorld();
}
function animate() {
requestAnimationFrame( animate );
render();
rotateWorldYAxis(cube, 0.01)
}
function render() {
renderer.render( scene, camera );
}
function onWindowResize( event ) {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.js"></script>
<p style="position: fixed;z-index:1;top:0;text-align:center;color: #fff">Parent rotate cause this wrong behavior, this cube need to rotates on Y world axis</p>
Any help is appreciated! Thank you!

Three.js OBJloader with OrbitControls

I need to do very simple 3d model viewer with rotation and so on..
I have simple code, everything works fine, but when I add these two rows with OrbitControls then there'S only blank page:
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
Whole code:
<body>
<script src="js/OrbitControls.js"></script>
<script src="js/three.min.js"></script>
<script src="js/OBJLoader.js"></script>
<div id="ahoj" style="width:1000px; height:700px">
</div>
<script>
var container;
var camera, controls, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = 1000 / 2;
var windowHalfY = 700 / 2;
init();
animate();
function init() {
container = document.getElementById('ahoj');
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, 1000 / 700, 1, 2000 );
camera.position.z = 200;
// scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x000 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 );
scene.add( directionalLight );
// texture
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
var texture = new THREE.Texture();
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete, 2) + '% downloaded' );
}
};
var onError = function ( xhr ) {
};
var loader = new THREE.ImageLoader( manager );
loader.load( 'textures/mapa1.png', function ( image ) {
texture.image = image;
texture.needsUpdate = true;
} );
// model
var loader = new THREE.OBJLoader( manager );
loader.load( 'obj/Immortal.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
//child.material.map = texture;
}
} );
object.scale.set(3,3,3);
object.position.y = 0;
object.position.z = 0;
object.position.x = 0;
scene.add( object );
}, onProgress, onError );
//
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
//controls = new THREE.OrbitControls( camera );
//controls.addEventListener( 'change', render );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( 1000, 700 );
container.appendChild( renderer.domElement )
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = 1000 / 2;
windowHalfY = 700 / 2;
camera.aspect = 1000 / 700;
camera.updateProjectionMatrix();
renderer.setSize( 1000, 700 );
}
function animate() {
render();
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
Any idea where is the problem?
I tried some few tutorials, but no one helped me..
You need to include three.min.js first:
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/OBJLoader.js"></script>

Var undefined when I use a loader in three.js

//Script loader
<script src="js/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/ColladaLoader.js" type="text/javascript"></script>
<script>
var loader = new THREE.ColladaLoader();
loader.load( 'texture/bigcube_hetre.dae', function ( collada ) {
window.cubeBigHetre = collada.scene;
var skin = collada.skins[ 0 ];
cubeBigHetre.position.set(0, 0, 0);
cubeBigHetre.scale.set(1, 1, 1);
});
var container;
var camera, scene, renderer;
var plane, cube;
var cubeExport;
init();
render();
function init() {
container = document.createElement( 'div' );
container.setAttribute("id", "container");
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 0, 2000 );
camera.lookAt( new THREE.Vector3() );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.damping = 0.2;
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
// grid
var size = 500, step = 50;
var geometry = new THREE.Geometry();
for ( var i = - size; i <= size; i += step ) {
geometry.vertices.push( new THREE.Vector3( - size, i, 0 ) );
geometry.vertices.push( new THREE.Vector3( size, i, 0 ) );
geometry.vertices.push( new THREE.Vector3( i, - size, 0 ) );
geometry.vertices.push( new THREE.Vector3( i, size, 0 ) );
}
var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2, transparent: true } );
var line = new THREE.Line( geometry, material, THREE.LinePieces );
scene.add( line );
//
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
var geometry = new THREE.PlaneBufferGeometry( 1000, 1000 );
plane = new THREE.Mesh( geometry );
plane.visible = false;
scene.add( plane );
// Lights
var ambientLight = new THREE.AmbientLight( 0x606060 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 1, 0.75, 0.5 ).normalize();
scene.add( directionalLight );
alert(cubeBigHetre);//Uncaught ReferenceError: cubeBigBrun is not defined
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() {
renderer.render( scene, camera );
}
</script>
Here is the code, and the problem comes from alert(cubeBigHetre);
It's working in Firefox and Internet Explorer but not with others. The error is : Uncaught ReferenceError: cubeBigBrun is not defined but not in firefox !
Cordialy Alexander
There is a race in your code:
loader.load(..., function)
will call the function when the resource becomes available. So when you call your init() function, the resource may be loaded, the loader callback called and your variable initialized, or the resource may be still downloading, the callback not yet called and your variable still not initialized. This code works by chance in IE and Firefox. Probably you are testing locally and/or experiencing minor differences in Javascript engines across the browsers.
You should move code that depends on the resource to be loaded from the init() function to the loader callback.
Thank you, I think you are true but i can't move it in the loader so I should add a setTimeout().

How to use EdgesHelper on imported Collada model in three.js

I'm trying to use EdgesHelper on loaded Collada model in three.js and having problems with:
applying edges to the whole model geometry,
misalignment and scale differences between the Collada model
and generated edges.
http://codepen.io/znak/pen/raqBLM?editors=001
var controls, scene, camera, renderer;
var light;
var dae, daeGeometry, daeMaterial, daeMesh, daeEdges;
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( 'http://www.lenart.pl/assets/codepen/FestoolClamp2.dae', function ( collada ) {
dae = collada.scene;
daeMaterial = new THREE.MeshBasicMaterial( { color: 0xaaaaaa } );
collada.scene.traverse( function ( child ) {
if ( child.material ) child.material = daeMaterial;
if ( child.geometry ) {
daeMesh = new THREE.Mesh( child.geometry, daeMaterial );
daeEdges = new THREE.EdgesHelper( daeMesh, 0x444444 );
}
} );
dae.updateMatrix();
init();
render();
} );
function init() {
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 150, -350 );
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
light = new THREE.DirectionalLight( 0xffffff, .75 );
light.position.set( 0, 1, -2 );
scene.add( light );
dae.add( daeEdges );
scene.add( dae );
dae.scale.x = dae.scale.y = dae.scale.z = 10;
renderer = new THREE.WebGLRenderer( { alpha: true, antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
animate();
}
function animate() {
requestAnimationFrame( animate );
dae.rotation.y += 0.002;
controls.update();
render();
}
function render() {
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
Any help would be appreciated.
Traverse the scene objects and add edges using EdgesHelper in the loader callback:
object3D.traverse(function(o){ if (o.type === "Mesh") {
var m = new THREE.EdgesHelper(o, 0x0);
m.matrixAutoUpdate = true;
m.matrix = o.matrix;
o.add(m);
} });
You should see outline on your imported dae models. I'm using this in one of my projects.

Three.js - VRML Loader

I'm trying to use the Three.js with VRML (WRL) models. What I am wondering is that the model is loaded with variations of colors (colored). How can I load the model in solid color as the original file?
My example is: http://dev.logicarts.com.br/semapro/projeto-3d/teste-1.html
The code:
<div id="info">
three.js -
vrml format loader test -
<!--model from VRML 2.0 Tutorial,-->
</div>
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/VRMLLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
camera.position.z = 6;
controls = new THREE.OrbitControls( camera );
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.noZoom = false;
controls.noPan = false;
scene = new THREE.Scene();
scene.add( camera );
// light
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( 200, 200, 1000 ).normalize();
camera.add( dirLight );
camera.add( dirLight.target );
var loader = new THREE.VRMLLoader();
loader.addEventListener( 'load', function ( event ) {
scene.add(event.content);
} );
loader.load( "3d/conjunto-carcaca.wrl" );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.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 );
controls.update();
renderer.render( scene, camera );
stats.update();
}
</script>
If you add this code under the scene.add(event.content); statement, all the objects in your scene will turn red.
scene.traverse (function (object)
{
if (object instanceof THREE.Mesh) {
object.material.color.setHex( 0xff0000 );
}
});

Categories