Default Object.rotation's axis of rotation (Three.js) - three.js

Does changing the value of an object's rotation property rotate the object about the world axes or the object's axes? For eg
object.rotation.x += 2
Will this rotate the object about the world X axis or the object's X axis?
I tried the following example :
var materials = [];
materials.push( [ new THREE.MeshBasicMaterial( { color: 0xff0000 } ) ] );
materials.push( [ new THREE.MeshBasicMaterial( { color: 0xff0000 } ) ] );
materials.push( [ new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) ] );
materials.push( [ new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) ] );
materials.push( [ new THREE.MeshBasicMaterial( { color: 0x0000ff } ) ] );
materials.push( [ new THREE.MeshBasicMaterial( { color: 0x0000ff } ) ] );
object = new THREE.Mesh( new THREE.CubeGeometry( 20, 20, 20, 1, 1, 1, materials ), new THREE.MeshFaceMaterial() );
object.position.x = 0;
object.position.y = 0;
object.position.z = 0;
object.rotation.x = 0;
object.rotation.y = 0;
object.rotation.z = 0;
object.scale.x = 1;
object.scale.y = 1;
object.scale.z = 1;
scene.add( object );
After i have added the object to the scene i tried the following -
object.rotation.x += Math.PI/4;
object.rotation.y += Math.PI/4;
object.rotation.z += Math.PI/4;
Until now the object rotates with respect to its own X,Y and Z axes.
but doing:
object.rotation.x += Math.Pi/4;
now rotates the object 45 degrees about the World X axis instead of the object's X axis.

The rotations are in local space. However, they are evaluated in a specific order which you can set yourself. The object.rotation property is an Euler, and as you can read in the description of the order-property:
The order in which to apply rotations. Default is 'XYZ', which means
that the object will first be rotated around its X axis, then its Y
axis and finally its Z axis. Other possibilities are: 'YZX', 'ZXY',
'XZY', 'YXZ' and 'ZYX'. These must be in upper case.
Three.js uses intrinsic Tait-Bryan angles. This means that rotations
are performed with respect to the local coordinate system. That is,
for order 'XYZ', the rotation is first around the local-X axis (which
is the same as the world-X axis), then around local-Y (which may now
be different from the world Y-axis), then local-Z (which may be
different from the world Z-axis).
(Emphasis added by me).
Consider the following example, every cube is updated with the same y-axis rotation. In every case the rotation is happening around the y-axis in local space, but:
The first cube has not been rotated in any other axis, making its
local space axis the same as the world space axis.
The second cube has been rotated around its x-axis, which means that
the y-axis is also rotated.
The third cube has also been rotated, but the order of rotation is
changed so that the y-axis rotation happens first, while it is still the same as the world y-axis, and the rotation around x happens afterward.
const canvas = document.getElementById("canvas");
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(10, 2, 20, 40);
const renderer = new THREE.WebGLRenderer({ canvas });
const light = new THREE.PointLight();
light.position.set(0, 5, 10)
scene.add(light);
camera.position.set(0, 0, 25);
const material = new THREE.MeshLambertMaterial();
const geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
const cube1 = new THREE.Mesh(geometry, material);
const cube2 = new THREE.Mesh(geometry, material);
const cube3 = new THREE.Mesh(geometry, material);
cube1.position.set(-2, 0, 0);
cube2.position.set( 0, 0, 0);
cube3.position.set( 2, 0, 0);
scene.add(cube1);
scene.add(cube2);
scene.add(cube3);
//The first cube is not rotated
cube1.rotation.set(0, 0, 0);
//The second cube is rotated pi/4 rad around X
cube2.rotation.set(Math.PI/4, 0, 0);
//The third cube is rotated pi/4 rad around X
//AND the rotation order is set to YXZ to make the y-rotation happen first
cube3.rotation.set(Math.PI/4, 0, 0);
cube3.rotation.order = "YXZ";
let t0 = performance.now();
function update(){
const t1 = performance.now();
const rotation = 0.001 * (t1 - t0);
cube1.rotation.y += rotation;
cube2.rotation.y += rotation;
cube3.rotation.y += rotation;
renderer.render(scene, camera);
t0 = t1;
requestAnimationFrame(update);
}
update();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.js"></script>
<canvas id="canvas" width="400" height="200"></canvas>

