Three.js pixel perfect at z=0 plane - three.js

Is there any way to configure the camera in Three.js so that when a 2d object (line, plane, image) is rendered at z=0, it doesn't bleed (from perspective) into other pixels.
Ex:
var plane = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), material);
plane.position.x = 4;
plane.position.y = 3;
scene.add(plane);
...
// Get canvas pixel information
context.readPixels(....);
If you example the data from readPixels, I always find that the pixel is rendering into its surrounding pixels (ex: 3,3,0 may contain some color information), but would like it to be pixel perfect if the element that is draw is on the z=0 plane.

You probably want to use THREE.OrthographicCamera for the 2d stuff instead of THREE.PerspectiveCamera. That way they are not affected by perspective projection.

Which pixels get rendered depends on where your camera is. If your camera for example t z=1 then a lot of pixels will get rendered. If you move your camera to z=1000 then you see, due to perspective, maybe only 1 pixel will get rendered from your geometry.

Related

Rotate around World Axis

I tried to rotate an object arount the Worlds-Y-Axis, with
myObject.rotateOnWorldAxis(new THREE.Vector3(0,1,0),THREE.Math.degToRad(1));
but the result was, that the object is only rotated in object space.
To be sure that I used the correct method I looked into the documentation and found that there are three methods to rotate an object:
.RotateY(rad) // rotate in Local Space
.rotateOnAxis(axis,rad) // rotation in Object Space
.rotateOnWorldAxis(axis,rad) // rotation in World Space
It seems that I used the correct method.
Is this a bug or an understanding problem on my side?
Here is a JSFiddle which illustrates my problem (the blue cube should rotate around the world axis).
Here is a second Fiddle where thy cyan cube is a child of another object.
It looks to me like your real question isn't regarding world space or object space rotations, cause those are working as expected in your examples.
You probably meant, how to change the point of rotation of an object. If that is the case, you have two options, you can either translate all your geometry vertices in respect to a pivot point of rotation. That way, your pivot will be centered at (0,0,0) and your vertices will rotate in respect to that.
mesh.geometry.translate( x, y, z );
Or you can make your object a child of a different Object3D (pivot), position your original mesh similarly to what was described above and rotate your pivot mesh.
var cube = new THREE.Mesh( geometry, material );
var pivot = new THREE.Object3D();
cube.position.set( 0, 12, 30 ); // offset from center
pivot.add( cube );
scene.add( pivot );
//...
pivot.rotation.y += Math.PI/2;
JSFiddle

How can I rotate around the center of an object in three.js?

I am dynamically adding a number of different objects of various sizes into a scene (one per click) and scaling and positioning them. Now I want to be able to rotate the objects around the Y axis at their center. I have added a boundingBox and an axesHelper, but the latter is showing up in the bottom corner of the objects. Reading this answer, which is similar to mine, it seems like this might be because of an offset. I can find the center of the object fine with this:
var box3 = new THREE.Box3();
var boundingBox = new THREE.BoxHelper( mesh, 0xffff00 );
scene.add( boundingBox );
box3.setFromObject( boundingBox );
center = box3.getCenter( boundingBox.position );
console.log( "center: ", center );
But when I try to reset the center to this position, following this answer, my object shoots way off into space.
box3.center(mesh.position);
mesh.position.multiplyScalar( -1 );
And I’m not really clear (even after reading the documentation) what “multiplyScalar” does/means. By playing with that number, I can get the object closer to the desired position, but the object still doesn't rotate around its center, and the AxesHelper is still at the original location.
Your object is not rotating around its center. Likely, your object's geometry is offset from the origin.
If you are dealing with a single Mesh or Line, you can center the object's geometry by calling
geometry.center();
This method will translate the vertices of the geometry so the geometry's bounding box is centered at the origin.
three.js r.97

Make text always appear orthogonal to the plane when rotating a cube

I'm creating text labels that appear on a 3D cube using the following pattern:
canvas = createTextCanvas(text, color, font, size);
texture = new THREE.Texture(canvas);
geom = new THREE.PlaneBufferGeometry(canvas.width, canvas.height, segW, segH);
material = new THREE.MeshBasicMaterial({map: texture, transparent: true});
mesh = new THREE.Mesh(geom, material);
mesh.position.x = x;
mesh.position.y = y;
mesh.position.z = z;
texture.needsUpdate = true;
The labels and their positions get set within a for loop for each edge of the cube. This results in labels appearing similar to this:
But then when I rotate the cube (using OrbitControls), you'll see that the label no longer appears vertically like above:
So using the Cost label as an example, I would want the text to remain vertically oriented whenever the cube is rotated. Basically, I'm trying to mimic the behavior of axis labeling in VTK.
So I believe the solution here is to set the up vector of the label to a vector that's always orthogonal to the plane. But I'm not sure how to implement this. Any suggestions or examples would be greatly appreciated.
If it helps, I'm constructing the cube using a BoxGeometry and MeshNormalMaterial.
Do you mean the label keeps moving with the cube or not?
If not, there is a example: http://stemkoski.github.io/Three.js/Sprite-Text-Labels.html. The label keeps facing to you but may not vertical.
Else ,you may need a canvas texture,the label is a object just like the cube and you can set its position to keep it vertical.But it doesn't look good sometime.the example:http://stemkoski.github.io/Three.js/Texture-From-Canvas.html.
I think you just want the label always facing to you when you change your sight.

