Mathematically I computed the orthogonal matrix for the rotation that I want to apply to the camera. Before that I successfully applied a rotation on a axis. Perhaps the solution is to transform Matrix3 to Matrix4 and then apply it to the camera somehow.
camera = new THREE.PerspectiveCamera(150, window.innerWidth / window.innerHeight, 0.1, 5000);
camera.position.x = myParams.eye_x;
camera.position.y = myParams.eye_y;
camera.position.z = myParams.eye_z;
var m = new Matrix3();
m.set(
-cos(myParams.eye_deg2)*cos(myParams.eye_deg1),
sin(myParams.eye_deg2)*(Math.pow(cos(myParams.eye_deg1),2)-Math.pow(sin(myParams.eye_deg1),2)) ,
cos(myParams.eye_deg2)*sin(myParams.eye_deg1),
-sin(myParams.eye_deg2)*cos(myParams.eye_deg1),
cos(myParams.eye_deg2)*(Math.pow(sin(myParams.eye_deg1),2)-Math.pow(cos(myParams.eye_deg1),2)) ,
sin(myParams.eye_deg2)*sin(myParams.eye_deg1),
-sin(myParams.eye_deg1),
0,
cos(myParams.eye_deg1));
// camera.rotateOnAxis( pos_center.add(pos_camera.negate()).normalize(), -Math.PI / 2);
// >>>> to do: apply rotation matrix m to camera <<<<<
camera.updateProjectionMatrix();
Related
I'm creating a game level page using three js. Here I used mapcontrols for user control. In this when I click and drag any part of the screen, the object gets translated (as per my wish). But when I move along the Z axis, the objects move along z-axis which I need to block.
I just want to make the scene like a horizontal carousel in normal html (literally)
I tried some properties of OrbitControls which is given in threejs docs.
https://threejs.org/docs/index.html#examples/en/controls/OrbitControls
Here is the code I tried
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
var mapControls = new THREE.MapControls( camera, renderer.domElement );
mapControls.enableDamping = true;
mapControls.enableRotate = false;
mapControls.enableZoom = false;
To create a carousel-like experience, you don't need orbit controls, you only need to move the camera while looking at your object is advancing through the carousel, like the typical platform games.
I have created this fiddle with an example with an sphere moving along the x axis and the camera following it.
and the relevant code is basically on the render method:
function render() {
requestAnimationFrame(render);
mesh.position.x -= 0.1;
camera.lookAt(mesh.position);
camera.position.x -= 0.1;
renderer.render(scene, camera);
}
If you want to still playing with OrbitControls and fix the axes, you need to play with minPolarAngle and maxPolarAngle, that will block vertical axis if you set the same value for both.
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 2;
but that gives no perspective at all, so I would use:
controls.maxPolarAngle = Math.PI / 2.2;
controls.minPolarAngle = Math.PI / 2.2;
Then you have to play with the horizontal perspective, for that you need to set minAzimuthAngle and maxAzimuthAngle between -2 PI and +2 PI...:
controls.minAzimuthAngle = -Math.PI * 1.1;
controls.maxAzimuthAngle = Math.PI * 1.1;
This will slightly turn your camera angle:
Then, using only OrbitControls you will need to move the rest of the objects in the scene, so instead of moving the sphere, you will need to move conceptually the "floor".
If this solution solves your question, please mark the answer as answer accepted, in that way it will also help other users to know it was the right solution.
I have some code that converts a perspective camera to an orthographic camera. The problem is that when I make the conversion, the model becomes very tiny and hard to see.
I have calculated the zoom factor for the orthographic camera, based on the distance and the FOV. Are there any other properties that I need to set on the orthographic camera (e.g. clipping plane, etc..)?
I believe the position remains the same. I'm not sure what else I need to calculate.
fieldOfView = viewInfo.fov;
var getCameraPosition = function() {
return viewer._viewport._implementation.getCamera()._nativeCamera.position;
};
// Calculate the delta position between the camera and the object
var getPositionDelta = function(position1, position2) {
return {
x: position1.x - position2.x,
y: position1.y - position2.y,
z: position1.z - position2.z
}
};
var getDistance = function(positionDelta, cameraDirection) {
return dot(positionDelta, cameraDirection);
};
distance = getDistance(positionDelta, cameraDirection),
var depth = distance;
var viewportWidth = view.getDomRef().getBoundingClientRect().width;
var viewportHeight = view.getDomRef().getBoundingClientRect().height;
var aspect = viewportWidth / viewportHeight;
var height_ortho = depth * 2 * Math.atan( fieldOfView * (Math.PI/180) / 2 )
var width_ortho = height_ortho * aspect;
var near = viewInfo.near, far = viewInfo.far;
var newCamera = new THREE.OrthographicCamera(
width_ortho / -2, width_ortho / 2,
height_ortho / 2, height_ortho / -2,
near, far );
newCamera.position.copy( viewInfo.position );
var sCamera = new vk.threejs.OrthographicCamera(); //framework creatio of threejs cam
sCamera.setZoomFactor(orthoZoomFactor);
sCamera.setCameraRef(newCamera);
view.getViewport().setCamera(sCamera);
I also tried setting the same camera properties (e.g. clipping planes etc) of the perspective for the orthographic and I still had the same problem.
I guess I am missing some property or calculation required to put the object in the same position as when it was in perspective camera view.
Let's assume you have a perspective view with a given vertical field of view angle fov_y (in degrees) and you know the size of the viewport width and height. Furthermore, you have the near and far plane. These are the values which you use to setup the THREE.PerspectiveCamera:
perspCamera = new THREE.PerspectiveCamera( fov_y, width / height, near, far );
Also, you know the position of the object and the position of the camera. An object doesn't have only a single position, but you have to choose a representative position for its depth.
First you have to calculate the depth of the object.
var v3_object = .... // THREE.Vector3 : positon of the object
var v3_camera = perspCamera.position;
var line_of_sight = new THREE.Vector3();
perspCamera.getWorldDirection( line_of_sight );
var v3_distance = v3_object.clone().sub( v3_camera );
depth = v3_distance.dot( line_of_sight );
Then you have to calculate the "size" of the rectangle which is projected to the viewport at the depth:
aspect = width / height;
height_ortho = depth * 2 * Math.atan( fov_y*(Math.PI/180) / 2 )
width_ortho = height_ortho * aspect;
With these values the THREE.OrthographicCamera can be setup like this:
var orthoCamera = new THREE.OrthographicCamera(
width_ortho / -2, width_ortho / 2,
height_ortho / 2, height_ortho / -2,
near, far );
orthoCamera.position.copy( perspCamera.position );
The positon and direction of the perspective camera can be committed to the orthographic camera like this:
orthoCamera.position.copy( perspCamera.position );
orthoCamera.quaternion.copy( perspCamera.quaternion );
See also stackoverflow question Three.js - Find the current LookAt of a camera?
Following some previous post on stackoverflow I am trying to add labels in my canvas.
I made a second scene and second camera to overlap my labels on first scene.
this.sceneOrtho = new THREE.Scene();//for labels
this.scene = new THREE.Scene();// for Geometry
//camera for geometry
var SCREEN_WIDTH = window.innerWidth-5, SCREEN_HEIGHT = window.innerHeight-5;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20;
this.camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
var r = 4, phi = Math.PI/4, theta = Math.PI/4;
this.camera.position.set(r*Math.cos(phi)*Math.sin(theta),r*Math.sin(phi), r*Math.cos(phi)*Math.cos(theta));
this.camera.lookAt(new THREE.Vector3(0, 0, 0));
// camera for labels
this.cameraOrtho = new THREE.OrthographicCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
this.cameraOrtho.position.z = 10;
I also added THREE.Sprite object to the scene sceneOrtho.add(spritey);
and rendered this.model.clearScene(this.scene);
this.model.populateScene(this.scene,this.sceneOrtho);//<--------
this.renderer.clear();
this.renderer.render(this.scene, this.camera);
this.renderer.clearDepth();
this.renderer.render( this.sceneOrtho, this.cameraOrtho );
but I can see only the geometries and not my labels.
Here there is a live example click on button test to see it.
I guess scene is rendering right, but your orthographic camera is looking in bad direction. I don't see setting lookAt for your ortho camera.
And yes as #westlangley write, this is not useful for others.
I just try to use the THREE.OrbitControls to perform zooming in orthographic projection, but i dont get the behave that i want.
I think that is possible change the viewSize that multiply to left, right, top and bottom to create a something near of a zoom
Anyone hava a better idea?
Yes, you can implement a zooming effect with an OrthographicCamera by using the following pattern:
camera.zoom = 1.5;
camera.updateProjectionMatrix();
This works for PerspectiveCamera, too.
three.js r.70
I have a function to zoom the scene. Please try it.
function zoom_all(center,size) {
// get the current lookAt vector of OrthographicCamera camera
var vectorLookAt = new THREE.Vector3(0, 0, -1);
vectorLookAt.applyQuaternion(camera.quaternion);
vectorLookAt.normalize();
// move back along lookat vector to set new position of camera
vectorLookAt.multiplyScalar(-size);
camera.position = new THREE.Vector3().addVectors(center, vectorLookAt);
// get current size of camera
var viewSize = 2 * camera.top;
var aspectRatio = 2 * camera.right / viewSize; // get aspectRatio of camera
// camera = new THREE.OrthographicCamera(
// -aspectRatio * viewSize / 2, aspectRatio * viewSize / 2,
// viewSize / 2, -viewSize / 2,
// 0.1, 1000);
// update new size for camera
viewSize = size;
// now update camera size
camera.left = -aspectRatio * viewSize / 2;
camera.right = aspectRatio * viewSize / 2;
camera.top = viewSize / 2;
camera.bottom = -viewSize / 2;
camera.near = 0.1;
camera.far = 2 * size;
camera.updateProjectionMatrix();
// you can set light to camera position
spotLight.position.set(camera.position.x, camera.position.y, camera.position.z);
// set center point for orbit control
orbitControls.center.set(center.x, center.y, center.z);
orbitControls.target.set(center.x, center.y, center.z);
}
If anyone is still interested, I edited OrbitControls to work with orthographic camera based on WestLangley's answer:
https://github.com/traversc/OrbitControls-orthographic_camera_fix/blob/master/OrbitControls.js
I'm trying to place a cube relative to the camera, rather than relative to the scene. The thing is, to place it in the scene (which I have to do make it show), I have to know the scene coordinates that correspond to the cubes camera space coordinates. I found this function "projectionMatrixInverse" in THREE.Camera. It has a nice function called "multiplyVector3" which I hoped would enable me to transform a vector (1,1,1) back to scene space like this:
var camera, myvec, multvec; // (and others)
camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 2000, 1000 );
camera.position.x = 200;
camera.position.y = 100;
camera.position.z = 200;
myvec = new THREE.Vector3(1,1,1);
console.log("myvec: ", myvec);
multvec = camera.projectionMatrixInverse.multiplyVector3(THREE.Vector3(1,1,1));
console.log("multvec: ", multvec);
the thing is, on the console i get:
myvec: Object { x=1, y=1, z=1}
TypeError: v is undefined
var vx = v.x, vy = v.y, vz = v.z;
multiplyVector3 simply doesn't accept my myvec, or says it's undefined, even though the console says it's an object. I don't get it.
The camera is located at the origin of it's coordinate system, and looks down it's negative-Z axis. A point directly in front of the camera has camera coordinates of the form ( 0, 0, z ), where z is a negative number.
You convert a point p
p = new THREE.Vector3(); // create once and reuse if you can
p.set( x, y, z );
from camera coordinates to world coordinates like so:
p.applyMatrix4( camera.matrixWorld );
camera.matrixWorld is by default updated every frame, but if need be, you can update it yourself by calling camera.updateMatrixWorld();
three.js r.95
This may also be what you're after:
scene.add( camera );
brick.position.set( 0, 0, -1 );
camera.add( brick );