Related

Three.js place one box upon another

To display rack structure, placing one box upon another. But y Position calculation fails.Currently creates gap between boxes. Please inform how could it be fixed, whether camera or light effect creates a problem. As per rack size, altering y position. Data contain size and starting place.
```
var data = [{"id": 10075,"size": 3,"slotNumber": 1},{"id": 10174,"size": 7,"slotNumber": 4}];
var rackListGroup;
init();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x999999 );
var light = new THREE.AmbientLight( 0xffffff );
light.position.set( 0.5, 1.0, 0.5 ).normalize();
scene.add( light );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.fromArray([0, 0, 140]);
scene.add( camera );
rackListGroup = new THREE.Mesh();
rackListGroup.name = "Rack List"
var i;
for (i = 0; i < 1; i++) {
rackListGroup.add(drawRack(10, i))
}
scene.add(rackListGroup);
render();
}
function drawRack(size, rackNo){
var rackGroup = new THREE.Group();
rackGroup.name = "rack "+rackNo;
var yPosition = -42;
var xPosition = -20 + parseInt(rackNo)*40;
var slot = 1, counter = 0;
var slotWidth = 5;
while(slot <= parseInt(size)){
var slotSize = data[counter].size;
slot = slot + slotSize;
yPosition = yPosition + slotSize* slotWidth;
var geometry = new THREE.BoxGeometry( 30, slotWidth*slotSize, 5 );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var shape = new THREE.Mesh( geometry, material );
shape.name = data[counter].name;
shape.position.set(xPosition, yPosition, 0);
rackGroup.add(shape);
var boxGeometry = new THREE.BoxBufferGeometry( 30, slotWidth*slotSize, 5, 1, 1, 1 );
var boxMaterial = new THREE.MeshBasicMaterial( { wireframe:true } );
var box = new THREE.Mesh( boxGeometry, boxMaterial );
box.name = data[counter].name;
box.position.set(xPosition, yPosition, 0);
rackGroup.add(box);
if(counter+1 < data.length){
counter++;
}
}
return rackGroup;
}
```
I've tried your code and I see a misunderstanding between the objects position and the objects height to be able to stack them on top of each other.
You use one variable for yPosition and you need 2 variables, the reason is that geometries are positioned based on its axes center, so it means a 15 units height mesh positioned at y=0 it will place indeed at -7.5 units below the y=0 position and the upper side of the geometry will be at 7.5. So next slot to stack will be needed to place (conceptually) at y = 7.5 + (topSlotHeight / 2).
That's why your calculation of the next slot to stack y position is wrong. I have created this fiddle with the solution, and I have added a gridHelper at y=0 for your reference and the OrbitControls to be able to check it better. Now it works perfectly doing like this, storing the accumulated base position of the previous slot in yBaseHeight and the yPosition for the slot on top:
var slotHeight = (slotSize * slotWidth);
yPosition = yBaseHeight + (slotHeight / 2);
yBaseHeight = yBaseHeight + slotHeight;
PD.- I saw you start placing objects at y=-42, I started from y=0 to show better the effect.

threejs - how to rotate an object in relation to mouse to a degree setting from its current center point

