I need to create perfect ring geometry in three.js. I am looking for something like this:
I spend more than a day to find how to do this, and I am stuck with code like this:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
var controls = new THREE.OrbitControls( camera, renderer.domElement );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
ring = '';
var loader = new THREE.TextureLoader();
loader.load('img/water.jpg', function ( texture ) {
var geometry = new THREE.TorusGeometry( 5, 1, 8, 1900 );
ring = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({map: texture, wireframe: true}));
scene.add(ring);
});
camera.position.z = 20;
var render = function () {
requestAnimationFrame( render );
ring.rotation.y = 0.4;
renderer.render(scene,camera);
};
render();
EDIT:
My code has changed, and now it looks like this:
var container, stats;
var camera, scene, renderer;
var group;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 100, 350, 00 );
scene.add( camera );
var light = new THREE.PointLight( 0xffffff, 0.9 );
camera.add( light );
group = new THREE.Group();
group.position.y = 0;
scene.add( group );
var loader = new THREE.TextureLoader();
var texture = loader.load( "img/metal.png" );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 0.008, 0.008 );
function addShape( shape, extrudeSettings, color, x, y, z, rx, ry, rz, s ) {
// flat shape with texture
// note: default UVs generated by ShapeGemoetry are simply the x- and y-coordinates of the vertices
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: color } ) );
mesh.position.set( x, y, z );
mesh.rotation.set( rx, ry, rz );
mesh.scale.set( s, s, s );
group.add( mesh );
}
// Arc circle 1
var x = 0, y = 0;
var arcShape1 = new THREE.Shape();
arcShape1.moveTo( 0, 0 );
arcShape1.absarc( 10, 10, 11, 0, Math.PI*2, false );
var holePath1 = new THREE.Path();
holePath1.moveTo( 20, 10 );
holePath1.absarc( 10, 10, 10, 0, Math.PI*2, true );
arcShape1.holes.push( holePath1 );
//
// Arc circle 2
var x = 0, y = 0;
var arcShape2 = new THREE.Shape();
arcShape2.moveTo( 0, 0 );
arcShape2.absarc( 10, 10, 13, 0, Math.PI*2, false );
var holePath2 = new THREE.Path();
holePath2.moveTo( 25, 10 );
holePath2.absarc( 10, 10, 12, 0, Math.PI*2, true );
arcShape2.holes.push( holePath2 );
//
var extrudeSettings = { amount: 1.6, bevelEnabled: true, bevelSegments: 30, steps: 30, bevelSize: 0.3, bevelThickness: 1.5, curveSegments: 100 };
// addShape( shape, color, x, y, z, rx, ry,rz, s );
//addShape( heartShape, extrudeSettings, 0xf00000, 60, 100, 0, 0, 0, Math.PI, 1 );
addShape( arcShape1, extrudeSettings, 0xffc107, -35, -30, -20, 0, 0, 0, 4 );
addShape( arcShape2, extrudeSettings, 0xffc107, -40, -22, -50, 0, 0.6, 0, 4 );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
group.castShadow = true;
group.receiveShadow = false;
container.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
The result looks like this:
And now the questions: how to make this line on the ring dissapear, how to make my ring more shiny, how to make my ring more 'circular' on the left and right side?
Should works fine. It was the bevel at junction at PI*2 causing the 'line' thing. You can solve the problem by overlapping the two edges of the curve.
arcShape1.absarc( 10, 10, 11, 0, Math.PI*1.99, false );
holePath1.absarc( 10, 10, 10, 0, Math.PI*2.01, true );
arcShape2.absarc( 10, 10, 13, 0, Math.PI*1.99, false );
holePath2.absarc( 10, 10, 12, 0, Math.PI*2.01, true );
! Please click to see the screenshot. I do not have enough reputation to post the picture here.
I found that by adding more light sources in various locations and color, I could increase perceived reflectivity and shine, but this is assuming it is the only object in the scene.
Related
I made a TubeGeometry by passing in a SplineCurve3 / CatmullRomCurve3 path as a parameter.
I am trying to update the position of each of the path's points with geometry.parameters.path.points[1].y += 0.01; under requestAnimationFrame.
The values itself updates on console.log but the points dont move. How can i do this?
By the way, i'm not looking to move 'vertices' but rather the points of the path that shape how the tube is rendered.
var camera, scene, light, renderer, geometry, material, mesh;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// default bg canvas color //
renderer.setClearColor(0x00ff00);
// use device aspect ratio //
// renderer.setPixelRatio(window.devicePixelRatio);
// set size of canvas within window //
renderer.setSize(window.innerWidth, window.innerHeight);
// create camera //
// params = field of view, aspect ratio, clipping of near objects, clipping of far objs
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
camera.position.z = 100;
// create scene
scene = new THREE.Scene();
// create ambient lighting, params -> color, intensity
light = new THREE.AmbientLight(0xffffff, 0.5)
// add light to scene
scene.add(light)
// create line, with params as x,y,z
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -60, 0, 0 ),
new THREE.Vector3( -50, 10, 0 ),
new THREE.Vector3( -40, 0, 0 ),
new THREE.Vector3( -30, -10, 0 ),
new THREE.Vector3( -20, 0, 0 ),
new THREE.Vector3( -10, 10, 0 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 10, -10, 0 ),
new THREE.Vector3( 20, 0, 0 ),
new THREE.Vector3( 30, 10, 0 ),
new THREE.Vector3( 40, 0, 0 ),
new THREE.Vector3( 50, -10, 0 ),
new THREE.Vector3( 60, 0, 0 )
]);
curve.verticesNeedUpdate = true;
for (i = 0; i < curve.points.length; i++) {
// this will get a number between 1 and 10;
var num = Math.floor(Math.random()*10) + 1;
num *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
curve.points[i].y = num;
// console.log(curve.points[i].y);
}
geometry = new THREE.TubeGeometry(curve, 1000, 0.2, 8, false);
geometry.dynamic = true;
/* standard material */
material = new THREE.MeshBasicMaterial({
color: 0xff0000
});
// create mesh
mesh = new THREE.Mesh(geometry, material);
// set positon of line
mesh.position.set(0,0,-10);
// add to scene
scene.add(mesh);
document.body.appendChild(renderer.domElement);
} /* end init */
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//console.log(geometry.parameters.path.points);
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// mesh.rotation.x += 0.01;
// mesh.rotation.y += 0.01;
geometry.parameters.path.points[1].y += 0.01;
geometry.verticesNeedUpdate = true;
//console.log(geometry.parameters.path.points[1].y)
/* render scene and camera */
renderer.render(scene,camera);
}
body {
margin:0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
I wasn't able to get it working using TubeGeometry, but I did with TubeBufferGeometry. Luckily, there isn't much to change, because both use the curve path to define the mesh vertices. You're free to try to replicate this with TubeGeometry instead.
The main problem you're seeing though is that Tube(Buffer)Geometry BUILDS geometry, rather than IS geometry, and that's where the convenience ends. Updating the path does not trigger the geometry to rebuild. Instead, if you update your path, you must recreate the Tube(Buffer)Geometry.
In the code below, all I did was swap TubeBufferGeometry in place of TubeGeometry, changed geometry.verticesNeedUpdated to geometry.needsUpdate (this is how BufferGeometry handles updates), and added the line which re-builds the tube:
geometry.copy(new THREE.TubeBufferGeometry(geometry.parameters.path, 1000, 0.2, 8, false));
var camera, scene, light, renderer, geometry, material, mesh;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// default bg canvas color //
renderer.setClearColor(0x00ff00);
// use device aspect ratio //
// renderer.setPixelRatio(window.devicePixelRatio);
// set size of canvas within window //
renderer.setSize(window.innerWidth, window.innerHeight);
// create camera //
// params = field of view, aspect ratio, clipping of near objects, clipping of far objs
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
camera.position.z = 100;
// create scene
scene = new THREE.Scene();
// create ambient lighting, params -> color, intensity
light = new THREE.AmbientLight(0xffffff, 0.5)
// add light to scene
scene.add(light)
// create line, with params as x,y,z
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -60, 0, 0 ),
new THREE.Vector3( -50, 10, 0 ),
new THREE.Vector3( -40, 0, 0 ),
new THREE.Vector3( -30, -10, 0 ),
new THREE.Vector3( -20, 0, 0 ),
new THREE.Vector3( -10, 10, 0 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 10, -10, 0 ),
new THREE.Vector3( 20, 0, 0 ),
new THREE.Vector3( 30, 10, 0 ),
new THREE.Vector3( 40, 0, 0 ),
new THREE.Vector3( 50, -10, 0 ),
new THREE.Vector3( 60, 0, 0 )
]);
curve.verticesNeedUpdate = true;
for (i = 0; i < curve.points.length; i++) {
// this will get a number between 1 and 10;
var num = Math.floor(Math.random()*10) + 1;
num *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
curve.points[i].y = num;
// console.log(curve.points[i].y);
}
geometry = new THREE.TubeBufferGeometry(curve, 1000, 0.2, 8, false);
geometry.dynamic = true;
/* standard material */
material = new THREE.MeshBasicMaterial({
color: 0xff0000
});
// create mesh
mesh = new THREE.Mesh(geometry, material);
// set positon of line
mesh.position.set(0,0,-10);
// add to scene
scene.add(mesh);
document.body.appendChild(renderer.domElement);
} /* end init */
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//console.log(geometry.parameters.path.points);
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// mesh.rotation.x += 0.01;
// mesh.rotation.y += 0.01;
geometry.parameters.path.points[3].y += 0.01;
geometry.copy(new THREE.TubeBufferGeometry(geometry.parameters.path, 1000, 0.2, 8, false));
geometry.needsUpdate = true;
//console.log(geometry.parameters.path.points[1].y)
/* render scene and camera */
renderer.render(scene,camera);
}
body {
margin:0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
Is it possible that an object reflects in itself?
I like to receive a self reflection on a metallic object.
So basicially, the two rings of the mechanism should be reflected in the lower part.
Thank you very much in advance!
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var loader;
var camera, cameraTarget, controls, scene, renderer;
init();
animate();
function init() {
var previewDiv = document.getElementById("preview");
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 15 );
camera.position.set( 3, 0.15, 3 );
cameraTarget = new THREE.Vector3( 0, -0.25, 0 );
controls = new THREE.OrbitControls( camera );
controls.maxPolarAngle = Math.PI / 2.2;
controls.minDistance = 1;
controls.maxDistance = 8;
controls.noPan = false;
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xdae1e6, 2, 15 );
// Ground
var plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 40, 40 ),
new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } )
);
plane.rotation.x = -Math.PI/2;
plane.position.y = -0.5;
scene.add( plane );
plane.receiveShadow = true;
// feinleinen
var feinleinentexture = THREE.ImageUtils.loadTexture( 'textures/feinleinen.jpg' );
feinleinentexture.anisotropy = 16;
feinleinentexture.wrapS = feinleinentexture.wrapT = THREE.RepeatWrapping;
feinleinentexture.repeat.set( 5, 5 );
var feinleinen = new THREE.MeshPhongMaterial( { color: 0xffffff, map: feinleinentexture } );
// Chrome
var path = "textures/chrome/";
var format = '.jpg';
var urls = [
path + 'px' + format, path + 'nx' + format,
path + 'py' + format, path + 'ny' + format,
path + 'pz' + format, path + 'nz' + format
];
var envMap = THREE.ImageUtils.loadTextureCube( urls, THREE.CubeReflectionMapping );
var chrome = new THREE.MeshPhongMaterial( {
color : 0x151515,
specular : 0xffffff,
shininess : 200,
envMap : envMap,
combine : THREE.MixOperation, // or THREE.AddOperation, THREE.MultiplyOperation
reflectivity : 0.8
} );
// basis
var basisGeometry = new THREE.BoxGeometry(1.8,0.012,3);
var basis = new THREE.Mesh(basisGeometry, feinleinen);
basis.castShadow = false;
basis.receiveShadow = true;
basis.position.set( 0, -0.47, 0 );
scene.add(basis);
// 2 Ring
var loader = new THREE.JSONLoader();
loader.load('/models/2ring.js', function(geo, mat){
var mesh = new THREE.Mesh(geo, chrome);
mesh.position.set( 0.08, - 0.477, -0.2 );
mesh.rotation.set( 0, - Math.PI / 0.67, 0 );
mesh.scale.set( 0.1, 0.1, 0.1 );
mesh.castShadow = true;
mesh.receiveShadow = true;
loadJson(mesh );
});
function loadJson(mesh){
scene.add( mesh );
}
// Lights
scene.add( new THREE.AmbientLight( 0x777777 ) );
addShadowedLight( 1, 1, 1, 0xffffff, 1.35 );
addShadowedLight( 0.5, 1, -1, 0xffffff, 1 );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapCullFace = THREE.CullFaceBack;
previewDiv.appendChild (renderer.domElement);
// resize
window.addEventListener( 'resize', onWindowResize, false );
}
function addShadowedLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
directionalLight.castShadow = true;
// directionalLight.shadowCameraVisible = true;
var d = 1;
directionalLight.shadowCameraLeft = -d;
directionalLight.shadowCameraRight = d;
directionalLight.shadowCameraTop = d;
directionalLight.shadowCameraBottom = -d;
directionalLight.shadowCameraNear = 1;
directionalLight.shadowCameraFar = 4;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = -0.005;
directionalLight.shadowDarkness = 0.15;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.lookAt( cameraTarget );
controls.update();
renderer.render( scene, camera );
}
</script>
You want an object to reflect itself when using a three.js renderer.
Environment mapping, which you have implemented, is based on an approximation that the environment being reflected is (infinitely) far away.
Even if you used a CubeCamera for your environment map, as in this example, you would have the same problem.
The solution using three.js is to use a form of raytracing. three.js has a RaytracingRenderer, and a simple demo, but that renderer is currently not highly-supported, nor does it run at real-time frame rates.
three.js r.71
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 using three.js and I'm trying to make a good viewer for .stl files.
But I have a big problem with the shadow, for some files it's ok and for some other it's just horrible. (Most of the time, it's stl file that come from Blender that don't work).
Here are the two different render with a "normal" file and the same file import/export with Blender.
Images : http://imageup.fr/uploads/1367501292.jpeg & http://imageup.fr/uploads/1367501311.jpeg
Here is the code:
<script src="scripts/three.min.js"></script>
<script src="three/js/loaders/STLLoader.js"></script>
<script src="three/js/Detector.js"></script>
<script src="three/js/controls/TrackballControls.js"></script>
<div id='3d' style='width:400px;height:300px;margin:auto;position:relative;border:5px solid white;border-radius:5px;'>
<script>
var modele = document.getElementById('modele3d').value;
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, cameraTarget, scene, renderer;
init();
animate();
function init() {
container = document.getElementById('3d');
camera = new THREE.PerspectiveCamera( 45, 400 / 300, 0.1, 10000 );
camera.position.set( 200, 200, 200 );
cameraTarget = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x1875cd, 0, 100000 );
var material = new THREE.MeshPhongMaterial( { ambient: 0xaeadad, color: 0xfefcfc, specular: 0x111111, shininess: 200} );
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, 0, 0 );
mesh.rotation.set( - Math.PI / 2, 0, 0 );
// Recherche et envoi des tailles //
geometry.computeBoundingBox();
var largeur = (mesh.geometry.boundingBox.max.x)-(mesh.geometry.boundingBox.min.x);
var hauteur = (mesh.geometry.boundingBox.max.y)-(mesh.geometry.boundingBox.min.y);
var profondeur = (mesh.geometry.boundingBox.max.z)-(mesh.geometry.boundingBox.min.z);
var tailles = largeur + " " + hauteur + " " + profondeur;
var prix = document.getElementById('prototype_prix').value;
if(prix==0){
document.getElementById('prototype_taille1').value = Math.round(largeur);
document.getElementById('prototype_taille2').value = Math.round(hauteur);
document.getElementById('prototype_taille3').value = Math.round(profondeur);
document.getElementById('prototype_taille1_base').value = largeur;
document.getElementById('prototype_taille2_base').value = hauteur;
document.getElementById('prototype_taille3_base').value = profondeur;
}
geometry.computeBoundingSphere();
var radius = mesh.geometry.boundingSphere.radius;
mesh.position.set( 0, -radius/2, 0 );
var d = 300/(2*radius);
mesh.scale.set( d, d, d );
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add( mesh );
} );
loader.load( 'images/'+modele);
// Lights
scene.add( new THREE.AmbientLight( 0x777777 ) );
addShadowedLight( 1, 1, 1, 0xffffff, 0.8 );
addShadowedLight( 0.5, 1, -1, 0xfcd891, 0.6 );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
renderer.setSize( 400, 300);
renderer.setClearColor( scene.fog.color, 1 );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.physicallyBasedShading = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapCullFace = THREE.CullFaceBack;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// Trackball
enhanced_control = new THREE.TrackballControls(camera,renderer.domElement);
}
function addShadowedLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z );
scene.add( directionalLight );
directionalLight.castShadow = true;
directionalLight.shadowCameraVisible = true;
directionalLight.shadowCameraNear = 0;
directionalLight.shadowCameraFar = 20;
directionalLight.shadowMapWidth = 1024;
directionalLight.shadowMapHeight = 1024;
directionalLight.shadowBias = -0.005;
directionalLight.shadowDarkness = 0.15;
}
function onWindowResize() {
camera.aspect = 400 / 300;
renderer.setSize( 400, 300);
}
function animate() {
requestAnimationFrame( animate );
enhanced_control.update();
render();
}
function render() {
var timer = Date.now() * 0.0005;
camera.lookAt( cameraTarget );
renderer.render( scene, camera );
}
</script>
<p style='position:relative;margin-top:-310px;margin-left:3px;float:left;color:white;text-shadow:1px 1px 1px #135da4'>Rendu 3D :</p>
</div>
I hope you can help me, I have already passed a lot of time trying to make the render works :s
In the following code, I render some cubes and light them with a PointLight and AmbientLight. However the AmbientLight when set to 0xffffff changes the colour of the sides to white, no matter their assigned colours. Strangely, the point light is working as expected.
How can I make the ambient light behave like the point light, in that it shouldn't wash out the face colours, simply illuminate them? I.e. so setting ambient light to 0xffffff would be equivalent to having multiple point lights at full intensity around the object.
$(function(){
var camera, scene, renderer;
var airplane;
var fuselage;
var tail;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 0.1, 10000 );
camera.position.z = 2;
airplane = new THREE.Object3D();
fuselage = newCube(
{x: 1, y: 0.1, z: 0.1},
{x: 0, y: 0, z: 0},
[0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
[0, 1, 2, 3, 4, 5]
);
airplane.add(fuselage);
tail = newCube(
{x: 0.15, y: 0.2, z: 0.05},
{x: 0.5, y: 0.199, z: 0},
[0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
[0, 1, 2, 3, 4, 5]
);
airplane.add(tail);
scene.add( airplane );
var ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
var pointLight = new THREE.PointLight(0x888888);
pointLight.position.x = 100;
pointLight.position.y = 100;
pointLight.position.z = 100;
scene.add(pointLight);
renderer = new THREE.WebGLRenderer();
renderer.setClearColorHex(0x000000, 1);
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
airplane.rotation.x += 0.005;
airplane.rotation.y += 0.01;
renderer.render( scene, camera );
}
});
function newCube(dims, pos, cols, colAss){
var mesh;
var geometry;
var materials = [];
geometry = new THREE.CubeGeometry( dims.x, dims.y, dims.z );
for (var i in cols){
materials[i] = new THREE.MeshLambertMaterial( { color: cols[i], overdraw: true } );
}
geometry.materials = materials;
for (var i in colAss){
geometry.faces[i].materialIndex = colAss[i];
}
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
mesh.position = pos;
return mesh;
}
EDIT - the three.js API has been changed; material.ambient has been deprecated.
The solution is to set the intensity of your ambient light to a reasonable value.
var ambientLight = new THREE.AmbientLight( 0xffffff, 0.2 );
Updated to three.js r.84