How to make a flat ring in Three.js? - 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);

Related

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

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.

three.js set background image

How to create a static background image?
For default background:
scene = new THREE.Scene();
// ...
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );
How to set a image for scene.fog, or set opacity for clearcolor?
If you are trying to set a static background image (even if you rotate your main camera, the background doesn't change), you have to create 2 scenes and 2 cameras.
The first scene will be composed of a basic plane on which a texture is applied.
The second scene will have all your objects.
Here is a code that would do it :
<html>
<body>
<script src="Three.js"></script>
<script>
var color = 0x000000;
// Create your main scene
var scene = new THREE.Scene();
// Create your main camera
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// Create lights
var light = new THREE.PointLight(0xEEEEEE);
light.position.set(20, 0, 20);
scene.add(light);
var lightAmb = new THREE.AmbientLight(0x777777);
scene.add(lightAmb);
// Create your renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a cube
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({
color: 0xff00ff,
ambient: 0x121212,
emissive: 0x121212
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// Set up the main camera
camera.position.z = 5;
// Load the background texture
var texture = THREE.ImageUtils.loadTexture( '1.jpg' );
var backgroundMesh = new THREE.Mesh(
new THREE.PlaneGeometry(2, 2, 0),
new THREE.MeshBasicMaterial({
map: texture
}));
backgroundMesh .material.depthTest = false;
backgroundMesh .material.depthWrite = false;
// Create your background scene
var backgroundScene = new THREE.Scene();
var backgroundCamera = new THREE.Camera();
backgroundScene .add(backgroundCamera );
backgroundScene .add(backgroundMesh );
// Rendering function
var render = function () {
requestAnimationFrame(render);
// Update the color to set
if (color < 0xdddddd) color += 0x0000ff;
// Update the cube color
cube.material.color.setHex(color);
// Update the cube rotations
cube.rotation.x += 0.05;
cube.rotation.y += 0.02;
renderer.autoClear = false;
renderer.clear();
renderer.render(backgroundScene , backgroundCamera );
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
**Demo right here **
Hope this helps.
NOTE (2014/06/28): This code works with the latest release of Three.js: R67
Use Texture loader to load a any image as texture and then apply that to scene like this:
//Load background texture
const loader = new THREE.TextureLoader();
loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' , function(texture)
{
scene.background = texture;
});
Result:
Demo:
See the Pen Flat Earth Three.JS by Hitesh Sahu (#hiteshsahu) on CodePen.
this run:
renderer = new THREE.WebGLRenderer({ antialias: false,alpha:true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor(0x000000, 0);
An background image can be set by setting the scene.background attribute of the THREE.Scene:
scene = new THREE.Scene();
bgTexture = loader.load("https://i.stack.imgur.com/vDUZz.jpg",
function ( texture ) {
var img = texture.image;
bgWidth= img.width;
bgHeight = img.height;
resize();
} );
scene.background = bgTexture;
bgTexture.wrapS = THREE.MirroredRepeatWrapping;
bgTexture.wrapT = THREE.MirroredRepeatWrapping;
The aspect ratio of the image can be adjusted to the aspect ratio of the canvas like this:
var aspect = window.innerWidth / window.innerHeight;
var texAspect = bgWidth / bgHeight;
var relAspect = aspect / texAspect;
bgTexture.repeat = new THREE.Vector2(
Math.max(relAspect, 1),
Math.max(1/relAspect,1) );
bgTexture.offset = new THREE.Vector2(
-Math.max(relAspect-1, 0)/2,
-Math.max(1/relAspect-1, 0)/2 );
See the code snippet:
(function onLoad() {
var container, loader, camera, scene, renderer, controls, bgTexture, bgWidth, bgHeight;
init();
animate();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, -4, -1.5);
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
bgTexture = loader.load("https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/background.jpg",
function ( texture ) {
var img = texture.image;
bgWidth= img.width;
bgHeight = img.height;
resize();
}
);
scene.background = bgTexture;
bgTexture.wrapS = THREE.MirroredRepeatWrapping;
bgTexture.wrapT = THREE.MirroredRepeatWrapping;
scene.add(camera);
window.onresize = resize;
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.x = -0.75;
directionalLight.position.y = -0.5;
directionalLight.position.z = -1;
scene.add( directionalLight );
controls = new THREE.OrbitControls(camera, renderer.domElement);
createModel();
}
function createModel() {
var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
var texAspect = bgWidth / bgHeight;
var relAspect = aspect / texAspect;
bgTexture.repeat = new THREE.Vector2( Math.max(relAspect, 1), Math.max(1/relAspect,1) );
bgTexture.offset = new THREE.Vector2( -Math.max(relAspect-1, 0)/2, -Math.max(1/relAspect-1, 0)/2 );
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://threejs.org/build/three.min.js"></script>
<!--script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script-->
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
thank you ))
I found yet another solution:
<!DOCTYPE html>
<head>
<title>three.js webgl - orbit 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-image:url(./foto.jpg);
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
</div>
<script src="./three.min.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<!--используем для вывода информации fps-->
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera.position.z = 100;
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
var texture = new THREE.Texture();
var loader = new THREE.ImageLoader( manager );
loader.load( './kos.jpg', function ( image ) {
texture.image = image;
texture.needsUpdate = true;
} );
// model
var loader = new THREE.OBJLoader( manager );
loader.load( './skull.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.map = texture;
}
} );
object.position.y = 10;
scene.add( object );
} );
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0xffffff );
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
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 );
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
It seems rather late in the day to be adding any contribution to this thread but here is my 'hap'orth':
<head>
<meta charset=utf-8>
<title>Temple7</title>
<style>
body { margin: 0;
}
canvas { width: 100%; height: 100%;
background-image:url(Clouds.jpg);
}
</style>
</head>
This rather simplistic approach has its limitations. The .jpg image retains its pixel dimensions so that, for different sizes of the browser window one sees different amounts of the image. If the canvas size exceeds the size of the .jpg, then tiling occurs.