I have a threejs model in a scene whose 0,0,0 point is at its end. I've had to rotate it so that its resting position is at the angle I want, and animate it into the scene, so neither the position nor the rotation is at 0,0,0. Furthermore, the camera has been positioned and set to look at the object, so its position and rotation have been changed.
I want to get the user's mouse coordinates, and just have the model rotate around its center point on a world Y axis a certain number of max and min degrees. I know how to map the mouse coordinates to the degree / radian angle I want, but how do I tell the model to rotate?
I've tried model.rotation.y = [radians], and it rotates, I'm assuming, based on whatever rotation matrix it currently has (or at the very least, not the way I expect it to). And if I do rotateOnWorldAxis it rotates from its 0,0,0 point at which it was imported, which not where I want it to be, and furthermore isn't an absolute number of degrees (i.e. it rotates 30 degrees from where it's at currently each mouse move, rather than to 30 degrees on the world origin.
How do I get it to rotate on its center point to a certain degree angle on the world Y axis?
Model position is at {_x: 0, _y: -0.3, _z: -2} and its rotation is at {x: -2, y: 2.4, z: 0}
Camera position is {x: 0, y: 0, z: 5} and rotation {_x: 0.3926990816987242, _y: 0, _z: -0}.
Current code is:
const target = this.mouseTarget;
const mouseX = clientX - this.halfWidth; //halfWidth is half the screen width, client X is the mouse e.clientX
const mouseY = clientY - this.halfHeight;
target.x += (mouseX - target.x) * 0.02;
target.y += (-mouseY - target.y) * 0.02;
target.z = this.camera.position.z; // assuming the camera is located at ( 0, 0, z );
const maxRotDeg = 30;
const maxRot = this.degToRad(maxRotDeg);
const rotVal = this.mapValue(
target.x,
-this.halfWidth,
this.halfWidth,
-maxRot,
maxRot,
); //works to give me the radians that I want for rotation
//this.modelGroup.rotateOnWorldAxis(this.rotationAxisY, rotVal); //doesn't work
//this.modelGroup.lookAt(target); //doesn't work
The simplest generic way to rotate any object anywhere in the scene hierarchy around some arbitrary rotation center is to make an Object3D where you want that rotation center to be. Let's call it the "pivotPoint". Then take the thing you want to rotate, attach it to the pivotPoint. rotate the pivotPoint, then put the object back where it was (re-attach it to it's previous parent). In other words
const pivotPoint = new THREE.Object3D();
pivotPoint.position.set(...); // optional
pivotPoint.rotation.set(...); // optional
someParent.add(pivotPoint)
Then to rotate some other thing around that point
const parent = thingToRotate.parent;
pivotPoint.attach(thingToRotate);
pivotPoint.rotation.set( ... ); // do the rotation
parent.attach(thingToRotate);
That is the most generic way to rotate around any point in any orientation regardless of how deep in the scene hierarchy the thingToRotate is.
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 50;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 3, 3);
camera.lookAt(0, 1, 0);
const scene = new THREE.Scene();
scene.background = new THREE.Color('white');
[[-1, 2, 4], [1, 2, -3]].forEach(pos => {
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(...pos);
scene.add(light);
});
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
function makeInstance(parent, pos, rot, scale) {
const material = new THREE.MeshPhongMaterial({color: Math.random() * 0xFFFFFF | 0});
const mesh = new THREE.Mesh(geometry, material);
parent.add(mesh);
mesh.position.set(...pos);
mesh.rotation.set(...rot);
return mesh;
}
const m1 = makeInstance(scene, [0, 0, 0], [0, 0.7, 0]);
const m2 = makeInstance(m1, [1, 1, 0], [0.3, 0.5, 0]);
const m3 = makeInstance(m1, [-1, 1, 0], [-0.9, 0.5, 0]);
const m4 = makeInstance(m2, [1, 1, 0], [-0.4, 1.3, 0.8]);
let thingToRotate = m3;
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
const pivotPoint = new THREE.Object3D();
scene.add(pivotPoint);
let then = 0;
function render(now) {
now *= 0.001;
delta = now - then;
then = now;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
{
// put pivotPoint at origin of thingToRotate in world space
// note: an object's origin might not be its center. If oyu
// want its center you need to compute its center
thingToRotate.getWorldPosition(pivotPoint.position);
// reset rotation for pivotPoint
pivotPoint.rotation.set(0, 0, 0);
// rotate thingToRotate around pivotPoint's yAxis
const parent = thingToRotate.parent;
pivotPoint.attach(thingToRotate);
pivotPoint.rotation.y = delta;
parent.attach(thingToRotate);
}
m1.rotation.y -= delta * 0.1;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function setClick(selector, thing) {
document.querySelector(selector).addEventListener('input', () => {
thingToRotate = thing;
});
}
setClick('#m1', m1);
setClick('#m2', m2);
setClick('#m3', m3);
setClick('#m4', m4);
requestAnimationFrame(render);
}
main();
body {
margin: 0;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
#ui {
position: absolute;
left: 0;
top: 0;
}
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.min.js"></script>
<div id="ui">
<div><input type="radio" name="thing" id="m1"><label for="m1">m1</label></div>
<div><input type="radio" name="thing" id="m2"><label for="m2">m2</label></div>
<div><input type="radio" name="thing" id="m3" checked><label for="m3">m3</label></div>
<div><input type="radio" name="thing" id="m4"><label for="m4">m4</label></div>
</div>
There are lots other shortcuts but each one requires knowing exactly how you have your scene setup.
For example if you the only thing you ever want to do is rotate things around the world Y axis but those things themselves have rotation then parent them to some other Object3D, set the position on the Object3D and the rotation on the thing.
Example: Imagine you had some thing oriented and rotated like this
scene.add(thing);
thing.position.set(100, 200, 300); // some arbitrary position
thing.rotation.set(1, 2, 3); // some arbitrary rotation
Change it to this
const helper = new THREE.Object3D();
scene.add(helper);
helper.position.set(100, 200, 300); // some arbitrary position on helper
thing.rotation.set(1, 2, 3); // some arbitrary rotation on thing
Now you can rotate helper.rotation.y and thing will rotate around its origin at the world Y axis.
If you want to rotate around the center of some object then you need to compute its center (center != origin though they are often the same) and add other helpers. See this article toward the bottom where it makes 3d text rotate around its center because its origin is on the left off the text.
This article also covers moving rotation points by adding helpers like above.

