Rotating a 3d vector in THREE.js on two axes - javascript

Sorry for posting possible duplicate.
I have two 3d vectors:
center ( 0, 0, 0 )
orb ( 0, 0, 100 )
I want to rotate the orb-vector around the center-vector on both X and the Y axes.
What I'm trying to achieve is the make and object always be in view of the camera in the direction it's facing.
I've tried this but with no luck.
var vector = new THREE.Vector3( 0, 0, 100 );
vector.applyAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI * 0.5 );
vector.applyAxisAngle( new THREE.Vector3( 1, 0, 0 ), Math.PI * 0.5 );
orbBall.position.copy(vector);

"What I'm trying to achieve is the make and object always be in view of the camera in the direction it's facing."
If you are simply trying to ensure that orbBall always faces the camera, and both orbBall and the camera are part of the THREE scene then you can just use lookAt like so:
orbBall.lookAt(camera.position);
if you need to align a particular side of orbBall you can use a null dummy Object3D to do it, by adding the dummy node to the scene and orbBall to the dummy, in something like this:
dummy = new THREE.Object3D();
scene.add(camera); // "camera" is defined however
scene.add(dummy);
dummy.add(orbBall); // "orbBall" is created as usual
// ... not to align dummy+orbBall
dummy.lookAt(camera.position);
// ...and you can just rotate orbBall around "inside" dummy, just once,
/// to face however you like

After digging around this issue I realise that it's quite advanced mathematics.
Check out this lecture about quaternions if you're interested:
https://www.youtube.com/watch?v=mHVwd8gYLnI
So I used #bjorke suggestins and used a dummy object, and it works well.
var container, scene, camera, renderer, controls, stats;
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(100, 100, 400);
camera.lookAt(scene.position);
scene.add(camera);
renderer = new THREE.WebGLRenderer( {antialias:true} );
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
var light = new THREE.DirectionalLight(0xffffff); //new THREE.PointLight(0xffffff);
light.position.set( 30, 80, -15 );
scene.add(light);
var boxGeo = new THREE.BoxGeometry( 10, 10, 10);
var axes = new THREE.AxisHelper(1000);
scene.add( axes );
var cameraObj = new THREE.Mesh(boxGeo, new THREE.MeshLambertMaterial( {color: 0x888800}));
scene.add(cameraObj);
var orbSpace = new THREE.Object3D();
scene.add(orbSpace);
var orbBall = new THREE.Mesh(boxGeo, new THREE.MeshLambertMaterial( {color: 0x880088}));
orbBall.position.set(0, 0, cameraObj.position.z + 100);
orbSpace.add(orbBall);
animate();
var camX = 0.3;
var camY = 0;
function animate() {
requestAnimationFrame( animate );
camY += 0.02;
if (camY >= 2) camY = 0;
cameraObj.rotation.x = Math.PI * document.querySelector('#volume').value;
cameraObj.rotation.y = Math.PI * camY;
orbSpace.position.copy(cameraObj.position);
orbSpace.rotation.copy(cameraObj.rotation)
renderer.render( scene, camera );
}
Here's a codepen about how it works:
http://codepen.io/arpo/pen/RrpMJJ
You can update the X angle in the uper right corner

Related

Orbit controls; Angle clamping

