Related
I'm still struggling with getting spotLight to stick to the camera. I can see the light but looks like it stays at one place (?).
See the video for reference
//Camera
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 1, 0 );
//spotLight attached to camera
spotlight = new THREE.SpotLight( 0xffffff, 55 );
spotlight.angle = 0.20*(Math.PI / 3);
spotlight.penumbra = 0.1;
spotlight.decay = 2;
spotlight.distance = 200;
camera.add( spotlight);
camera.add( spotlight.target );
spotlight.target.position.set( 0, 0, 1 );
spotlight.target=camera;
spotlight.position.copy( camera.position );
controls = new PointerLockControls( camera, document.body );
//adding first person camera from PointerLockControls
scene.add( controls.getObject() );
I also tried grouping camera and spotlight:
const group = new THREE.Group();
group.add(camera);
group.add(spotlight);
spotlight.target=camera;
spotlight.position.copy( camera.position );
controls = new PointerLockControls( group, document.body );
but that did not work either. What should I change? What's missing here?
//edit this is what my current code looks like
import * as THREE from "../node_modules/three/build/three.module.js";
import { GUI } from './jsm/libs/dat.gui.module.js';
let renderer, scene, camera, gui;
let spotlight, lightHelper;
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,1);
const boxgeometry = new THREE.BoxGeometry( 25, 25, 25 );
const boxmaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( boxgeometry, boxmaterial );
scene.add( cube );
cube.position.set(-20,0,1);
const ambient = new THREE.AmbientLight( 0xffffff, 0.2 );
scene.add(ambient);
**scene.add(camera);
spotlight = new THREE.SpotLight(0xffffff, 55, 80, 0.8*Math.PI);
camera.add(spotlight);
camera.add(spotlight.target);**
let material = new THREE.MeshPhongMaterial( { color: 0x808080, dithering: true } );
let geometry = new THREE.PlaneGeometry( 2000, 2000 );
let floor= new THREE.Mesh( geometry, material );
floor.position.set( 0, - 1, 0 );
floor.rotation.x = - Math.PI * 0.5;
floor.receiveShadow = true;
scene.add(floor);
render();
window.addEventListener( 'resize', onWindowResize );
}
function animate()
{
requestAnimationFrame( animate );
camera.rotation.y+=0.01;
renderer.render( scene, camera );
}
animate();
The setup should look like so:
let camera, scene, renderer;
init();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 1;
scene = new THREE.Scene();
scene.add(camera);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const spotLight = new THREE.SpotLight(0xffffff, 0.6, 0, Math.PI * 0.05);
camera.add(spotLight);
const geometry = new THREE.PlaneGeometry();
const material = new THREE.MeshPhongMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animation);
document.body.appendChild(renderer.domElement);
}
function animation(time) {
const t = time * 0.001;
camera.position.x = Math.sin(t) * 0.25;
camera.position.y = Math.cos(t) * 0.25;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.134.0/build/three.min.js"></script>
It's important to add the spot light as a child to the camera and the camera itself to the scene.
I draw a sphere using this code
function sphere(cena,x,y,z,radius,colorr)
{
var sphereGeometry = new THREE.SphereGeometry( radius, 10, 10);
var materiall = new THREE.MeshBasicMaterial( { color: colorr , side: THREE.DoubleSide} );
var cir = new THREE.Mesh( sphereGeometry, materiall )
cir.position.x=x;
cir.position.y=y;
cir.position.z=z;
cena.add( cir );
return cir ;
}
Now I am drawing a sphere with radius 10^(-6)
var um=Math.pow(10,-6);
sphere(scene,0,0,0,um*3.5,'green')
Nothing is drawn. The same is for um*30. Only from um*300 the sphere appears. Camera near is set 0.000001
I need that scales, what to do?
Lines, by the way are drawn well
It depends on how you position your camera. Try it with this code:
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.000001, 1 );
scene = new THREE.Scene();
var um = Math.pow( 10, - 6 );
camera.position.z = um * 10;
var mesh = sphere( scene, 0, 0, 0, um * 3.5 , 'green' );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
function sphere(cena,x,y,z,radius,colorr) {
var sphereGeometry = new THREE.SphereBufferGeometry( radius, 10, 10);
var materiall = new THREE.MeshBasicMaterial( { color: colorr , side: THREE.DoubleSide} );
var cir = new THREE.Mesh( sphereGeometry, materiall );
cir.position.x=x;
cir.position.y=y;
cir.position.z=z;
cena.add( cir );
return cir;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.114/build/three.js"></script>
The following code is a working example using custom geometry to draw a tetrahedron with three.js (relevant is mesh2):
<!DOCTYPE html>
<html>
<header>
<script src="three.min.js"></script>
<style>
body {
overflow: hidden;
}
</style>
</header>
<body>
<script>
var camera, scene, renderer;
var geometry, material, mesh1, mesh2;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.01, 300 );
camera.position.z = 50;
scene = new THREE.Scene();
material = new THREE.MeshNormalMaterial();
// 1
geometry = new THREE.BoxGeometry( 10, 10, 10 );
mesh1 = new THREE.Mesh( geometry, material );
scene.add( mesh1 );
// 2 begin
geometry = new THREE.Geometry( );
geometry.vertices.push( new THREE.Vector3( 6,6, 6), new THREE.Vector3( 10,6, 6), new THREE.Vector3( 6,10, 6), new THREE.Vector3( 6,6, 10) );
geometry.faces.push( new THREE.Face3( 0,2,1),new THREE.Face3( 1,2,3),new THREE.Face3( 1,3,0),new THREE.Face3( 0,3,2));
geometry.computeFaceNormals();
geometry.computeVertexNormals();
mesh2 = new THREE.Mesh( geometry, material );
scene.add( mesh2 );
// 2 end
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh1.rotation.x += 0.01;
mesh1.rotation.y += 0.02;
mesh2.rotation.x += 0.01;
mesh2.rotation.y += 0.02;
renderer.render( scene, camera );
}
</script>
</body>
</html>
The following code tries to draw a component of a furniture:
<!DOCTYPE html>
<html>
<header>
<script src="three.min.js"></script>
<style>
body {
overflow: hidden;
}
</style>
</header>
<body>
<script>
var camera, scene, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0, 550 );
camera.position.z = 4000;
scene = new THREE.Scene();
scene.add(camera);
function cos(x) {
return Math.cos(Math.PI*x/180);
}
function sin(x) {
return Math.sin(Math.PI*x/180);
}
var geometry = new THREE.Geometry();
var step_deg = 10;
var count = -1;
for(deg=0 ;deg<=360;deg+=step_deg) {
var x1,y1,z1,x2,y2,z2;
if (deg>=0 && deg<=90) {
x1 = 400+100*cos(deg); y1 = 900+100*sin(deg); z1=0;
x2 = x1; y2 = y1; z2 = 27;
geometry.vertices.push( new THREE.Vector3( x1,y1, z1), new THREE.Vector3( x2,y2,z2) );
count++; console.log(""+count+": ["+x1+","+y1+","+z1+"]");
count++; console.log(""+count+": ["+x2+","+y2+","+z2+"]");
}
if (deg>=90 && deg<=180) {
x1 = 50+50*cos(deg); y1 = 950+50*sin(deg); z1 = 0;
x2 = x1; y2 = y1; z2 = 27;
geometry.vertices.push( new THREE.Vector3( x1,y1, z1), new THREE.Vector3( x2,y2,z2) );
count++; console.log(""+count+": ["+x1+","+y1+","+z1+"]");
count++; console.log(""+count+": ["+x2+","+y2+","+z2+"]");
}
if (deg>=180 && deg<=270) {
x1 = 50+50*cos(deg); y1 = -950+50*sin(deg); z1 = 0;
x2 = x1; y2 = y1; z2 = 27;
geometry.vertices.push( new THREE.Vector3( x1,y1, z1), new THREE.Vector3( x2,y2,z2) );
count++; console.log(""+count+": ["+x1+","+y1+","+z1+"]");
count++; console.log(""+count+": ["+x2+","+y2+","+z2+"]");
}
if (deg>=270 && deg<=360) {
x1 = 400+100*cos(deg); y1 = -900+100*sin(deg); z1 = 0;
x2 = x1; y2 = y1; z2 = 27;
geometry.vertices.push( new THREE.Vector3( x1,y1, z1), new THREE.Vector3( x2,y2,z2) );
count++; console.log(""+count+": ["+x1+","+y1+","+z1+"]");
count++; console.log(""+count+": ["+x2+","+y2+","+z2+"]");
}
}
geometry.vertices.push( new THREE.Vector3( 400,900, 0), new THREE.Vector3( 400,900, 27) ); // 80, 81
geometry.vertices.push( new THREE.Vector3( 50,950, 0), new THREE.Vector3( 50,950, 27) );
geometry.vertices.push( new THREE.Vector3( 50,-950, 0), new THREE.Vector3( 50,-950, 27) );
geometry.vertices.push( new THREE.Vector3( 400,-900, 0), new THREE.Vector3( 400,-900, 27) ); // 86, 87
for(i=0;i<40;i++) {
geometry.faces.push( new THREE.Face3( i*2, (i*2+2) % 80, i*2+1) );
console.log("["+i*2+","+ ((i*2+2) % 80)+","+ (i*2+1)+"]");
geometry.faces.push( new THREE.Face3( i*2+1, (i*2+2) % 80, (i*2+3) % 80) );
console.log("["+(i*2+1)+","+ ((i*2+2)%80)+","+ ((i*2+3) % 80)+"]");
}
geometry.faces.push( new THREE.Face3( 82,20,80), new THREE.Face3( 18,80,20),
new THREE.Face3( 84,38,82), new THREE.Face3( 84,40,38),
new THREE.Face3( 80,86,82), new THREE.Face3( 82,86,84),
new THREE.Face3( 0,78,80), new THREE.Face3( 80,78,86),
new THREE.Face3( 60,84,86), new THREE.Face3( 60,58,84)
);
geometry.faces.push( new THREE.Face3( 83,81,21), new THREE.Face3( 19,21,81),
new THREE.Face3( 85,83,39), new THREE.Face3( 85,39,41),
new THREE.Face3( 81,83,87), new THREE.Face3( 83,85,87),
new THREE.Face3( 1,81,79), new THREE.Face3( 81,87,79),
new THREE.Face3( 61,87,85), new THREE.Face3( 61,85,59)
);
for(i=0;i<10;i++) {
geometry.faces.push( new THREE.Face3( 80, 2*(i+1), 2*i),new THREE.Face3( 81, 2*i+1, 2*(i+1)+1),
new THREE.Face3( 82, 2*(i+1)+20,2*i+20),new THREE.Face3( 83, 2*i+21, 2*(i+1)+21),
new THREE.Face3( 84, 2*(i+1)+40,2*i+40),new THREE.Face3( 85, 2*i+41, 2*(i+1)+41),
new THREE.Face3( 86, (2*(i+1)+60)%80,2*i+60),new THREE.Face3( 87, 2*i+61, (2*(i+1)+61)%80)
);
}
geometry.computeFaceNormals();
geometry.computeVertexNormals();
var box = new THREE.Box3().setFromPoints( geometry.vertices );
console.log( box.min, box.max, box.getSize() );
material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
</script>
</body>
</html>
Basically it is the same technology but more complex. This second example does not show up.
My questions:
Is there a rule of dumb, given that the mesh is in x=0..500,y=-1000..1000,z=0..27 (mm), how do I set PerspectiveCamera and camera.position.z (or to generalize: given x=-X..X,y=-Y..Y,z=-Z..Z)?
How sensible is the library from stopping rendering the object (in the console there is no error!)?
Can the orientation of a some faces be inverted?
Can the surface be incomplete?
What else could be wrong?
EDIT
Now it works! I made following change
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 500, 0 );
camera.position.z = 3000;
If I understand it correctly, we are in the point (0,0,3000) observing in the direction of (0,0,0) with an angle of 60°, and the "near" is the xy-plane with z=500 resp. the "far" is the xy-plane with z=0. The mesh is 100% correct (at the first try! ;-) ).
EDIT 2 Fiddle with the complete furniture: link
Updated, now the animation make a lot more meaningful. But the main point is: I need the center of the furniture in the center of the picture. I need some sort of function "lookAt" for the camera and set it to the difference between camera position and furniture center (pos_center.add(pos_camera.negate()).normalize()).
The granite texture for the floor does not work, but this is another question.
I've created a polyhedron and it has rounded corners (or even faces - I don't know which explanation is correct). How can I set border-radius?
Is it possible to remove rounding and make usual corners?
Code is below.
<html>
<head
>
<title>Моё 3</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
<script src="http://stemkoski.github.io/Three.js/js/Three.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/Detector.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/Stats.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/OrbitControls.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.KeyboardState.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.FullScreen.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.WindowResize.js"></script>
<script>
/*
Three.js "tutorials by example"
Author: Lee Stemkoski
Date: July 2013 (three.js v59dev)
*/
// MAIN
var polyhedronShape, polyhedronPts = [], cube, mesh;
// standard global variables
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// custom global variables
var targetList = [];
var projector, mouse = { x: 0, y: 0 };
init();
animate();
// FUNCTIONS
function init()
{
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// EVENTS
THREEx.WindowResize(renderer, camera);
THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
// CONTROLS
controls = new THREE.OrbitControls( camera, renderer.domElement );
// STATS
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
// LIGHT
var light = new THREE.PointLight(0xffffff);
light.position.set(0,250,0);
scene.add(light);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture( 'images/checkerboard.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
// SKYBOX/FOG
var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
scene.add(skyBox);
////////////
// CUSTOM //
////////////
//////////////////////////////////////////////////////////////////////
// this material causes a mesh to use colors assigned to faces
var faceColorMaterial = new THREE.MeshBasicMaterial(
{ color: 0xffffff, vertexColors: THREE.FaceColors } );
var sphereGeometry = new THREE.SphereGeometry( 80, 32, 16 );
for ( var i = 0; i < sphereGeometry.faces.length; i++ )
{
face = sphereGeometry.faces[ i ];
face.color.setRGB( 0, 0, 0.8 * Math.random() + 0.2 );
}
var sphere = new THREE.Mesh( sphereGeometry, faceColorMaterial );
sphere.position.set(0, 50, 0);
scene.add(sphere);
targetList.push(sphere);
// Create an array of materials to be used in a cube, one for each side
var cubeMaterialArray = [];
// order to add materials: x+,x-,y+,y-,z+,z-
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff3333 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff8800 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xffff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x33ff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x3333ff } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x8833ff } ) );
var cubeMaterials = new THREE.MeshFaceMaterial( cubeMaterialArray );
// Cube parameters: width (x), height (y), depth (z),
// (optional) segments along x, segments along y, segments along z
var cubeGeometry = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1 );
// using THREE.MeshFaceMaterial() in the constructor below
// causes the mesh to use the materials stored in the geometry
cube = new THREE.Mesh( cubeGeometry, cubeMaterials );
cube.position.set(-100, 50, -50);
scene.add( cube );
targetList.push(cube);
// polyhedron
polyhedronPts.push( new THREE.Vector2 ( -100, 600 ) );
polyhedronPts.push( new THREE.Vector2 ( 300, 600 ) );
polyhedronPts.push( new THREE.Vector2 ( 600, -100 ) );
polyhedronShape = new THREE.Shape( polyhedronPts );
var extrudeSettings = {amount: 20}; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5
var geometry = new THREE.ExtrudeGeometry( polyhedronShape, extrudeSettings );
mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshBasicMaterial( { color: 0x00cc00 } ), new THREE.MeshBasicMaterial( { color: 0xff3333, wireframe: true, transparent: true } ) ] );
mesh.position.set( -50, 50, 300 );
mesh.rotation.set( 300, 0, 0 );
//mesh.scale.set( 1, 1, 1 );
scene.add( mesh );
targetList.push(mesh);
//////////////////////////////////////////////////////////////////////
// initialize object to perform world/screen calculations
projector = new THREE.Projector();
// when the mouse moves, call the given function
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
function onDocumentMouseDown( event )
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
// event.preventDefault();
//console.log("Click.");
// update the mouse variable
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// find intersections
// create a Ray with origin at the mouse position
// and direction into the scene (camera direction)
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects( targetList );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
console.log("Hit # " + toString( intersects[0].point ) );
// change the color of the closest face.
intersects[ 0 ].face.color.setRGB( 0.8 * Math.random() + 0.2, 0, 0 );
intersects[ 0 ].object.geometry.colorsNeedUpdate = true;
}
}
function toString(v) { return "[ " + v.x + ", " + v.y + ", " + v.z + " ]"; }
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
function update()
{
if ( keyboard.pressed("z") )
{
// do something
}
controls.update();
stats.update();
}
function render()
{
renderer.render( scene, camera );
}
</script>
</body>
</html>
Do you mean smooth faces?
The way to make your edges 'hard' is to first add this to your material options:
shading: THREE.FlatShading,
And then possibly:
geometry.computeVertexNormals()
I'm making a Three.js application and I want to catch clicks on objects. When I create cube or sphere everything is ok, but I fail with polyhedron - Raycaster.intersectObjects() returns empty result.
My code is below (see click events in console.log()).
What can I do to make it work? Are there other ways to create polyhedrons?
<html>
<head>
<title>Моё 3</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
<script src="http://stemkoski.github.io/Three.js/js/Three.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/Detector.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/Stats.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/OrbitControls.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.KeyboardState.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.FullScreen.js"></script>
<script src="http://stemkoski.github.io/Three.js/js/THREEx.WindowResize.js"></script>
<script>
/*
Three.js "tutorials by example"
Author: Lee Stemkoski
Date: July 2013 (three.js v59dev)
*/
// MAIN
var polyhedronShape, polyhedronPts = [], cube, mesh;
// standard global variables
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// custom global variables
var targetList = [];
var projector, mouse = { x: 0, y: 0 };
init();
animate();
// FUNCTIONS
function init()
{
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// EVENTS
THREEx.WindowResize(renderer, camera);
THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
// CONTROLS
controls = new THREE.OrbitControls( camera, renderer.domElement );
// STATS
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
// LIGHT
var light = new THREE.PointLight(0xffffff);
light.position.set(0,250,0);
scene.add(light);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture( 'images/checkerboard.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
// SKYBOX/FOG
var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
scene.add(skyBox);
////////////
// CUSTOM //
////////////
//////////////////////////////////////////////////////////////////////
// this material causes a mesh to use colors assigned to faces
var faceColorMaterial = new THREE.MeshBasicMaterial(
{ color: 0xffffff, vertexColors: THREE.FaceColors } );
var sphereGeometry = new THREE.SphereGeometry( 80, 32, 16 );
for ( var i = 0; i < sphereGeometry.faces.length; i++ )
{
face = sphereGeometry.faces[ i ];
face.color.setRGB( 0, 0, 0.8 * Math.random() + 0.2 );
}
var sphere = new THREE.Mesh( sphereGeometry, faceColorMaterial );
sphere.position.set(0, 50, 0);
scene.add(sphere);
targetList.push(sphere);
// Create an array of materials to be used in a cube, one for each side
var cubeMaterialArray = [];
// order to add materials: x+,x-,y+,y-,z+,z-
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff3333 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff8800 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xffff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x33ff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x3333ff } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x8833ff } ) );
var cubeMaterials = new THREE.MeshFaceMaterial( cubeMaterialArray );
// Cube parameters: width (x), height (y), depth (z),
// (optional) segments along x, segments along y, segments along z
var cubeGeometry = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1 );
// using THREE.MeshFaceMaterial() in the constructor below
// causes the mesh to use the materials stored in the geometry
cube = new THREE.Mesh( cubeGeometry, cubeMaterials );
cube.position.set(-100, 50, -50);
scene.add( cube );
targetList.push(cube);
// polyhedron
polyhedronPts.push( new THREE.Vector2 ( -100, 600 ) );
polyhedronPts.push( new THREE.Vector2 ( 300, 600 ) );
polyhedronPts.push( new THREE.Vector2 ( 600, -100 ) );
polyhedronShape = new THREE.Shape( polyhedronPts );
var extrudeSettings = {amount: 20}; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5
var geometry = new THREE.ExtrudeGeometry( polyhedronShape, extrudeSettings );
mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshBasicMaterial( { color: 0x00cc00 } ), new THREE.MeshBasicMaterial( { color: 0xff3333, wireframe: true, transparent: true } ) ] );
mesh.position.set( -50, 50, 300 );
mesh.rotation.set( 300, 0, 0 );
//mesh.scale.set( 1, 1, 1 );
scene.add( mesh );
targetList.push(mesh);
//////////////////////////////////////////////////////////////////////
// initialize object to perform world/screen calculations
projector = new THREE.Projector();
// when the mouse moves, call the given function
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
function onDocumentMouseDown( event )
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
// event.preventDefault();
//console.log("Click.");
// update the mouse variable
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// find intersections
// create a Ray with origin at the mouse position
// and direction into the scene (camera direction)
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects( targetList );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
console.log("Hit # " + toString( intersects[0].point ) );
// change the color of the closest face.
intersects[ 0 ].face.color.setRGB( 0.8 * Math.random() + 0.2, 0, 0 );
intersects[ 0 ].object.geometry.colorsNeedUpdate = true;
}
}
function toString(v) { return "[ " + v.x + ", " + v.y + ", " + v.z + " ]"; }
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
function update()
{
if ( keyboard.pressed("z") )
{
// do something
}
controls.update();
stats.update();
}
function render()
{
renderer.render( scene, camera );
}
</script>
</body>
</html>