In three.js how to position image texture similar to 'contain' in css?

My image texture is positioned relative to the center of 3d space instead of mesh and I don't quite understand what determines its size.
Here is example showing how the same image is positioned on different meshes:
https://imgur.com/glHE97L
I'd like the image be in the center of the mesh and it's size set similar as 'contain' in css.
The mesh is flat plane created using ShapeBufferGeometry:
const shape = new THREE.Shape( edgePoints );
const geometry = new THREE.ShapeBufferGeometry( shape );
To see any image I have to set:
texture.repeat.set(0.001, 0.001);
Not sure if that matters but after creating the mesh I than set its position and rotation:
mesh.position.copy( position[0] );
mesh.rotation.set( rotation[0], rotation[1], rotation[2] );
I've tried setting those:
mesh.updateMatrixWorld( true );
mesh.geometry.computeBoundingSphere();
mesh.geometry.verticesNeedUpdate = true;
mesh.geometry.elementsNeedUpdate = true;
mesh.geometry.morphTargetsNeedUpdate = true;
mesh.geometry.uvsNeedUpdate = true;
mesh.geometry.normalsNeedUpdate = true;
mesh.geometry.colorsNeedUpdate = true;
mesh.geometry.tangentsNeedUpdate = true;
texture.needsUpdate = true;
I've played with wrapS / wrapT and offset.
I've checked UV's - I don't yet fully understand this concept but it seems fine. Example of UV for one mesh (I understand those are XY coordinates and they seem to reflect the actual corners of my mesh):
uv: Float32BufferAttribute
array: Float32Array(8)
0: -208
1: 188
2: 338
3: 188
4: 338
5: 12
6: -208
7: 12
I've tried setting:
texture.repeat.set(imgHeight/geometryHeight/1000, imgWidth/geometryWidth/1000);
This is how THREE.ShapeGeometry() computes UV coordinate:
https://github.com/mrdoob/three.js/blob/e622cc7890e86663011d12ec405847baa4068515/src/geometries/ShapeGeometry.js#L157
But you can re-compute them, to put in range [0..1].
Here is an example, click the button to re-compute uvs of the shape geometry:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var grid = new THREE.GridHelper(10, 10);
grid.rotation.x = Math.PI * 0.5;
scene.add(grid);
var points = [
new THREE.Vector2(0, 5),
new THREE.Vector2(-5, 4),
new THREE.Vector2(-3, -3),
new THREE.Vector2(2, -5),
new THREE.Vector2(5, 0)
];
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeBufferGeometry(shape);
var shapeMat = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/uv_grid_opengl.jpg")
});
var mesh = new THREE.Mesh(shapeGeom, shapeMat);
scene.add(mesh);
btnRecalc.addEventListener("click", onClick);
var box3 = new THREE.Box3();
var size = new THREE.Vector3();
var v3 = new THREE.Vector3(); // for re-use
function onClick(event) {
box3.setFromObject(mesh); // get AABB of the shape mesh
box3.getSize(size); // get size of that box
var pos = shapeGeom.attributes.position;
var uv = shapeGeom.attributes.uv;
for (let i = 0; i < pos.count; i++) {
v3.fromBufferAttribute(pos, i);
v3.subVectors(v3, box3.min).divide(size); // cast world uvs to range 0..1
uv.setXY(i, v3.x, v3.y);
}
uv.needsUpdate = true; // set it to true to make changes visible
}
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<button id="btnRecalc" style="position: absolute;">Re-calculate UVs</button>

