How to move an object in particular direction with specific distance in three.js - three.js

I need to move an object along directional vector through some distance. I fount translateOnAxis(vector, distance) of Object3D class. But I'm not able to understand how it works.
I've an object- sphere. I'm scaling it to look like ellipse. And setting position and direction. Now I need this object to move in the same direction which I'm setting it to, through some distance. When I apply it, I can't see the object. Can anybody suggest how it can be achieved?
var geometry = new THREE.SphereGeometry( radius, 64, 64, 0, -Math.PI );
geometry.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, zScale ); //scaling it to look like ellipse
var direction = new THREE.Vector3( xDir, yDir, zDir);
var ellipse = new THREE.Mesh( geometry, material );
ellipse.lookAt(direction);
ellipse.position.set( xPos, yPos, zPos);
ellipse.translateOnAxis(direction, distance);

Your pasted code is buggy.
You're missing a ) on your applyMatrix line.
Are you using a debugger and observing console errors/warnings?

Related

three.js make a cutting plane visible

In this demo:
https://threejs.org/examples/?q=clipping#webgl_clipping_advanced
if you enable the "visualize" option, you can see the 3d pyramid "cutting" the inside object.
Here:
https://threejs.org/examples/?q=clipping#webgl_clipping
there is a simple 2d plane cutting the object, but there is no such option to "see" the plane. I just started learning threejs and I am not too familiar with any 3d engine (other than fully understanding the math behind it), so I tried some basic stuff, e.g.:
localPlane.visible = true
But of course it didn't work. Any 'simple' way to make the second demo display the cutting plane?
Thank you
Here's some code to add the plane in the position you want:
const planeGeometry = new THREE.PlaneGeometry( 1.5, 1.5 );
const planeMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
const plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.position.copy(localPlane.normal);
plane.position.multiplyScalar(-localPlane.constant);
plane.quaternion.setFromUnitVectors(new THREE.Vector3(0, 0, 1), localPlane.normal);
plane.material.opacity = 0.5;
plane.material.transparent = true;
scene.add( plane );
And here's what that looks like...
However, depending on what you are implementing, you may find it easier to create a Plane Mesh in the position you want, and then derive the clipping plane THREE.Plane from that.
If you want to be able to move the clipping plane around, the reasoning involved in moving a Plane Mesh Object3D is probably more straightforward than reasoning about moving a THREE.Plane.
(update)
Another alternative approach I've come across: you could simply use the built in THREE.PlaneHelper, which can be used to visualize any THREE.Plane.
https://threejs.org/docs/#api/en/helpers/PlaneHelper
The sample code offered on that page is this:
const plane = new THREE.Plane( new THREE.Vector3( 1, 1, 0.2 ), 3 );
const helper = new THREE.PlaneHelper( plane, 1, 0xffff00 );
scene.add( helper );

Three.js: Draw a vector on plane