Bring point to nearest camera position by camera rotation

I have a scene in Three.js (r67) with a camera that is controlled by OrbitControls.
If I now select an arbitrary point (Vector3) in the scene, what would be the best way to bring this point (programmatically) to the nearest camera position just by rotating the camera?
Example Scenario
In the below picture the left side is the starting point. The camera rotates around the green sphere (like OrbitControls) where the center of the camera is the center of the sphere. I now like to automatically rotate the camera around the sphere (doing the minimum amount of moves) so that the red box is nearest to the camera (like on the right side).
Independntly to the method of selecting the point in the scene, there's several understanding to what you mean by "bringing camera just by rotating".
I suppose, You want to rotate the camera in the way, to make the selected point in the center of the screen.
This is simple:
camera.lookAt(your_point_in_scene);
You could do this more complicated. Firstly, find the current pointing vector. By default camera looks in direction Vector(0,0,1). When we rotate it in the same rotation as a camera, we will have camera direction:
var vec = new THREE.Vector3(0,0,1);
vec.applyQuaternion(camera.rotation._quaternion);
Now we must determine angle to rotate our camera, and axis, around which we would rotate.
Axis of rotation could be found as a cross product of camera direction and vector from camera to object. Angel could be extracted from dot product:
var object_dir = object_world_point.clone().sub(camera.position);
var axis = vec.clone().crossProduct(object_dir);
var angle = Math.acos( vec.clone().dot(object_dir) / vec.length() / object_dir.length());
Having angle and axis, we could rotate camera:
camera.rotateOnAxis(axis, angle);
Or, if you want to make it smooth:
// before animation started
var total_rotation = 0,
rotateon,
avel = 0.01; // 0.01 radian per second
if(total_rotation < angle){
rotateon = avel * time_delta;
camera.rotateOnAxis(axis, angle);
total_rotation += rotateon;
}
Well that's not hard Oo
You have a center/target point for the camera. You calculate the difference from the target position to the point position and normalize that vector to the length of the camera-centerpoint-distance (i.e. something like pointdistance.multiplyScalar(cameradistance.length() / pointdistance.length()) ).
And that's it. If I understood your question correctly. All you do is "extend" the point's positioni onto your "camera movement dome" and then you have the ideal new camera position. The camera's rotation is done automatic since you always target the center point.
Aaand if you want to smoothen the camera movement a bit you can just interpolate the angle (not the positions directly) with e.g. an exponential function, whatever you prefer.
Hi Dear please follow this
Independntly to the method of selecting the point in the scene, there's several understanding to what you mean by "bringing camera just by rotating".
I suppose, You want to rotate the camera in the way, to make the selected point in the center of the screen.
This is simple:
camera.lookAt(your_point_in_scene);
You could do this more complicated. Firstly, find the current pointing vector. By default camera looks in direction Vector(0,0,1). When we rotate it in the same rotation as a camera, we will have camera direction:
var vec = new THREE.Vector3(0,0,1);
vec.applyQuaternion(camera.rotation._quaternion);
Now we must determine angle to rotate our camera, and axis, around which we would rotate.
Axis of rotation could be found as a cross product of camera direction and vector from camera to object.
Angle could be extracted from dot product:
var object_dir = object_world_point.clone().sub(camera.position);
var axis = vec.clone().crossProduct(object_dir);
var angle = Math.acos( vec.clone().dot(object_dir) / vec.length() / object_dir.length());

Three.js plane facing away from camera aligned with viewport

I'm trying to have a plane face away from the camera with same orientation so it's aligned in the viewport.
I have a plane in front of the camera, perfectly aligned to the cameras viewport, and I want to flip it in front of the camera, along the objects Y axis, regardless of camera orientation.
The following will orient my plane to face at the camera and works for any orientation:
target.rotation.copy(camera.rotation);
The following will then flip the plane along the plane's Y axis:
target.rotation.y += Math.PI;
All good so far? Except when the camera rotation has a funky tilt to it, let's say it's looking up and to the left, tilted slightly to the right, the plane's flip is tilted, but not the same way as the camera, leaving me with a plane tilted either to the left or right...
I've tried several things such as:
target.rotation.z -= camera.rotation.z;
Nothing... Thanks for your help.
So the problem I was running into was when the camera was in negative z coordinates. This causes the flip on the Y axis to get messed up.
So basically you would do something like this:
var target = new THREE.Object3D();
//position
target.position.copy(s.camera.position);
target.position.add(THREE.Utils.cameraLookDir(s.camera).multiplyScalar(300));
//rotation
target.rotation.copy(s.camera.rotation);
target.rotation.y += PI;
target.rotation.z = -s.camera.rotation.z;
if (s.camera.position.z < 0) {
target.rotation.z = s.camera.rotation.z;
}
EDIT:
Add the following to appropriate spots in your program.
camera.rotation.eulerOrder = 'XZY';
target.rotation.eulerOrder = 'XZY';
Seems to solve previously encountered tilt issues! (see below)
RESOLVED:
Flipped planes tilted the wrong way in some instances, for example when in negative z coords and also the y rotation is not equal to 0, example: point in space hovering and looking at 0, 0, 0.
This is the solution I was looking for when I found this page (taken from this answer):
mesh.lookAt( camera.position );
The local z-axis of the mesh should then point toward the camera.

Resources