ThreeJS raycasting is different in R81 than R71

I have a plane with a mesh on it. My code draws a ball when the user double clicks on the mesh. This works just fine in R71 but as soon as I switched to R81 raycaster doesn't return an intersect. Here's the code:
In init():
// Plane
plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 1000, 1000, 3, 3 ),
new THREE.MeshBasicMaterial( { color: 0xff0000, opacity: .5, transparent: true } )
);
plane.visible = false;
scene.add( plane );
planes.push(plane);
In doubleClickEvent():
event.preventDefault();
var mouse = new THREE.Vector2((event.clientX / window.innerWidth ) * 2 - 1, -(((event.clientY / window.innerHeight ) * 2 - 1)));
var directionVector = new THREE.Vector3();
directionVector.set(mouse.x, mouse.y, 0.1);
directionVector.unproject(camera);
directionVector.sub(camera.position);
directionVector.normalize();
raycaster.set(camera.position, directionVector);
intersects = raycaster.intersectObjects(planes);
if (intersects.length) {
var sphereParent = new THREE.Object3D();
var sphereGeometry = new THREE.SphereGeometry(.1, 16, 8);
var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphereParent.add(sphere);
sphereParent.position.set(intersects[0].point.x, intersects[0].point.y, 0.0);
scene.add(sphereParent);
objects.push(sphereParent);
}
If I change
intersects = raycaster.intersectObjects(planes);
to
intersects = raycaster.intersectObjects(scene.children);
the ball gets drawn but it gets drawn on the wrong position.
Any ideas?
I found the answer. The reason why the raycast isn't working is because the plane's visibility is false. The solution is to change the visibility of the material visibility rather the plane.

really weird ghosty shadows using three.js

