ThreeJS - Bounding Box not set on object with material - three.js

I've tried to add Bounding Box to my object but it seems to work only for the testObj, he does not work for my others objects with texture.
var testObj = new THREE.Mesh(
new THREE.CylinderGeometry( 1 , 1 , 4 , 8 ),
new THREE.MeshLambertMaterial({ color: 0xff00ff })
);
scene.add(testObj );
staticCollideMesh.push(testObj );
// PADDLE1
loaderTexture.load('http://localhost:8000/WoodTexture.jpg', function (texture ) {
var material = new THREE.MeshLambertMaterial( {
map: texture
});
var geometry = new THREE.BoxGeometry(PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_DEPTH );
paddle1 = new THREE.Mesh( geometry, material);
paddle1.castShadow = true;
paddle1.receiveShadow = true;
paddle1.name = "paddle1";
scene.add( paddle1 );
staticCollideMesh.push(paddle1);
}, undefined, function ( err ) {
console.error( 'WoodTexture1.jpg : An error happened.' );
}
);
This is how I add BBox and BoxHelper :
let constructCollisionBoxes = function() {
staticCollideMesh.forEach( function( mesh ){
mesh.BBox = new THREE.Box3().setFromObject( mesh );
mesh.BBoxHelper = new THREE.BoxHelper( mesh , 0xff0000 );
scene.add( mesh.BBoxHelper );
});
}
I don't know why the loop just apply for my cylinder ... I need help to understand why this is not working.
EDIT: thanks to #prisoner849 I just added the function in the loader
scene.add(paddle1);
staticCollideMesh.push(paddle1);
constructionCollisionMesh();

In case of using loaders, keep in mind, that loading is asynchronous, so when you call constructCollisionBoxes(), your box, whose creation relies on the moment of finishing of loading of the texture, is not in the staticCollideMesh array yet.
To fix it, you can do it this way:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.25));
var staticCollideMesh = [];
var PADDLE_WIDTH = 3,
PADDLE_HEIGHT = 3,
PADDLE_DEPTH = 2;
var testObj = new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, 4, 8),
new THREE.MeshLambertMaterial({
color: 0xff00ff
})
);
scene.add(testObj);
staticCollideMesh.push(testObj);
var texture = new THREE.TextureLoader().load(`https://threejs.org/examples/textures/uv_grid_opengl.jpg`);
// PADDLE1
var material = new THREE.MeshLambertMaterial({
map: texture
});
var geometry = new THREE.BoxGeometry(PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_DEPTH);
paddle1 = new THREE.Mesh(geometry, material);
paddle1.castShadow = true;
paddle1.receiveShadow = true;
paddle1.name = "paddle1";
scene.add(paddle1);
staticCollideMesh.push(paddle1);
let constructCollisionBoxes = function() {
staticCollideMesh.forEach(function(mesh) {
mesh.BBox = new THREE.Box3().setFromObject(mesh);
mesh.BBoxHelper = new THREE.BoxHelper(mesh, 0xff0000);
scene.add(mesh.BBoxHelper);
});
}
constructCollisionBoxes();
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://unpkg.com/three#0.115.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.115.0/examples/js/controls/OrbitControls.js"></script>

Related

Three.js : remove texture on top/bottom of CylinderGeometry