Three.js, Macintosh Display 3D Model

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.

three.js - identify point on tube circumference and rotate from that point

Below is my code for the scene of tube geometry. I've loaded 200 co-ordinates as JSON data from external file.
<!DOCTYPE html>
<html lang="en">
<head>
<title>3d Model using HTML5 and three.js</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: #f0f0f0;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
</style>
</head>
<body>
<div id="info">
WASD-move, RF-up/down, QE-roll, mouse-look around, mouse left/right click- zoom-in/out
</div>
<script src="three.min.js" type="text/javascript"></script>
<script src="Curve.js" type="text/javascript"></script>
<script src="Stats.js" type="text/javascript"></script>
<script src="Detector.js" type="text/javascript"></script>
<script src="path.js" type="text/javascript"></script>
<script>
// variables
var container, stats;
var camera, scene, renderer, controls;
var text, plane, tube, tubeMesh, parent;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0, mouseY = 0; var radius = 6371;
var mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var clock = new THREE.Clock();
function plotPath()
{
var obj = getPath();
var segments = 60;
var closed = false;
var debug = true;
var radiusSegments = 12;
var tube;
var points = [];
var x=0,y=0,z=0;
var extrudePath;
for(var i=0; i<obj.path.length; i++)
{
console.log(obj.path[i].point);
points.push(obj.path[i].point);
}
extrudePath = new THREE.SplineCurve3(points);
tube = new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed, debug);
tubeMesh = new THREE.Mesh(tube ,new THREE.MeshBasicMaterial({
color: 0x000000, side: THREE.DoubleSide,
opacity: 0.5, transparent: true, wireframe: true}));
if ( tube.debug ) tubeMesh.add( tube.debug );
scene.add( tubeMesh );
}
init();
animate();
function init(){
// container
container = document.createElement( 'div' );
document.body.appendChild( container );
// scene
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// camera
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
// light
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( 0x555555 );
scene.add( light );
// CONTROLS
controls = new THREE.RollControls( camera );
controls.movementSpeed = 50;
controls.lookSpeed = 3;
controls.constrainVertical = [ -0.5, 0.5 ];
// Grid
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );
geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );
for ( var i = 0; i <= 20; i ++ ) {
line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.z = ( i * 50 ) - 500;
scene.add( line );
line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.x = ( i * 50 ) - 500;
line.rotation.y = 90 * Math.PI / 180;
scene.add( line );
}
// projector
projector = new THREE.Projector();
plotPath();
// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
// events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
update();
}
function update(){
controls.update(clock.getDelta());
stats.update();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
How can I identify a point on tube circumference and how to rotate a tube from that point ?
OrbitControls, for example, has a property target which is both the center of rotation and the camera look-at position.
controls = new THREE.OrbitControls( camera );
You can change the center of rotation of the camera using picking.
function onDocumentMouseDown( event ) {
event.preventDefault();
var vector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
0.5 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
var intersects = ray.intersectObjects( objects );
if ( intersects.length > 0 ) {
controls.target.copy( intersects[0].point );
}
}
EDIT: Here is an updated fiddle: http://jsfiddle.net/eVkgs/30/
three.js r.65

Resources