I'm a newbie in three.js (and in stackoverflow).
I try to find answer but I'm not able to do this simple things.
I'm playing with Helpers and Plane.
I want to create a Plane (and it's PlaneHelper), and draw an arbitrary vector on this Plane.
All is right if the plane's distance from origin is set to 0.
If I give a distance to the plane, the vector is not on the plane.
Here is the commented code I use for this little experiment.
Projecting both the origin and the vector on the plane I was convinced that arrowHelper_Point remained on the plane, but it's not.
Where is my mistake? I can not understand it.
// Define ARROW_LENGTH to display ArrowHelper
const ARROW_LENGTH = 5;
// Point (0,0,0)
var origin = new THREE.Vector3(0, 0, 0);
// Axes helper in (0,0,0)
var axesHelperOrigin = new THREE.AxesHelper(100);
scene.add(axesHelperOrigin);
// Define a plane by the normal, color and distance from (0,0,0)
var vectorNormal = {
normal: new THREE.Vector3(1, 1, 0).normalize(),
color: "rgb(255, 255, 0)",
colorNormal: "rgb(255,100,0)",
colorVector: "rgb(194, 27, 255)",
distance: -3,
};
// Create Plane from the normal and distance
var plane = new THREE.Plane(vectorNormal.normal, vectorNormal.distance);
// Add PlaneHelper to scene
var planeHelper = new THREE.PlaneHelper(plane, 100, vectorNormal.color);
scene.add(planeHelper);
// Add ArrowHelper to display normal
// Find the projection of origin on plane
var originOnPlane = plane.projectPoint(origin);
var arrowHelper_Normal = new THREE.ArrowHelper(vectorNormal.normal, originOnPlane, ARROW_LENGTH, vectorNormal.colorNormal);
scene.add(arrowHelper_Normal);
// Define a point "random"
var point = new THREE.Vector3(5, -2, 6);
// Project the point on plane
var pointOnPlane = plane.projectPoint(point);
// Draw ArrowHelper to display the pointOnPlane, from originOnPlane
var arrowHelper_Point = new THREE.ArrowHelper(pointOnPlane.normalize(), originOnPlane, ARROW_LENGTH, vectorNormal.colorVector);
scene.add(arrowHelper_Point);
EDIT: OK, I think I find the error.
Looking at this Get direction between two 3d vectors using Three.js?
I need the vector between the two points:
var dir=new THREE.Vector3();
dir.subVectors(pointOnPlane,originOnPlane).normalize();
And use dir as the arrow direction.
Sorry for asking an obviously thing.
Looking at this Get direction between two 3d vectors using Three.js?
I need the vector between the two points:
var dir=new THREE.Vector3();
dir.subVectors(pointOnPlane,originOnPlane).normalize();
And use dir as the arrow direction.

Inconsistent surface behaviour in Three.js

when I set a point light at a THREE.BoxGeometry object it looks like this:
THREE.BoxGeometry with point light
var light = new THREE.PointLight (0xffffff, 1, 100);
light.position.set (10, 10, 10);
scene.add (light);
var geometry = new THREE.BoxGeometry (1, 1, 1);
var material = new THREE.MeshPhongMaterial ();
var cube = new THREE.Mesh (geometry, material);
scene.add (cube);
When I now set a point light at a THREE.PolyhedronGeometry object it looks like this:
THREE.PolyhedronGeometry with point light
var light = new THREE.PointLight (0xffffff, 1, 100);
light.position.set (10, 10, 10);
scene.add (light);
var geometry = new THREE.PolyhedronGeometry (vertices, faces, 1, 0);
var vertices = [-1,-1,-1,1,-1,-1,1,1,-1,-1,1,-1,-1,-1,1,1,-1,1,1,1,1,-1,1,1];
var faces = [2,1,0,0,3,2,0,4,7,7,3,0,0,1,5,5,4,0,1,2,6,6,5,1,2,3,7,7,6,2,4,5,6,6,7,4];
var material = new THREE.MeshPhongMaterial ();
var cube = new THREE.Mesh (geometry, material);
scene.add (cube);
I want to know, where this behaviour comes from and how I can manage to make polyhedrons' faces behave as nice as boxs?
I read that it might be related to geometry.computeFaceNormals().
So I tried it out, but it doesn't make any difference.
when something is different with how light behaves on a surface, first candidates to look at are normals
this is true for the box face
boxGeometry.faces[i].normal.equals(boxGeometry.faces[i].vertexNormals[j]);//true
so box has only simple normal for each face
the polyhedron has different face normal from the vertex normals
polyhedronGeo.faces[i].normal.equals(polyhedronGeo.faces[i].vertexNormals[j]);//not true
and some of the vertex normals are not equal among each other
polyhedronGeo.faces[i].vertexNormals[j].equals(polyhedronGeo.faces[i].vertexNormals[k]);
//not true for some j,k
that is why the light looks ~shadowy - normal is interpolated for the shader from vertexNormals
to modify the polyhedron to look like box just change the vertex notmals to match the face normal
as for
geometry.computeFaceNormals();
it will only compute the face normals, not the vertexNormals
there is another function
geometry.computeVertexNormals();
but that would create vertex normals as are in polyhedron
Thanks Derte. Your reflection got me closer to the point. So with advanced keywords I found this: https://github.com/mrdoob/three.js/issues/1982
The answer to my question is this line, flattening shading for "free forms":
material.shading = THREE.FlatShading;

Is there ANY way to have the three.js camera lookat being rendered off-center?

Is there a way to setup the Three.js renderer in such a way that the lookat point of the camera is not in the center of the rendered image?
To clarify: image a scene with just one 1x1x1m cube at ( 0, 0, 0 ). The camera is located at ( 0, 0, 10 ) and the lookat point is at the origin, coinciding with the center of the cube. If I render this scene as is, I might end up with something like this:
normal render
However I'd like to be able to render this scene in such a way that the lookat point is in the upper left corner, giving me something like this:
desired render
If the normal image is 800x600, then the result I envision would be as if I rendered a 1600x1200 image with the lookat in the center and then cropped that normal image so that only the lower right part remains.
Of course, I can change the lookat to make the cube go to the upper left corner, but then I view the cube under an angle, giving me an undesired result like this:
test.moobels.com/temp/cube_angle.jpg
I could also actually render the full 1600x1200 image and hide 3/4 of the image, but one would hope there is a more elegant solution. Does anybody know it?
If you want your perspective camera to have an off-center view, the pattern you need to use is:
camera = new THREE.PerspectiveCamera( for, aspect, near, far );
camera.setViewOffset( fullWidth, fullHeight, viewX, viewY, viewWidth, viewHeight );
See the docs: https://threejs.org/docs/#api/cameras/PerspectiveCamera
You can find examples of this usage in this example and this example.
three.js r.73
Here's a simple solution:
Assuming your cube is 4 x 4 x 4, at position 0, 0, 0:
var geometry = new THREE.BoxGeometry( 4, 4, 4 );
var material = new THREE.MeshBasicMaterial( { color: 0x777777 } );
var cube = new THREE.Mesh( geometry, material );
cube.position.set( 0, 0, 0 );
Get cube's position:
var Vx = cube.position.x,
Vy = cube.position.y,
Vz = cube.position.z;
Then deduct by 2 from x position, then add 2 to y and z position, and use the values to create a new Vector3:
var newVx = Vx - 2,
newVy = Vy + 2;
newVz = Vz + 2;
var xyz = new THREE.Vector3(newVx, newVy, newVz)
Then camera lookAt:
camera.lookAt(xyz);
Using console log, it would show that the camera is now looking at -2, 2, 2, which is the upper-left of your cube.
console.log(xyz);

Three.js How to create a simple 3d Point

I want to create some simple 3D points.
Is there any way to create this geometry without tricks?
- I don't need a pointcloud ( or do I need ? )
- I don't want a sprite ( I don't want to load any image).
Maybe I'm some clumsy but I don't see the way.
Any idea & advise ? Thanks.
You maybe want to use a simple sphere geometry with a small radius for your project.
var pointGeometry = new THREE.SphereGeometry( 2, 16, 16 ), // adjust the first value for the 'point' radius
pointMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00} ), // adjust the color of your 'point'
point3D = new THREE.Mesh( pointGeometry, pointMaterial );
scene.add( point3D );
Important side notice: the radius of the sphere and the size it takes on your screen depends on the distance from the camera and the camera.['far'] value, you set while initiating.

Resources