I'm using Three.js to make basic 3D cylinder rendering. I'm using TextureLoader to load texture async (based on UI interactions).
All is ok, but I would like those textures not to be applied on the cylinder top / bottom.
How can I achieve that?
Here's what I've done so far:
function threeJsRenderer() {
var width = 325;
var height = 375;
var scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera(width / - 2, width / 2, height / 2, height / - 2, -200, 1000);
var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setClearColor( 0x000000, 0 );
renderer.setSize(width,height);
document.getElementById('projection').appendChild(renderer.domElement);
// CylinderGeometry(radiusTop : Float, radiusBottom : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
var geometry = new THREE.CylinderGeometry(135,128,110,64,1, false, 0, Math.PI-2);
var loader = new THREE.TextureLoader();
var material = new THREE.MeshPhongMaterial();
var cone = new THREE.Mesh();
var pointLight = new THREE.AmbientLight( 0xFFFFFF );
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight);
camera.position.z = 40;
camera.position.y = 0;
cone.rotation.x = 0.01;
cone.rotation.y = -10;
jQuery(document).on('new3DConfigReady', function () {
scene.remove(cone);
var newGeometry = new THREE.CylinderGeometry(state.cylinderGeometry.radiusTop,state.cylinderGeometry.radiusBottom,state.cylinderGeometry.height,64,1, false, 0, Math.PI-2);;
cone = new THREE.Mesh(newGeometry, material);
cone.rotation.x = 0.01;
cone.rotation.y = -0.55;
cone.position.y = state.cylinderGeometry.positionY;
geometry.dispose();
if(state.textureUrl !== ''){
scene.add(cone);
}
});
jQuery(document).on('newTextureReady', function () {
loader.load( state.textureUrl, function (texture){
material.map = texture;
material.map.anisotropy = 256;
material.map.needsUpdate = true;
material.needsUpdate = true;
scene.add(cone);
});
});
var render = function () {
requestAnimationFrame(render);
renderer.render(scene, camera);
};
render();
}
Using a materials array you can have different materials on the sides and ends of your cylinder.
var geometry = new THREE.CylinderBufferGeometry( 5, 5, 10, 16, 1 );
var materials = [
new THREE.MeshPhongMaterial( { map: texture } ),
new THREE.MeshPhongMaterial( { color: 0x0000ff } ),
new THREE.MeshPhongMaterial( { color: 0xff0000 } )
];
var mesh = new THREE.Mesh( geometry, materials );
three.js r.100

THREE.js Image aspect ratio