I've been working on a mini project recently for a visuals I want to develop and I'm having issues being able to limit the camera rotation based on the Y axis rotation, and I don't quite know why or how I'm having this issue.
I've looked around and all I can find is people wanting to remove the angle clamp, and they always seem to refer to minAzimuthAngle or maxAzimuthAngle, but I can't seem to get it to do anything.
// controls.minAzimuthAngle = -Math.PI, controls.maxAzimuthAngle = Math.PI
I'm just asking here as I can't find much elsewhere to explain my problem. I'm thinking it's just the specifically the way I'm using or rendering the camera but it's hard to find any reference to clamping the angles other than unclamping them.
var renderer, scene, camera; // scene render var creation
var orbitalControl = new THREE.OrbitControls(camera, renderer); //orbitcontrol setup
var controls = new THREE.OrbitControls( camera, renderer); // camera to renderer
controls.addEventListener( 'change', render ); //control listening
scene = new THREE.Scene(), camera; // scene creation
var W = window.innerWidth, H = window.innerHeight; // scene size
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 400); // camera assignment
camera.up = new THREE.Vector3(0,500,0);
controls = new THREE.OrbitControls(camera); // centeralising the camera
controls.target = new THREE.Vector3(500, 200, 500); // controls
controls.addEventListener('change', render); // renderer based on controls
scene.add(camera); // camera to scene
controls.addEventListener( 'change', render ); // control adjustments
controls.screenSpacePanning = false;
controls.enableDamping = true, controls.dampingFactor = 0.25;
controls.enableZoom = false, controls.autoRotate = false;
controls.minPolarAngle = Math.PI / 2 ; // radians
controls.maxPolarAngle = Math.PI / 2 // radians
controls.minAzimuthAngle = -Math.PI * 0.5;
controls.maxAzimuthAngle = Math.PI * 0.5;
controls.addEventListener("change", () => {
if (this.renderer) this.renderer.render(this.scene, camera)});
regardless of whatever I change the min or max AzimuthAngle, it doesn't do anything, but it's the only thing I'm referred to from any other posts.
is there something conflicting with the way I'm trying to render this?
I genuinelly have no clue what the issue is.
Thanks in advance for anyone who responds
github link to the entire project; https://github.com/Thealonic/GENESIS
I'm having issues being able to limit the camera rotation based on the Y axis rotation,
In this case, you have to configure minAzimuthAngle and maxAzimuthAngle. Keep in mind that you can only use values in the range [ - Math.PI, Math.PI ]. Check out how the following example restricts how far you can orbit horizontally.
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 20, 20, 20 );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.minAzimuthAngle = 0;
controls.maxAzimuthAngle = Math.PI * 0.5;
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 20,20, 0 );
scene.add( light );
// axes
scene.add( new THREE.AxesHelper( 20 ) );
// geometry
var geometry = new THREE.SphereGeometry( 5, 12, 8 );
// material
var material = new THREE.MeshPhongMaterial( {
color: 0x00ffff,
flatShading: true,
transparent: true,
opacity: 0.7,
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.115/examples/js/controls/OrbitControls.js"></script>

three.js - Camera on spline doesn't have a uniform speed

I used this cool codepen to have my camera follow a spline :
https://codepen.io/wiledal/pen/WvNvEq
This works great but I want to have a uniform speed during my camera movement.
I played with all the parameters of the CatmullRomCurve3() function but to no avail.
In the following example you can see that it slows down at once when it reaches the curves.
Should I try to have the same intensity of points everywhere all along my spline ? If so how can I do that ?
Thank you very much.
var renderer, scene, camera, spline, camPos, camPosIndex;
function init(){
renderer = new THREE.WebGLRenderer();
scene = new THREE.Scene();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const W = window.innerWidth;
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, .1, 2000 );
spline = new THREE.CatmullRomCurve3([
new THREE.Vector3( -70, 9 ),
new THREE.Vector3( -20, 9 ),
new THREE.Vector3( -13, 9 ),
new THREE.Vector3( 13, -9 ),
new THREE.Vector3( 20, -9 ),
new THREE.Vector3( 70, -9 ),
]);
var points = spline.getPoints(500);
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
// Create the final object to add to the scene
var splineObject = new THREE.Line( geometry, material );
scene.add(splineObject);
camPosIndex = 0;
}
let speed = 1000;
function update() {
renderer.render(scene, camera);
requestAnimationFrame(update);
camPosIndex++;
if (camPosIndex > speed) {
camPosIndex = 0;
}
var camPos = spline.getPoint(camPosIndex / speed);
var camRot = spline.getTangent(camPosIndex / speed);
camera.position.x = camPos.x;
camera.position.y = camPos.y;
camera.position.z = camPos.z + 40; // so I can watch my spline
camera.rotation.x = camRot.x;
camera.rotation.y = camRot.y;
camera.rotation.z = camRot.z;
camera.lookAt(spline.getPoint((camPosIndex+1) / speed));
}
init();
update();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>

Set 3d cube rotation origin

I have a simple 3d cube (BoxGeometry of 100, 100, 100) and I am trying to rotate it. If we call all 100x100x100 a tile - when I rotate it I can see it's overlapping the below tile.
(by changing color, now I totally understand the behaviour).
tl.to(this.cube4.rotation, 0.5, {z: -45* Math.PI/180});
[
What if I want to rotate it based on an anchor point of right bottom? So instead of overflowing inside the below tile, it will overflow that portion to above tile.
So it will look like the green example and not the red example:
The red example here is achieved by
tl.to(this.cube4.rotation, 0.5, {z: -45* Math.PI/180});
tl.to(this.cube4.position, 0.5, {x: 50 }, 0.5);
I am very new to three.js so if any terminology is wrong, please warn me
Add the ("red") cube to a THREE.Group, in that way that the rotation axis (the edge) is in the origin of the group. This means the cube has to be shifted by the half side length.
If you rotate the group object, then the cube (which is inside the group) will rotate around the edge and not around its center.
e.g.
var bbox = new THREE.Box3().setFromObject(cube);
cube.position.set(bbox.min.x, bbox.max.y, 0);
var pivot = new THREE.Group();
pivot.add(cube);
scene.add(pivot);
See also the answer to How to center a group of objects?, which uses this solution to rotate a group of objects.
(function onLoad() {
var camera, scene, renderer, orbitControls, pivot;
var rot = 0.02;
init();
animate();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(4, 1, 2);
//camera.lookAt( -1, 0, 0 );
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
orbitControls = new THREE.OrbitControls(camera, container);
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,-1.5);
scene.add( directionalLight );
addGridHelper();
createModel();
}
function createModel() {
var material = new THREE.MeshPhongMaterial({color:'#80f080'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var cube1 = new THREE.Mesh(geometry, material);
cube1.position.set(0,-0.5,-0.5);
var cube2 = new THREE.Mesh(geometry, material);
cube2.position.set(0,0.5,-0.5);
var cube3 = new THREE.Mesh(geometry, material);
cube3.position.set(0,-0.5,0.5);
var material2 = new THREE.MeshPhongMaterial({color:'#f08080'});
var cube4 = new THREE.Mesh(geometry, material2);
var bbox = new THREE.Box3().setFromObject(cube4);
cube4.position.set(bbox.min.x, bbox.max.y, 0);
pivot = new THREE.Group();
pivot.add(cube4);
pivot.position.set(-bbox.min.x, 0.5-bbox.max.y, 0.5);
scene.add(cube1);
scene.add(cube2);
scene.add(cube3);
scene.add(pivot);
}
function addGridHelper() {
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
pivot.rotation.z += rot;
if (pivot.rotation.z > 0.0 || pivot.rotation.z < -Math.PI/2) rot *= -1;
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<!--script src="https://threejs.org/build/three.js"></!--script-->
<script src="https://rawcdn.githack.com/mrdoob/three.js/r124/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r124/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>
<div id="container"></div>
From the first image, it appears that the pivot of your red tile is at its center.
For the rotation you want, you would ideally change the pivot to the lower right of the cube. This is impossible without modifying the geometry of the cube.
BUT a simple trick is to create an empty node at that pivot point, parent your cube to that empty, and apply your rotation to the empty. (Don't forget to remove your translation, you don't need it anymore)
Here is some pseudo code, assuming your red box is centered at (0,0,0) and has a width and height of 100:
// create an empty node at desired rotation pivot
var empty = new Object3D or group
empty.position = (50, -50, 0)
// parent your cube to the empty
var cube = your box
empty.add(cube)
// you may need to change the local position of your cube to bring it back to its global position of (0,0,0)
cube.position = (-50, 50, 0)
rotate empty by 45°
I think you can get the bounds of the rotated object like this:
bounds = new THREE.Box3().setFromObject( theRedObject )
Then reposition the object.y based on its bounds.min.y
let scene, camera, controls, ambient, point, loader, renderer, container, stats;
const targetRotation = 0;
const targetRotationOnMouseDown = 0;
const mouseX = 0;
const mouseXOnMouseDown = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
init();
animate();
var box, b1, b2, b3;
function init() {
// Create a scene which will hold all our meshes to be rendered
scene = new THREE.Scene();
// Create and position a camera
camera = new THREE.PerspectiveCamera(
60, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
/*window.innerWidth / -8,
window.innerWidth / 8,
window.innerHeight / 8,
window.innerHeight / -8,
*/
0.1, // Near clipping pane
1000 // Far clipping pane
);
scene.add(camera)
// Reposition the camera
camera.position.set(0, 5, 10);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add orbit control
controls = new THREE.OrbitControls(camera);
controls.target.set(0, -0.5, 0);
controls.update();
// Add an ambient lights
ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambient);
// Add a point light that will cast shadows
point = new THREE.PointLight(0xffffff, 1);
point.position.set(25, 50, 25);
point.castShadow = true;
point.shadow.mapSize.width = 1024;
point.shadow.mapSize.height = 1024;
scene.add(point);
group = new THREE.Group();
group.position.y = 0;
scene.add(group);
rotationAnchor = new THREE.Object3D()
group.add(rotationAnchor);
box = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({
color: 'grey'
}))
b1 = box.clone();
b2 = box.clone();
b3 = box.clone();
b3.material = b3.material.clone()
b3.material.color.set('red')
group.add(box);
group.add(b1);
b1.position.y += 1
group.add(b2);
b2.position.z += 1
rotationAnchor.add(b3);
rotationAnchor.position.set(0.5, 0.5, 1.5)
b3.position.set(-.5, -.5, -.5)
// Create a renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
// Set size
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set color
renderer.setClearColor(0xf8a5c2);
renderer.gammaOutput = true;
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
container = document.createElement("div");
document.body.appendChild(container);
document.body.appendChild(renderer.domElement);
// Add resize listener
window.addEventListener("resize", onWindowResize, false);
// Enable FPS stats
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI({
height: 5 * 32 - 1
});
let params = {
'test': 4,
'bevelThickness': 1,
'bevelSize': 1.5,
'bevelSegments': 3
}
gui.add(params, 'test', 0, 10).onChange(val => {
test = val
})
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
rotationAnchor.rotation.z = (Math.cos(performance.now() * 0.001) * Math.PI * 0.25) + (Math.PI * 1.25)
requestAnimationFrame(animate);
// Re-render scene
renderer.render(scene, camera);
// Update stats
stats.update();
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>

Three.js: Raycast Has an Empty Array of Intersects

I am using this example for my WebGL panorama cube: https://threejs.org/examples/?q=pano#webgl_panorama_equirectangular
I want to know what cube user clicks on and I discovered I can use Raycaster for this. According to docs I added the following function:
function onMouseDown( event ) {
event.preventDefault();
var mouseVector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
1 );
//projector.unprojectVector( mouseVector, camera );
mouseVector.unproject( camera );
var raycaster = new THREE.Raycaster( camera.position, mouseVector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = raycaster.intersectObjects( scene.children );
console.log(intersects);
if (intersects.length>0){
console.log("Intersected object:", intersects.length);
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
// ...
But intersects is always empty. My scene is defined as
scene = new THREE.Scene();
and has skyBox added:
var skyBox = new THREE.Mesh( new THREE.CubeGeometry( 1, 1, 1 ), materials );
skyBox.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, - 1 ) );
scene.add( skyBox );
I've seen similar posts related to this issue but could not figure out how to apply to this example. Any directions are appreciated.
Try adding this to your material definition:
var materials = new THREE.SomeMaterial({
/* other settings */,
side: THREE.DoubleSide
});
Raycaster won't intersect back-faces unless the side property is set to THREE.BackSide or THREE.DoubleSide. Even though your scaling technically inverts the face direction, the vertex order stays the same, which is what's important to Raycaster.
Some further explanation
The snippet below is showing how a ray projected from a camera at the center of a skybox inverted by a -Z scale might look.
The box itself looks weird because it has been -Z scaled, and the normals no longer match the material. But that's here nor there.
The green arrow represents the original ray. The red arrow represents what will happen to that ray inside the Mesh.raycast function, which will apply the inverse of the object's world matrix to the ray, but not to the object's geometry. This is a whole different problem.
The point I'm making is that within Mesh.raycast, it does not affect the vertex/index order, so when it checks the triangles of the mesh, they are still in their original order. For a standard BoxGeometry/BoxBufferGeometry, this means the faces all face outward from the geometric origin.
This means the rays (regardless of how the transformation matrix affects them) are still trying to intersect the back-face of those triangles, which will not work unless the material is set to THREE.DoubleSide. (It can also be set to THREE.BackSide, but the -Z scale will ruin that.)
Clicking either of the raycast buttons will produce 0 intersects if the -Z scaled box is not set to THREE.DoubleSide (default). Click the "Set THREE.DoubleSide" button and try it again--it will now intersect.
var renderer, scene, camera, controls, stats;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000,
ray1, ray2, mesh;
function populateScene(){
var cubeGeo = new THREE.BoxBufferGeometry(10, 10, 10),
cubeMat = new THREE.MeshPhongMaterial({ color: "red", transparent: true, opacity: 0.5 });
mesh = new THREE.Mesh(cubeGeo, cubeMat);
mesh.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, -1 ) );
mesh.updateMatrixWorld(true);
scene.add(mesh);
var dir = new THREE.Vector3(0.5, 0.5, 1);
dir.normalize();
ray1 = new THREE.Ray(new THREE.Vector3(), dir);
var arrow1 = new THREE.ArrowHelper(ray1.direction, ray1.origin, 20, 0x00ff00);
scene.add(arrow1);
var inverseMatrix = new THREE.Matrix4();
inverseMatrix.getInverse(mesh.matrixWorld);
ray2 = ray1.clone();
ray2.applyMatrix4(inverseMatrix);
var arrow2 = new THREE.ArrowHelper(ray2.direction, ray2.origin, 20, 0xff0000);
scene.add(arrow2);
}
function init() {
document.body.style.backgroundColor = "slateGray";
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
populateScene();
animate();
var rayCaster = new THREE.Raycaster();
document.getElementById("greenCast").addEventListener("click", function(){
rayCaster.ray.copy(ray1);
alert(rayCaster.intersectObject(mesh).length + " intersections!");
});
document.getElementById("redCast").addEventListener("click", function(){
rayCaster.ray.copy(ray2);
alert(rayCaster.intersectObject(mesh).length + " intersections!");
});
document.getElementById("setSide").addEventListener("click", function(){
mesh.material.side = THREE.DoubleSide;
mesh.material.needsUpdate = true;
});
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function threeReady() {
init();
}
(function () {
function addScript(url, callback) {
callback = callback || function () { };
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function () {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function () {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function () {
threeReady();
})
})
})
})();
body{
text-align: center;
}
<input id="greenCast" type="button" value="Cast Green">
<input id="redCast" type="button" value="Cast Red">
<input id="setSide" type="button" value="Set THREE.DoubleSide">
You might actually want to use an easier process to determine your ray from the camera:
THREE.Raycaster.prototype.setFromCamera( Vector2, Camera );
Simply define your mouse coordinates as you do in a Vector2, then pass the elements to the Raycaster and let it do its thing. It hides the complexity of intersecting the frustrum with the ray from the camera, and should solve your problem.
(Also, the raycaster does indeed only intersect faces that face the ray directly, but since your SkyBox has been inverted its geometries faces are pointing to the inside of the box, so they should intersect if the camera is inside the box. Another possibility is that your box is further away than the raycasters default far value.)
function onMouseDown( event ) {
event.preventDefault();
var mouseVector = new THREE.Vector2(
event.clientX / window.innerWidth * 2 - 1,
-event.clientY / window.innerHeight * 2 + 1
);
var raycaster = new THREE.Raycaster;
raycaster.setFromCamera( mouseVector, camera );
var intersects = raycaster.intersectObjects( scene.children );
console.log(intersects);
if( intersects.length > 0 ){
console.log( "Intersected object:", intersects[ 0 ] );
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
}

Three JS Level Horizon Camera

I've dug around everywhere looking for a solution to this. It seems that on OrbitControls and TrackballControlls the camera wont stay horizontal! As you move around with TrackballControlls the scene starts to roll. OrbitControlls dragging from left to right only rolls the scene. I'd like to be able to use the TrackballControls but keep the camera level with the horizon when moving around the center of the scene. Is this possible?
My code:
// SETUP GLOBAL VARIABLES
var camera, controls, scene, renderer;
// PLANET PHYSICAL LOCATIONS
var sun, mercPL, venPL, earthPL, marsPL, jupPL, satPL, urPL, nepPL;
// TIME, AND SCALARS
var now, scalar, planetScalar;
init();
animate();
function init() {
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.z = 200;
controls = new THREE.OrbitControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.8;
controls.enableZoom = true;
// ADD THE SUN PHYSICAL LOCATION
var geometry = new THREE.SphereGeometry(5, 30, 30, 0, Math.PI * 2, 0, Math.PI * 2);
var material = new THREE.MeshBasicMaterial({color: "Yellow"});
sun = new THREE.Mesh(geometry, material);
scene.add(sun);
var segmentCount = 32,
radius = 80,
geometry = new THREE.Geometry(),
material = new THREE.LineBasicMaterial({ color: 0xFFFFFF });
for (var i = 0; i <= segmentCount; i++) {
var theta = (i / segmentCount) * Math.PI * 2;
geometry.vertices.push(
new THREE.Vector3(
Math.cos(theta) * radius,
Math.sin(theta) * radius,
0));
}
scene.add(new THREE.Line(geometry, material));
var segmentCount2 = 32,
radius2 = 120,
geometry2 = new THREE.Geometry(),
material2 = new THREE.LineBasicMaterial({ color: 0xFFFFFF });
for (var i = 0; i <= segmentCount2; i++) {
var theta = (i / segmentCount2) * Math.PI * 2;
geometry2.vertices.push(
new THREE.Vector3(
Math.cos(theta) * radius2,
Math.sin(theta) * radius2,
0));
}
scene.add(new THREE.Line(geometry2, material2));
//
window.addEventListener( 'resize', onWindowResize, false );
//
render();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render(); // MUST BE HERE FOR ANIMATION
}
function render() {
renderer.render( scene, camera );
}
Thanks!
Perhaps this can help you ( all the options are commented in the orbit library)
Level Horizon:
controls.minPolarAngle = Math.PI / 2;
controls.maxPolarAngle = Math.PI / 2;
Focus of Orbit:
controls.target = (cube.position);
Result: (Note: My mouse controls are inverted (Orbit Right / Pan Left) )
Three.js Lock Orbit Controls
Edit: After reviewing your comments code, I think this is what you want:
Three.js Orbit Controls pt 2.
The gist is that :
a) you need to provide the camera with an up vector:
camera.up.set( 0, 0, 1 );
And
b) Target the sun with the camera:
camera.lookAt(sun.position);
You can still play with the damping, and lock the angles ( there are also vertical constraints if you need them) and speed up down the yaw, but I hope this gets you closer.

Categories