I am trying to create my first glTF model in Three.js rendered from Blender and I can not get the camera to display close to the rendered model.
No matter what I do to the Blender camera nothing fixes the problem so it must be the code that has been written in Three.js. Please help! Thx
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webglTF - loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a {
color: #046;
font-weight: bold;
}
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/libs/inflate.min.js"></script>
<script src="js/loaders/GLTFLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/WebGL.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var container, stats, controls;
var camera, scene, renderer, light;
var clock = new THREE.Clock();
var mixers = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth /
window.innerHeight, 1, 2000 );
camera.position.set( -400, 0, 200 );
controls = new THREE.OrbitControls( camera );
controls.target.set( 0, 0, 0 );
controls.update();
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = -100;
light.shadow.camera.left = -120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera )
);
// ground
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry(
2000, 2000 ), new THREE.MeshPhongMaterial( { material:
0x999999, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000
);
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// model
var loader = new THREE.GLTFLoader();
loader.load( '../The-Raisin/TREE_GLTF.gltf', function ( gltf)
{
scene.add( gltf.scene );
}, undefined, function ( error ) {
console.error( error );
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// stats
stats = new Stats();
container.appendChild( stats.dom );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
if ( mixers.length > 0 ) {
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() );
}
}
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
Camera is displayed outside of scene.
No matter what I do to the Blender camera nothing fixes the problem
Changing the camera properties in Blender has not effect if you define an own camera object in your application. You have two options:
Access gltf.cameras in your onLoad() callback which represents an array of cameras defined in the glTF asset. If the camera from Blender is exported, you should find it right there.
Improve the parameters of the camera defined in your application with an approach similar to 3D viewers. You usually center your object first and then derive optimal camera parameters from the object's AABB. Try to use the following code from this three.js based glTF viewer:
https://github.com/donmccurdy/three-gltf-viewer/blob/18f43073bbfdbd3c220e2059e548e74c507522d2/src/viewer.js#L218-L246
three.js R104
Related
I am trying to change the color of 3D object where intersected using color picker.I am trying with dat.gui.I want to change the color of 3d part where it gets clicked and change the selected from the colorPicker.I tried out some possible ways but it doesn't work out.Please,refer to the code I tried out. Help me out with some solution and draw my attention to where I am getting wrong. Thanks.
<!DOCTYPE html>
<html lang="en">
<head>
<title>color</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script src="Detector.js"></script>
<script src="stats.min.js"></script>
<script src="loaders/MTLLoader.js"></script>
<script src="loaders/OBJLoader.js"></script>
<script type='text/javascript' src='DAT.GUI.min.js'></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,effectController;
var raycaster;
var objects = [];
var selectedObject,selectedPos;
var rotation;
var pos,quat;
var INTERSECTED;
var guiColor;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 15;
controls = new THREE.OrbitControls( camera );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x555000 );
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 mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl('assets/'); mtlLoader.setPath('assets/'); mtlLoader.load('anno.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('anno.obj', function (object) {
scene.add( object );
objects.push( object );
});
});
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
/* Controls */
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
raycaster = new THREE.Raycaster();
gui = new dat.GUI();
parameters =
{
color: "#ff0000",
};
gui.add( parameters, 'reset' ).name("Reset");
guiColor = gui.addColor( parameters, 'color' ).name('Color');
container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener("click", onclick, false);
}
var mouse = new THREE.Vector2();
function onclick(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects, true);
if (intersects.length > 0) {
INTERSECTED = intersects[0].object;
if ( INTERSECTED && INTERSECTED.material.emissive != null ){
guiColor.onChange(function(){
INTERSECTED.material.emissive.setHex(parameters.color)
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
I've create a little live demo with your code and a basic working solution. I'd like to highlight three important changes:
You can use the onChange() event handler in order to know when a certain dat.gui property has changed. The demo uses this feature to update the color of a selected object.
I have refactored your raycasting logic into something more simple. I've seen you've copied some code from the official three.js examples but the new code should be sufficient for your case. Besides, it's also better to update Material.color instead of Material.emissive.
If you set OrbitControls.enableDamping to true, you have to update the controls in your animation loop.
https://jsfiddle.net/btuzd23o/2/
three.js R103
i tried to import 3d model in .dae format in three js like below i am able to import it properly but i can not see textures for that model even thought i have textures folder and no error related to that. so i added one function using my function (switchtexture()) by passing object of child and matching the name of child i can give assign texture but no success can someone tell me where i am doing wrong ? is this right way or not
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - collada - skinning</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background: #777;
padding: 0;
margin: 0;
font-weight: bold;
overflow: hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
}
a {
color: #ffffff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js webgl - collada - skinning
</div>
<script src="js/three.js"></script>
<script src="js/ColladaLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats, clock;
var camera, scene, renderer, mixer;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( - 7, 4, 7 );
scene = new THREE.Scene();
clock = new THREE.Clock();
// collada
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load("./wolf/Wolf_dae.dae", function (collada) {
var object = collada.scene;
mixer = new THREE.AnimationMixer( object );
object.traverse( function ( child ) {
switchTexture(child);
if ( child instanceof THREE.SkinnedMesh ) {
var clip = THREE.AnimationClip.parseAnimation( child.geometry.animation, child.geometry.bones );
mixer.clipAction( clip, child ).play();
}
} );
object.scale.set(1,1,1);
object.position.set(0, 0, 0);
object.rotateX(- Math.PI/2);
scene.add( object );
} );
//
var gridHelper = new THREE.GridHelper( 5, 20 );
scene.add( gridHelper );
//
var ambientLight = new THREE.AmbientLight( 0xcccccc );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( -1, 0.5, -1 ).normalize();
scene.add( directionalLight );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild( renderer.domElement );
//
controls = new THREE.OrbitControls( camera, renderer.domElement );
//
stats = new Stats();
container.appendChild( stats.dom );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function switchTexture(obj) {
// for Textures
var imageDir = './wolf/textures/';
var images = {
"Wolf_obj_fur": imageDir + 'Wolf_Fur.jpg'
};
for (var prop in images) {
if (obj.name == prop) {
obj.children[0].material.map = THREE.ImageUtils.loadTexture(images[prop], {}, function () {
// add callback here if you want
});
}
}
}
function render() {
var delta = clock.getDelta();
if ( mixer !== undefined ) {
mixer.update( delta );
}
renderer.render( scene, camera );
}
</script>
</body>
</html>
here is the jiddle to see the code
https://jsfiddle.net/saisoft00/jv7rnos2/
and i downloaded the 3d model from this
https://free3d.com/3d-model/wolf-rigged-and-game-ready-42808.html
Try using THREE.MeshStandardMaterial for the mesh materials.
Your switchTexture will look something like this:
function switchTexture(obj) {
// for Textures
var imageDir = './wolf/textures/';
var images = {
"Wolf_obj_fur": imageDir + 'Wolf_Fur.jpg'
};
for (var prop in images) {
var material = new THREE.MeshStandardMaterial( {
map: new THREE.TextureLoader().load(images[prop])
});
if (obj.name == prop) {
obj.children[0].material = material;
}
}
}
You should also move from ImageUtils to TextureLoader, ImageUtils was deprecated.
I am trying to rotate a model on a plane geometry that represents a hill. I use the following code. My problem is that though the model see to have the correct rotation when start animating and is parallel to the face it is moving when getting near and overcoming the point(0,0,0) it is rotating weirdly. Maybe the problem that I have set the up of the model to be the vector(0,0,1) (you can copy paste to an editor and view the example on your browser):
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - trackball controls</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - trackball controls example</br>
MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
</div>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,mesh,animation,morph;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
// world
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(100,100,2,2);
var material = new THREE.MeshPhongMaterial({color: 0xff0000,side:THREE.DoubleSide,
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1});
var vertices = geometry.attributes.position.array;
vertices[ 14 ] =10;
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
// wireframe
var helper1 = new THREE.WireframeHelper( mesh, 0x000000 ); // or THREE.WireframeHelper
helper1.material.linewidth = 2;
scene.add( helper1 );
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
//
render();
}
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( 0, 0, -20 ),
new THREE.Vector3( 0, 0, 20 )
);
var helper = new THREE.Line( geometry, material );
scene.add( helper );
//////////
var loader = new THREE.JSONLoader( true );
loader.load( "http://threejs.org/examples/models/animated/horse.js", function( geometry ) {
morph = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x606060, morphTargets: true } ) );
morph.scale.set( 0.02, 0.02, 0.02 );
//morph.rotation.set(Math.PI/2,Math.PI/2+Math.PI/4,0);//rotate to look at the direction moving.
morph.position.set(-50,-50,0);
scene.add( morph );
animation = new THREE.MorphAnimation( morph );
animation.play();
} );
/////////
//raycaster function
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove( event ) {
mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
// See if the ray from the camera into the world hits one of our meshes
var intersects = raycaster.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersects.length > 0 ) {
helper.position.set( 0, 0, 0 );
helper.lookAt( intersects[ 0 ].face.normal );
document.body.style.cursor = "crosshair";
helper.position.copy( intersects[ 0 ].point );
render();
}
else{document.body.style.cursor = "auto";}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
var prevTime = Date.now();
function render() {
if ( animation ) {
var time = Date.now();
animation.update( time - prevTime );
prevTime = time;
}
if(morph){
if(morph.position.x>50){morph.position.x=-50;morph.position.y = -50;}
morph.position.x+=0.3;
morph.position.y+=0.3;
var help = helper.clone();
help.position.set(morph.position.x,morph.position.y,-10);
var ray= new THREE.Raycaster();
ray.set(help.position,new THREE.Vector3(0,0,1).normalize());
var intersect = ray.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersect.length > 0 ) {
morph.up.set(0,0,1);
morph.position.copy( intersect[ 0 ].point );
morph.lookAt( intersect[ 0 ].face.normal );
}
}
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
Any ideas to keep the models rotation parallel to the face it is on?
Similar question with this one that has no answer.
i have take the code above and after playing with it for a while was able to get the effect you were going for but maybe not the way that answers your question... here is what i have found anyway... and another note i think i was working with the code that was first posted..
so it's been a long time scene i have dealt with 3d code (2001-2002 time frame) so my knowledge may be both rusty and out of date with newer trends. plus i am new to this frame work.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - trackball controls</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - trackball controls example</br>
MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
</div>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,mesh,animation,morph;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
// world
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(100,100,2,2);
var material = new THREE.MeshPhongMaterial({color: 0xff0000,side:THREE.DoubleSide,
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1});
var vertices = geometry.attributes.position.array;
vertices[ 14 ] =10;
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
// wireframe
var helper1 = new THREE.WireframeHelper( mesh, 0x000000 ); // or THREE.WireframeHelper
helper1.material.linewidth = 2;
scene.add( helper1 );
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
//
render();
}
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( 0, 0, -20 ),
new THREE.Vector3( 0, 0, 20 )
);
var helper = new THREE.Line( geometry, material );
scene.add( helper );
//////////
var loader = new THREE.JSONLoader( true );
loader.load( "http://threejs.org/examples/models/animated/horse.js", function( geometry ) {
morph = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x606060, morphTargets: true } ) );
morph.scale.set( 0.02, 0.02, 0.02 );
//morph.rotation.set(Math.PI/2,Math.PI/2+Math.PI/4,0);//rotate to look at the direction moving.
morph.position.set(-50,-50,0);
scene.add( morph );
animation = new THREE.MorphAnimation( morph );
animation.play();
} );
/////////
//raycaster function
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove( event ) {
mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
// See if the ray from the camera into the world hits one of our meshes
var intersects = raycaster.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersects.length > 0 ) {
helper.position.set( 0, 0, 0 );
helper.lookAt( intersects[ 0 ].face.normal );
document.body.style.cursor = "crosshair";
helper.position.copy( intersects[ 0 ].point );
render();
}
else{document.body.style.cursor = "auto";}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
var prevTime = Date.now();
function render() {
var DelX,DelY,DelZ,LastZ;
DelX=0.3;DelY=0.3;
if ( animation ) {
var time = Date.now();
animation.update( time - prevTime );
prevTime = time;
}
if(morph){
LastZ=morph.position.z;
if(morph.position.x>50){morph.position.x=-50;morph.position.y = -50.1;}
morph.position.x+=DelX;
morph.position.y+=DelY;
var help = helper.clone();
help.position.set(morph.position.x,morph.position.y,-10);
var ray= new THREE.Raycaster();
ray.set(help.position,new THREE.Vector3(0,0,1).normalize());
var intersect = ray.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersect.length > 0 ) {
morph.up.set(0,0,1);
morph.position.copy( intersect[ 0 ].point );
DelZ=morph.position.z-LastZ;
var PointToLookat = new THREE.Vector3(morph.position.x+DelX,morph.position.y+DelY,morph.position.z+DelZ);
morph.lookAt( PointToLookat );
// old morph.lookAt( intersect[ 0 ].face.normal );
}
}
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
so basically your LookAt is "pointing" the horse at some point in 3d space at first i assumed it was a vector direction and maybe that what you were assuming too, i at least was wrong, so you have to put your point "in front" of the current position of the object. i added some delta vars and kept track of the lastZ position value (as i write this i realized i could have used a vector for that) so i found the "next spot" the object will be at and used that as the PointToLookat.
I was able to make a donut with Three.js using THREE.TorusGeometry. But I can't get it to look like a flat ring like the ones in these pictures:
http://www.google.com/imgres?imgurl=http://www.titanjewellery.co.uk/Mens/TI21-Titanium-8mm-Flat-Brushed-Ring.jpg&imgrefurl=http://www.titanjewellery.co.uk/Mens/8mm-Brushed-Titanium-Flat-Ring.html&h=301&w=232&sz=16&tbnid=LCN7eQuo2wyG_M:&tbnh=90&tbnw=69&zoom=1&usg=__3vayMvDy26tsj2hwvCK9SsYwVwY=&docid=ZMdcBBBQOzMSoM&sa=X&ei=pEhsUeL4FKWJiAKCzIHYCQ&ved=0CEAQ9QEwBA&dur=1660
Here's what my donut looks like:
Is there another Three.js geometry that can generate a flat ring (right with flat inner and outer walls)? Or another way of going about this?
Thanks for any pointers you can share! :)
Update:
The code and dependencies were taken from:
http://mrdoob.github.io/three.js/examples/misc_controls_trackball.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - trackball controls</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - trackball controls example</br>MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
</div>
<script src="three.min.js"></script>
<script src="TrackballControls.js"></script>
<script src="Detector.js"></script>
<script src="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, 1, 1000 );
camera.position.z = 500;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
// world
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
var radius = 100;
var tubeRadius = 50;
var radialSegments = 8 * 10;
var tubularSegments = 6 * 15;
var arc = Math.PI * 2;
var geometry = new THREE.TorusGeometry( radius, tubeRadius, radialSegments, tubularSegments, arc );
var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } );
for ( var i = 0; i < 1; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
}
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
http://jsfiddle.net/alininja/b4qGx/1/
There are multiple options:
Use TubeGeometry - this is probably what you need
ExtrudeGeometry to extrude a disk
lathe an offset rectangle with LatheGeometry
Use THREE.Shape -> grab the tube like shape from the webgl_geometry_shapes sample
You can use the RingGeometry function. The following code adds to the scene a full (between 0 and 360 degrees) wireframed red ring of inner radius equals to 10 and outer radio equals to 20. You can play with the other indicated variables to adjust the aspect of the disc you want to generate ()
var geometry = new THREE.RingGeometry(10, 20, thetaSegments, phiSegments, 0, Math.PI * 2);
var ring = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true}));
ring.position.set(25, 30, 0);
scene.add(ring);
Check this code!
var geometry = new THREE.TorusGeometry( 3, 0.5, 20, 2999 );
ring1 = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true}));
scene.add(ring1);
I created a 3D model in Blender.
I exported it with the exporter and the convert_obj_three.py (both did export fine, but did not show in the browser, with the code below).
I used the code below html/js from here:
http://dev.opera.com/articles/view/porting-3d-graphics-to-the-web-webgl-intro-part-2/
The original demo/any other three.js example from the site works fine in Firefox (Mac OS X 10.6.8, AMD Radeon HD 6490M).
All other browser seem to have a problem.
Interestingly if I run a simple:
python -m SimpleHTTPServer 8888
from any example directory and want to look at it via Firefox, it does not work/render either.
I always get the background color and the text, but no rendering.
And all required three .js are in the same directory.
Am I missing something or is this just random ?
How can I display a simple 3D model, that can be rotated by the user ?
Is this code correct ?
Thx.
<!doctype html>
<html lang="en">
<head>
<title>WebGL made easy</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background:#fff;
padding:0;
margin:0;
overflow:hidden;
font-family:'trebuchet ms', 'lucida grande', 'lucida sans unicode', arial, helvetica, sans-serif;
text-align:center;
}
canvas { pointer-events:none; z-index:10; }
p { font-size: small;}
</style>
</head>
<body>
<script src="Three.js"></script>
<script src="Detector.js"></script>
<script src="RequestAnimationFrame.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var FLOOR = 0;
var container;
var camera, scene;
var webglRenderer;
var zmesh, geometry;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// camera
camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 );
camera.position.z = 75;
//scene
scene = new THREE.Scene();
// lights
var ambient = new THREE.AmbientLight( 0xffffff );
scene.add( ambient );
// more lights
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, -70, 100 ).normalize();
scene.add( directionalLight );
// renderer
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
webglRenderer.domElement.style.position = "relative";
container.appendChild( webglRenderer.domElement );
// loader
var loader = new THREE.JSONLoader(),
callbackModel = function( geometry ) { createScene( geometry, 90, FLOOR, -50, 105 ) };
loader.load( { model: "mymodel.js", callback: callbackModel } );
}
function createScene( geometry, x, y, z, b ) {
zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
zmesh.position.set( 0, 16, 0 );
zmesh.scale.set( 1, 1, 1 );
scene.add( zmesh );
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
zmesh.rotation.set(-mouseY/500 + 1, -mouseX/200, 0);
webglRenderer.render( scene, camera );
}
</script>
</body>
</html>
I've tested your code and the issue lies with your loader callback functionality. Try this instead:
var loader = new THREE.JSONLoader(),
callbackModel = function(geometry, materials) { createScene( geometry, materials, 90, FLOOR, -50, 105 ) };
loader.load( "cubeHelper.js", callbackModel );
Notice the addition of the materials parameter, and of course add materials to the function parameters for createScene like so:
function createScene( geometry, materials, x, y, z, b ) {
zmesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( {color: 0xff0000 } ) );
zmesh.position.set( 0, 16, 0 );
zmesh.scale.set( 1, 1, 1 );
scene.add( zmesh );
}
Notice that I change MeshFaceMaterial to MeshBasicMaterial this is because MeshFaceMaterial needs and array of materials like that coming into the createScene, so when your ready you can create a material from the incoming materials and apply at that point. But that will get you going.