I'm using three.js to make some solar system, all my objects are sphere (suns and planets), but I found this really weird and ghosty square shadow:
Another ghost shadow seems to be that, the shadow that sphere A casts on sphere B, appears on both the front and back side of sphere B, like this:
I am so confused since I don't really remember create any square stuff and I've checked my code for like million times without any finding.
Finally, I dismissed all the lights in the world, and set the background to light color, it appears:
But when I move my camera to the back of it, it just disappears, like a "1-dimension" square created by some high-level creature from the universe.
This is my final project which is due next week, I really don't know how to explain this to my professor.
Appreciate any help!
Thanks a lot!
below is my code that creates objects:
function init() {
container = document.createElement('div');
document.body.appendChild(container);
renderer = new THREE.WebGLRenderer({
antialias : true, alpha: true
});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.shadowMapEnabled = true;
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.updateMatrixWorld(true);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera.position.set(5,5,5);
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.2;
var light = new THREE.AmbientLight( 0x222222 );
scene.add( light ); // this is the light I tried to close
var light = new THREE.DirectionalLight( 0xffffff, 0 );
light.position.set(0,0,5);
scene.add( light ); // this is the light I tried to close
light.castShadow = true;
light.shadowCameraNear = 0.01;
light.shadowCameraFar = 15;
light.shadowCameraFov = 45;
light.shadowCameraLeft = -1;
light.shadowCameraRight = 1;
light.shadowCameraTop = 1;
light.shadowCameraBottom= -1;
//light.shadowCameraVisible = true
light.shadowBias = 0.001;
light.shadowDarkness = 0.2;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
//////////////////////////////////////////////////////////////////////////////////
// render the scene //
//////////////////////////////////////////////////////////////////////////////////
onRenderFcts.push(function(){
controls.update();
renderer.render( scene, camera );
});
window.addEventListener('keydown', onKeyDown, false);
renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
renderer.domElement.addEventListener( 'click', onMouseClick, false );
}
function createSun (){
var geometry = new THREE.SphereGeometry(0.5, 32, 32)
var texture = THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/sunmap.jpg')
var material = new THREE.MeshPhongMaterial({
map : texture,
bumpMap : texture,
bumpScale: 0.05,
emissive: new THREE.Color('#ff9933'),
specular: new THREE.Color('#ffff66'),
shininess: 800,
wireframeLinewidth: 500
})
var mesh = new THREE.Mesh(geometry, material)
mesh.receiveShadow = true;
mesh.castShadow = true;
mesh.matrixWorldNeedsUpdate = true;
return mesh
}
function createMoon (){
var geometry = new THREE.SphereGeometry(0.5, 32, 32)
var material = new THREE.MeshPhongMaterial({
map : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonmap1k.jpg'),
bumpMap : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonbump1k.jpg'),
bumpScale: 0.002,
})
var mesh = new THREE.Mesh(geometry, material)
return mesh
}
function add_objects() {
// star field
var geometry = new THREE.SphereGeometry(900, 32, 32);
var material = new THREE.MeshBasicMaterial({
map : THREE.ImageUtils.loadTexture('images/earthcloudmap.jpg'),
side : THREE.BackSide
});
var starSphere = new THREE.Mesh(geometry, material);
scene.add(starSphere);
// reference points
originPoint = new THREE.Object3D();
scene.add(originPoint);
onRenderFcts.push(function (delta, now) {
originPoint.rotation.x += rotateFactor * delta;
originPoint.rotation.z += rotateFactor * delta;
});
sunsBasePoint = new THREE.Object3D();
originPoint.add(sunsBasePoint);
onRenderFcts.push(function (delta, now) {
sunsBasePoint.rotation.y += rotateFactor * delta;
sunsBasePoint.rotation.z += rotateFactor * delta;
});
// stars
sun1 = createSun();
sun1.name = 'sun1';
sun1.position.set(0,0,-1.5);
sunsBasePoint.add(sun1);
onRenderFcts.push(function (delta, now) {
sun1.rotation.y -= 1/2 * delta;
sun1.rotation.z += 1/4 * delta;
});
objects.push(sun1);
sun2 = createSun();
sun2.name = 'sun2';
sun2.position.set(1,-1.5,0);
sun2.scale.multiplyScalar(0.8)
sunsBasePoint.add(sun2);
onRenderFcts.push(function (delta, now) {
sun2.rotation.x -= 1/4 * delta;
sun2.rotation.y += 1/8 * delta;
});
objects.push(sun2);
sun3 = createSun();
sun3.name = 'sun3';
sun3.position.set(-1,1,1.5);
sun3.scale.multiplyScalar(1.5);
sunsBasePoint.add(sun3);
onRenderFcts.push(function (delta, now) {
sun3.rotation.y -= 1/8 * delta;
sun3.rotation.x += 1/4 * delta;
});
objects.push(sun3);
threeBodyPlanet = createMoon();
threeBodyPlanet.name = "Three Body Planet";
threeBodyPlanet.position.set(0.5,-0.5,0.5);
threeBodyPlanet.scale.multiplyScalar(1/5);
threeBodyPlanet.receiveShadow = true;
threeBodyPlanet.castShadow = true;
originPoint.add(threeBodyPlanet);
objects.push(threeBodyPlanet);
}
function debug() {
var debugaxis = function(axisLength){
//Shorten the vertex function
function v(x,y,z){
return new THREE.Vertex(new THREE.Vector3(x,y,z));
}
//Create axis (point1, point2, colour)
function createAxis(p1, p2, color){
var line, lineGeometry = new THREE.Geometry(),
lineMat = new THREE.LineBasicMaterial({color: color, lineWidth: 1});
lineGeometry.vertices.push(p1, p2);
line = new THREE.Line(lineGeometry, lineMat);
scene.add(line);
}
createAxis(v(-axisLength/25, 0, 0), v(axisLength, 0, 0), 0xFF0000);
createAxis(v(0, -axisLength/25, 0), v(0, axisLength, 0), 0x00FF00);
createAxis(v(0, 0, -axisLength/25), v(0, 0, axisLength), 0x0000FF);
};
//To use enter the axis length
debugaxis(100);
// lens flares
var textureFlare0 = THREE.ImageUtils.loadTexture( "lensflare0.png" );
var textureFlare2 = THREE.ImageUtils.loadTexture( "lensflare2.png" );
var textureFlare3 = THREE.ImageUtils.loadTexture( "lensflare3.png" );
addLight( 0.55, 0.9, 0.5, 0, 0, 100 );
//addLight( 0.08, 0.8, 0.5, 0, 0, -10 );
//addLight( 0.995, 0.5, 0.9, 50, 50, -10 );
function addLight( h, s, l, x, y, z ) {
var light = new THREE.PointLight( 0xffffff, 1.5, 4500 );
light.color.setHSL( h, s, l );
light.position.set( x, y, z );
scene.add( light );
var flareColor = new THREE.Color( 0xffffff );
flareColor.setHSL( h, s, l + 0.5 );
var lensFlare = new THREE.LensFlare( textureFlare0, 700, -0.1, THREE.AdditiveBlending, flareColor );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 60, 0.6, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 0.7, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 120, 0.9, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 1.0, THREE.AdditiveBlending );
lensFlare.customUpdateCallback = lensFlareUpdateCallback;
lensFlare.position = light.position;
lensFlare.size = 70;
scene.add( lensFlare );
}
function lensFlareUpdateCallback( object ) {
var f, fl = object.lensFlares.length;
var flare;
var vecX = -object.positionScreen.x * 2;
var vecY = -object.positionScreen.y * 2;
//var size = object.size ? object.size : 1000;
for( f = 0; f < fl; f++ ) {
flare = object.lensFlares[ f ];
flare.x = object.positionScreen.x + vecX * flare.distance;
flare.y = object.positionScreen.y + vecY * flare.distance;
//flare.scale = size / camera.distance;
flare.rotation = 0;
}
object.lensFlares[ 2 ].y += 0.025;
object.lensFlares[ 3 ].rotation = object.positionScreen.x * 0.5 + THREE.Math.degToRad( 45 );
};
}
-------------updating-------------
Thanks for yaku's help, I found that the weird square is indeed because of the camera shadow,like in the pics below:
After I increased the shadow parameters, the square shadow seems to be gone, but the remaining shadows on the back of the spheres are still kind of weird in its texture, like this:
It looks like very low resolution shadow made of small squares, why?
Thanks a lot!
------one more question------
All yaku said works!
But I found out there's no shadows of the spheres themselves.
I called
mesh.castShadow = mesh.receiveShadow = true;
every time I create the spheres.
I remember there were these shadows now they are gone...
What might the reason of it?
Thanks!
Not sure, but have you checked the shadow camera dimensions? Looks like the frustum of the shadow camera could be too small, and what you are seeing could be everything inside the frustum is in shadow and the rest unaffected. The light square could be some weird remnant of the shadow camera, shadow maps can be unwieldy..
Set light.shadowCameraVisible = true; and adjust the other shadow parameters so that the box encapsulates the whole scene.

Resources