Three.js, Macintosh Display 3D Model - three.js

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.

Related

The marker is not showing

I'm trying to add markers to rotating globe object with Three.js - the globe is showing, but the markers is not displayed. I don't know why this happens, the console.log dont throw any errors to debug anything.
Can someone help me find the root to this issue and correct it?
The code inside the index.html file is down below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src="js/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
</head>
<body>
<div id="threejs" style="position: absolute; left:0px; top:0px"></div>
<script>
var boards = [];
var texture = [];
var matTexture = [];
var camera, scene, renderer, controls, container, materialBoard, boardGeo,materialSph, sphGeo, sphere,picGeo;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 300000 );
scene.add( camera );
camera.position.set( 0, 1500, 5000);
renderer = new THREE.WebGLRenderer( { antialias:true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xeeeeee );
container = document.getElementById( 'threejs' );
container.appendChild( renderer.domElement );
controls = new THREE.OrbitControls( camera, renderer.domElement );
var loader = new THREE.TextureLoader();
texture[0] = loader.load( "test.png" );
matTexture[0] = new THREE.MeshBasicMaterial( { color:0xffffff, map: texture[0], transparent:true, opacity:1, wireframe:false} );
// ball
materialSph = new THREE.MeshBasicMaterial( { color: 0x0099dd, transparent: true, opacity: 0.8, wireframe:false } );
sphGeo = new THREE.SphereGeometry(1200, 8, 8);
sphere = new THREE.Mesh( sphGeo, materialSph );
scene.add( sphere );
// board for some things
materialBoard = new THREE.MeshBasicMaterial({color:0xdddddd, transparent:true, opacity:0.4, wireframe: true });
boardGeo = new THREE.PlaneGeometry(500,500);
picGeo = new THREE.PlaneGeometry( 500, 500 );
const vertices = sphGeo.attributes.position.array;
console.log(vertices);
var board = new THREE.Mesh( boardGeo, materialBoard ); // board for pictures etc.
var pic = new THREE.Mesh( picGeo, matTexture[ 0 ] );
board.add( pic ) ; // add picture to the board
boards.push( board );
scene.add( boards[ 0 ] );
boards[ 0 ].position.set( 1 * vertices[ 10 ].x , 0.5 * vertices[ 2 ].y, 1.8 * vertices[ 10 ].z );
}
function animate() {
requestAnimationFrame( animate );
for( var n = 0; n < boards.length; n ++ ) {
//boards[ n ].lookAt( camera.position );
boards[ n ].quaternion.copy( camera.quaternion );
}
renderer.render( scene, camera );
controls.update();
}
</script>
</body>
</html>

Why is my camera so far from rendered model?

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

Draw a line from the camera position to the origin

Using threejs, I'm trying to draw a line from the camera position to the origin.
I expect that the line will always point to the middle of the screen (assuming that the renedered scene is viewed from the camera origin)
but it does not (the line always points towards the side of the screen).
The code below is a subset of the formal threejs webgl_geometry_extrude_shapes.html example.
I added the function draw_line_from_camera_to_origin(scene, camera)
What am I doing wrong?
Thanks,
Avner
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - geometry - extrude shapes</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: #222;
margin: 0px;
overflow: hidden;
}
a {
color: #f80;
}
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script>
var container;
var camera, scene, renderer, controls;
init();
animate();
function draw_line_from_camera_to_origin(scene, camera)
{
// Draw line from camera to origin
var pointA2 = new THREE.Vector3( camera.position.x, camera.position.y, camera.position.z );
var pointB2 = new THREE.Vector3( 0, 0, 0 );
var geometry2 = new THREE.Geometry();
geometry2.vertices.push( pointA2 );
geometry2.vertices.push( pointB2 );
var material2 = new THREE.LineBasicMaterial( { color : 'yellow' } );
var line2 = new THREE.Line( geometry2, material2 );
scene.add( line2 );
}
function init() {
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.color = '#fff';
info.style.link = '#f80';
info.innerHTML = 'three.js webgl - geometry extrude shapes';
document.body.appendChild( info );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x222222 );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, 500 );
controls = new THREE.TrackballControls( camera, renderer.domElement );
controls.minDistance = 200;
controls.maxDistance = 500;
scene.add( new THREE.AmbientLight( 0x222222 ) );
var light = new THREE.PointLight( 0xffffff );
light.position.copy( camera.position );
scene.add( light );
//
var closedSpline = new THREE.CatmullRomCurve3( [
new THREE.Vector3( -60, -100, 60 ),
new THREE.Vector3( -60, 20, 60 ),
new THREE.Vector3( -60, 120, 60 ),
new THREE.Vector3( 60, 20, -60 ),
new THREE.Vector3( 60, -100, -60 )
] );
closedSpline.curveType = 'catmullrom';
closedSpline.closed = true;
var extrudeSettings = {
steps : 100,
bevelEnabled : false,
extrudePath : closedSpline
};
var pts = [], count = 3;
for ( var i = 0; i < count; i ++ ) {
var l = 20;
var a = 2 * i / count * Math.PI;
pts.push( new THREE.Vector2 ( Math.cos( a ) * l, Math.sin( a ) * l ) );
}
var shape = new THREE.Shape( pts );
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var material = new THREE.MeshLambertMaterial( { color: 0xb00000, wireframe: false } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
draw_line_from_camera_to_origin(scene, camera);
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>
You need to update the location of the other point.
When you first create the line you tell it a point in space and it never moves from there. It may seem like its moving around but thats just because it is a very long line.
So you need to make geometry2 a global variable (at the top):
var camera, scene, renderer, controls, geomerty2;
Then remove var when you declare geometry2 in draw_line_from_camera_to_origin
Then your animation loop should be:
function animate() {
geometry2.vertices[0].x = camera.position.x;
geometry2.vertices[0].y = camera.position.y;
geometry2.vertices[0].z = camera.position.z;
geometry2.verticesNeedUpdate = true;
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
Now when you move the camera you see the line move with it then drift back to the camera's position. I'm not sure why it does that, I was actually expecting the line to be invisible (because lines have 0 width, and its pointing directly at the camera).
But anyways, happy coding haha hello world 42

Rotate a moving model to be parallel on a plane geometry

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.

How to make a flat ring in Three.js?

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);

Resources