I am having trouble figuring out how to set a PlaneGeometry to a good aspect ratio based on the image size.
var material = new THREE.MeshBasicMaterial({
map : THREE.ImageUtils.loadTexture('img/bunny.png')
});
var plane = new THREE.Mesh(new THREE.PlaneGeometry(20, 20*.75), material);
plane.position.set(0, 10, -60)
scene.add(plane);
What I've tried so far sort of works, but I realise I'm still setting a fixed width/height on the Plane.
I'd like the plane to set the size of the image, then I could scale it down.
var planeGeom = new THREE.PlaneGeometry(20, 20);
var imgSrc = "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png"
var mesh;
var tex = new THREE.TextureLoader().load(imgSrc, (tex) => {
tex.needsUpdate = true;
mesh.scale.set(1.0, tex.image.height / tex.image.width, 1.0);
});
var material = new THREE.MeshLambertMaterial({
color: 0xffffff,
map: tex
});
mesh = new THREE.Mesh(planeGeom, material);
scene.add(mesh);
//Working snippet is below...
var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
45, // Field of view
w / h, // Aspect ratio
0.1, // Near
10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.PointLight(0xFFFFFF);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var planeGeom = new THREE.PlaneGeometry(20, 20);
var imgSrc = "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png"
var mesh;
var tex = new THREE.TextureLoader().load(imgSrc, (tex) => {
tex.needsUpdate = true;
mesh.scale.set(1.0, tex.image.height / tex.image.width, 1.0);
});
var material = new THREE.MeshLambertMaterial({
color: 0xffffff,
map: tex
});
mesh = new THREE.Mesh(planeGeom, material);
scene.add(mesh);
renderer.setClearColor(0xdddddd, 1);
(function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
The accepted answer works but has to use the callback to set the width since the loader is asynchronous. Nowadays one can also use the loadAsync method, which IMO makes the code more readable:
const getImageRatioPlane = async () => {
const texture = await new TextureLoader().loadAsync(imgSrc);
const material = new MeshBasicMaterial({ map: texture });
const geometry = new PlaneGeometry(texture.image.width, texture.image.height);
const plane = new Mesh(geometry, material);
}

Verifying if a point is inside a cube in three.js

I have created a cube as:
var cubeGeometry = new THREE.BoxGeometry( 1, 1, 1 );
var cubeMaterial = new THREE.MeshLambertMaterial( { color:
0xffff00,wireframe: true } );
var cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
cube.position.x = p.x;
cube.position.y = p.y;
cube.position.z = p.z;
scene.add(cube);
p is a input point to my function. So this code creates a cube at position p and adds it to the scene.
How can I check that some point,say A, lies inside this cube? I couldn't find any helper function like containsPoint etc for Three.Mesh. I may do some additional checks to verify, but I am looking for a Three.js function.
You can create THREE.Box3() instance, using its .setFromObject() the cube as the parameter, then call .containsPoint(), passing the point you want to check as the parameter to this method:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 5, 10);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var cube = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
cube.position.set(0, 1, 0);
scene.add(cube);
var pointA = new THREE.Vector3(0, 1, 0);
var pointB = new THREE.Vector3(2, 1, 0);
point(pointA, 0x00ff00);
point(pointB, "yellow");
function point(point, color) {
p = new THREE.Mesh(new THREE.SphereGeometry(0.25, 4, 2), new THREE.MeshBasicMaterial({
color: color
}));
p.position.copy(point);
scene.add(p);
}
var bb = new THREE.Box3(); // for re-use
bb.setFromObject(cube);
console.log(bb);
console.log(bb.containsPoint(pointA), bb.containsPoint(pointB));
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
cube.updateMatrixWorld(); //Make sure the object matrix is current with the position/rotation/scaling of the object...
var localPt = cube.worldToLocal(yourPoint.clone()); //Transform the point from world space into the objects space
if(Math.abs(localPt.x)<=0.5&&Math.abs(localPt.y)<=0.5&&Math.abs(localPt.z)<=0.5)
console.log("Point is inside!"); //Check if all the axis are within the size of the cube.. if your cube sizes arent 1,1,1, you'll have to adjust these checks to be half of width/height/depth..
Something like that?
#prisoner849
Your solution doesn't work if the box is rotated.
Here's an illustration of the problem. I render both solutions and you can see where the Box3 version breaks with the rotated cube, whereas the analytical once works.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 5, 10);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var boxDimensions = new THREE.Vector3(2,2,2);
var cube = new THREE.Mesh(new THREE.BoxGeometry(boxDimensions.x,boxDimensions.y,boxDimensions.z), new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
cube.position.set(0, 1, 0);
cube.rotation.y = Math.PI*0.25;
scene.add(cube);
var pointA = new THREE.Vector3(0.95, 0.95, 0.95);
var pointC = new THREE.Vector3(-0.65, 0.65, -0.65);
var pa = point(pointA, 0x00ff00);
var pc = point(pointC, 0x00ff00);
function point(point, color) {
p = new THREE.Mesh(new THREE.SphereGeometry(0.25, 4, 2), new THREE.MeshBasicMaterial({
color: color
}));
p.position.copy(point);
scene.add(p);
return p;
}
var bb = new THREE.Box3(); // for re-use
bb.setFromObject(cube);
console.log(bb);
function correctPointInBox(pt,cube,boxDim){
cube.updateMatrixWorld(); //Make sure the object matrix is current with the position/rotation/scaling of the object...
var localPt = cube.worldToLocal(pt.clone()); //Transform the point from world space into the objects space
if(Math.abs(localPt.x)<=boxDim.x*0.5&&Math.abs(localPt.y)<=boxDim.y*0.5&&Math.abs(localPt.z)<=boxDim.z*0.5)
return true;
else
return false;
}
render();
function render() {
pa.position.x = Math.sin(performance.now()*0.001)*2;
pc.position.z = Math.cos(performance.now()*0.001)*2;
if(bb.containsPoint(pa.position))
pa.material.color.set("red")
else
pa.material.color.set("green")
if(correctPointInBox(pc.position,cube,boxDimensions))
pc.material.color.set("red")
else
pc.material.color.set("green")
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Create Rope in Three.js using Physics from Ammo.js or Cannon.js

I have been trying to create in three.js a rope hanging from a point using any of the 3D physics libraries (ammo.js, cannon.js), but the only one I have successfully done is with (2D)verlet.js.
I really need and want to create it in 3D because I need two ropes attached to a midpoint so that I can show the instability of the midpoint as a load is applied. Something similar as the attached image.
enter image description here
To be honest, I have not idea how to start, I have some experience with Three.js, but non with ammo.js or cannon.js. So far I have been trying to understand the codes for the examples in these links with not success.
http://schteppe.github.io/cannon.js/demos/constraints.html
https://threejs.org/examples/#webgl_physics_rope
I even tried to make a rope using spring function from cannon.js, but you can see that my example is not success.
Can somebody please help me or guide me into the correct way to begin my task?
This is the Code I began to write using Cannon.js:
function initCannon()
{
world = new CANNON.World();
world.gravity.set(.2,-10,.2);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
var mass = 1;
var damping = 1;
// STATIC SPHERE
var sphereShape = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
mass = 0;
sphereBody = new CANNON.Body({ mass: 0 });
sphereBody.addShape(sphereShape);
sphereBody.position.set(.5,8,.5);
world.addBody(sphereBody);
// DINAMIC SPHERE 1
var shape = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body = new CANNON.Body({ mass: 1 });
body.addShape(shape);
body.angularDamping = damping;
body.position.set(0,8,0);
world.addBody(body);
// DINAMIC SPHERE 2
var shape2 = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body2 = new CANNON.Body({ mass: 1 });
body2.addShape(shape2);
body2.angularDamping = damping;
body2.position.set(0,8,0);
world.addBody(body2);
// DINAMIC SPHERE 3
var shape3 = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body3 = new CANNON.Body({ mass: 1 });
body3.addShape(shape3);
body3.angularDamping = damping;
body3.position.set(0,8,0);
world.addBody(body3);
var size = 1;
var rebote = 1;
var spring = new CANNON.Spring(body,sphereBody,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
var spring2 = new CANNON.Spring(body2, body,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
var spring3 = new CANNON.Spring(body3, body2,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
world.addEventListener("postStep",function(event){ spring.applyForce(); });
world.addEventListener("postStep",function(event){ spring2.applyForce(); });
world.addEventListener("postStep",function(event){ spring3.applyForce(); });
}
function initThree()
{
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.y = 3;camera.position.z = 15;
scene.add( camera );
controls = new THREE.TrackballControls( camera );
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
var material_wire = new THREE.MeshBasicMaterial( { color: 0xFFFFFF, wireframe: true } );
var sphere_size = .8;
var segmentos = 5;
geometry_sphere = new THREE.SphereGeometry( sphere_size, segmentos, segmentos );
sphere = new THREE.Mesh( geometry_sphere, material_wire );
scene.add( sphere );
geometry = new THREE.SphereGeometry( sphere_size, segmentos,segmentos ); // RRT DEFINE TAMANO DE CUBE
mesh = new THREE.Mesh( geometry, material_wire );
scene.add( mesh );
mesh2 = new THREE.Mesh( geometry, material_wire );
scene.add( mesh2 );
mesh3 = new THREE.Mesh( geometry, material_wire );
scene.add( mesh3 );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
updatePhysics();
render();
}
function updatePhysics() {
// Step the physics world
world.step(timeStep);
sphere.position.copy(sphereBody.position);
mesh.position.copy(body.position); // HACE QUE SE VEA
mesh2.position.copy(body2.position);
mesh3.position.copy(body3.position);
}
function render() {
renderer.render( scene, camera );
}

Three.js controlling shadows

I'm having trouble controlling shadows in THREE.js. First off, the shadow in my scene is way too dark. From what I've read, there was a shadowDarkness property, that is know longer available in the current version of three.js. Does anyone know a work around?
Also, in the attached image: the "backface" geometry is not occluding light on the shadow of the seat - however, you can see the backface of the stool in the reflection of the sphere(cubeCamera). Does anyone know how to fix that?
On a side note: chrome gives me an error "Uncaught TypeError: Cannot set property 'visible' of undefined," regarding the
frameMesh.visible = false;
cubeCameraFrame.position.copy(frameMesh.position);
cubeCameraFrame.updateCubeMap(renderer, scene);
frameMesh.visible = true;
part of my code. Could that be effecting the shadows in some way? I can comment that part of the code and it will have little effect on the stoolframes "reflective" appearance. However it then no longer is reflects in the sphere. Any help is much appreciated.
///webGL - Locking down the Basics
/////////////////////////////////////////////////////////////Environment Settings///////////////////////////////////////////////////////////////////////
///Renderer
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled = true;
document.body.appendChild(renderer.domElement);
///Camera's
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
scene.add(camera);
camera.position.set(0, 16, 25);
camera.rotation.x += -0.32;
var cubeCameraSphere = new THREE.CubeCamera(1, 1000, 256); // parameters: near, far, resolution
cubeCameraSphere.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter; // mipmap filter
scene.add(cubeCameraSphere);
var cubeCameraFrame = new THREE.CubeCamera(1, 1000, 256); // parameters: near, far, resolution
cubeCameraFrame.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter; // mipmap filter
scene.add(cubeCameraFrame);
///Controls
///Lights
var lightSpot_Right = new THREE.SpotLight(0xffffff);
lightSpot_Right.position.set(50, 50, 0);
lightSpot_Right.intensity = 1.25;
lightSpot_Right.castShadow = true;
lightSpot_Right.shadowDarkness = 0.1;
lightSpot_Right.shadowMapWidth = 2048;
lightSpot_Right.shadowMapHeight = 2048;
lightSpot_Right.shadowCameraNear = 1;
lightSpot_Right.shadowCameraFar = 100;
lightSpot_Right.shadowCameraFov = 65;
scene.add(lightSpot_Right);
var lightDirect_Left = new THREE.DirectionalLight(0xffffff, 0.25);
lightDirect_Left.position.set(-1, 0, 0);
scene.add(lightDirect_Left);
///Loaders
var loadTexture = new THREE.TextureLoader();
var loader = new THREE.JSONLoader();
///skyBox
var imagePrefix = "textures/";
var directions = ["skyboxRight", "skyboxLeft", "skyboxTop", "skyboxBottom", "skyboxFront", "skyboxBack"];
var imageSuffix = ".jpg";
var skyMaterialArray = [];
for (var i = 0; i < 6; i++)
skyMaterialArray.push(new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(imagePrefix + directions[i] + imageSuffix),
side: THREE.BackSide
}));
var skyMaterial = new THREE.MeshFaceMaterial(skyMaterialArray);
var skyGeometry = new THREE.CubeGeometry(1000, 1000, 1000);
var skyBox = new THREE.Mesh(skyGeometry, skyMaterial);
scene.add(skyBox);
////////////////////////////////////////////////////////Object Settings//////////////////////////////////////////////////////////////////
//Textures
var seatTexture = loadTexture.load("textures/Maharam_Mister_Notice_Diffuse.jpg");
seatTexture.wrapS = THREE.RepeatWrapping;
seatTexture.wrapT = THREE.RepeatWrapping;
seatTexture.repeat.set(3, 3);
var conceteDiffuse = loadTexture.load("textures/Contrete_Diffuse.jpg");
conceteDiffuse.wrapS = THREE.RepeatWrapping;
conceteDiffuse.wrapT = THREE.RepeatWrapping;
conceteDiffuse.repeat.set(3, 3);
var conceteNormal = loadTexture.load("textures/Contrete_Normal.jpg");
conceteNormal.wrapS = THREE.RepeatWrapping;
conceteNormal.wrapT = THREE.RepeatWrapping;
conceteNormal.repeat.set(3, 3);
var conceteSpecular = loadTexture.load("textures/Contrete_Specular.jpg");
conceteSpecular.wrapS = THREE.RepeatWrapping;
conceteSpecular.wrapT = THREE.RepeatWrapping;
conceteSpecular.repeat.set(3, 3);
///Materials
var seatMaterial = new THREE.MeshLambertMaterial({
map: seatTexture,
side: THREE.DoubleSide
});
var frameMaterial = new THREE.MeshPhongMaterial({
envMap: cubeCameraFrame.renderTarget,
color: 0xcccccc,
emissive: 0x404040,
shininess: 10,
reflectivity: .8
});
var frameHardwareMat = new THREE.MeshPhongMaterial({
color: 0x000000
});
var feetMat = new THREE.MeshPhongMaterial({
color: 0x050505,
shininess: 99
});
var sphereMat = new THREE.MeshPhongMaterial({
envMap: cubeCameraSphere.renderTarget
});
var groundMat = new THREE.MeshPhongMaterial({
map: conceteDiffuse,
specularMap: conceteSpecular,
normalMap: conceteNormal,
normalScale: new THREE.Vector2( 0.0, 0.6 ),
shininess: 50
});
///Geometry and Meshes
var barStool = new THREE.Object3D();
scene.add(barStool);
var seatMesh;
loader.load("models/stoolSeat.js", function (geometry, material) {
seatMesh = new THREE.Mesh(geometry, seatMaterial);
seatMesh.scale.set(.5, .5, .5);
seatMesh.castShadow = true;
seatMesh.receiveShadow = true;
barStool.add(seatMesh);
});
var frameMesh;
loader.load("models/stoolFrame.js", function (geometry, material) {
frameMesh = new THREE.Mesh(geometry, frameMaterial);
frameMesh.scale.set(.5, .5, .5);
frameMesh.castShadow = true;
barStool.add(frameMesh);
});
var frameFeetMesh;
loader.load("models/stoolFeet.js", function (geometry, material) {
frameFeetMesh = new THREE.Mesh(geometry, feetMat);
frameFeetMesh.scale.set(.5, .5, .5);
frameFeetMesh.castShadow = true;
barStool.add(frameFeetMesh);
});
var frameHardwareMesh;
loader.load("models/stoolHardware.js", function (geomtry, material) {
frameHardwareMesh = new THREE.Mesh(geomtry, frameHardwareMat);
frameHardwareMesh.scale.set(.5, .5, .5);
barStool.add(frameHardwareMesh);
});
var sphereGeo = new THREE.SphereGeometry(2.5, 50, 50);
var sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphereMesh);
sphereMesh.position.set(-10, 5, 0);
var groundGeo = new THREE.PlaneGeometry(100, 50, 1);
var groundMesh = new THREE.Mesh(groundGeo, groundMat);
scene.add(groundMesh);
groundMesh.rotation.x = -90 * Math.PI / 180;
groundMesh.receiveShadow = true;
///Render Scene
var render = function () {
requestAnimationFrame(render);
barStool.rotation.y += 0.01;
skyBox.rotation.y -= 0.0002;
sphereMesh.visible = false;
cubeCameraSphere.position.copy(sphereMesh.position);
cubeCameraSphere.updateCubeMap(renderer, scene);
sphereMesh.visible = true;
//frameMesh.visible = false;
//cubeCameraFrame.position.copy(frameMesh.position);
//cubeCameraFrame.updateCubeMap(renderer, scene);
//frameMesh.visible = true;
renderer.render(scene, camera);
};
render();
Shadow darkness has been removed. The best work-around is to add ambient light to your scene.
scene.add( new THREE.AmbientLight( 0xffffff, 0.3 );
You may want to concurrently reduce the intensity of your SpotLight.
The shadow is actually correct given only back faces are casting shadows. It appears that the stool is hollow under the seat -- in other words, the seat is not a closed volume. Add a bottom to the underside of your seat.
Alternatively, you can leave your model as-is and experiment with
renderer.shadowMap.cullFace = THREE.CullFaceNone;
Finally, you are getting the error because you are accessing frameMesh in the animation loop before it is defined in the loader callback. The callback is asynchronous.
if ( frameMesh !== undefined ) {
// your code
}
three.js r.75

Resources