Rotate a plane on its edge in three.js - rotation

I wanted to rotate a plane, but I can't figure out how to set the rotation axis. I'd like to rotate a plane around its edge.
I've seen solutions suggesting matrix transformations but they lacked explanation so I couldn't apply them.

Ok I figured it out. What you have to do is create a parent 3D object and add the plane to it. Once, added, you have to translate it by 50% and start rotating the parent object.
var object = THREE.SceneUtils.createMultiMaterialObject( new THREE.PlaneGeometry( 200, 50, 4, 4 ), [material] );
var parent = new THREE.Object3D();
object.applyMatrix( new THREE.Matrix4().makeTranslation( 0, 25, 0 ) );
parent.add(object);
parent.rotation.x = 1;
scene.add(parent)

Related

how to draw polygon in three js using vertices?

I have vertices(x,y,z) of a polygon as input. How can I render a polygon having these vertices in three.js? THREE.Geometry() is removed from three js. how to draw plane polygon with bufferGeometry or any other method ? now when i draw polygon with vertices it drawing incomplete mesh (polygon). following code is used to draw polygon.
const verticesGeometry = new THREE.BufferGeometry().setFromPoints(measurement.coordinates.map((coord) => new THREE.Vector3(coord.x, coord.y, coord.elevation)))
const polygon = new THREE.Mesh(verticesGeometry , new THREE.MeshBasicMaterial({ color: measurement.color, side: THREE.DoubleSide}))
scene.add(polygon)
screenshots attached of issue, which is i am facing right now, (3 points polygon working perfectly, more than it, rendering incomplete.) thanks in advance.
i also tried THREE.ShapeGeometry() but polygon are rendering to the bottom because THREE.shape() is accepting only VECTOR2 points.i am passing vector3 but it neglecting 3rd (z) point.
let polyShape = new THREE.Shape(measurement.coordinates.map((coord) =>
new THREE.Vector3(coord.x, coord.y, coord.elevation)))
const geometry = new THREE.ShapeGeometry( polyShape )
let polygon = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: measurement.color, side: THREE.DoubleSide }))
see the below image for reference.
You're just giving your points to a Mesh. They are interpreted as triples, each of which represent a triangle. If you want to render a filled polygon, it must be triangulated.
Easier though, is probably to use ShapeGeometry, see the doc in the link. This should do exactly what you need, if you can take the time to learn its interface.
If you want to make the vertices follow the height of your terrain, you can then edit the height coordinates of all vertices in the shape geometry (see how to update a buffer geometry; notice that ShapeGeometry extends BufferGeometry) back with its original Z or whatever your up direction is. The mesh topology will follow because it's already triangulated, and since you don't seem to have massive height variation, it should work nicely.
If you want to triangulate yourself instead of using ShapeGeometry, Three.js also provides a helper for this here.
As per the #berthur answer I tried following code and it worked. Thanks to https://stackoverflow.com/users/10559142/berthur
let coordinates = [
{
x : 1,
y : 1,
elevation : 10
},
{
x : 2,
y : 1,
elevation : 10
},
{
x : 2,
y : 2,
elevation : 10
},
{
x : 1,
y : 2,
elevation : 10
}
]
let polyShape = new THREE.Shape(coordinates.map((coord) => new THREE.Vector2(coord.x, coord.y)))
const polyGeometry = new THREE.ShapeGeometry(polyShape);
polyGeometry.setAttribute("position", new THREE.Float32BufferAttribute(coordinates.map(coord => [coord.x, coord.y, coord.elevation]).flat(), 3))
let polygon = new THREE.Mesh(polyGeometry, new THREE.MeshBasicMaterial({ color: "ColorYouWant, side: THREE.DoubleSide}))
scene.add(polygon);

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

Generate shape in three.js from multiple elements

Is there a way in three.js to create a poly from multiple individual elements, rectangle for example.
I have attached an example.
I am using:
for(i = 0; i<5; i++){
var rand = Math.floor(Math.random() * 50)+1000;
var material = new THREE.MeshBasicMaterial({
color : "#ff"+i+ rand,
side : THREE.DoubleSide,
transparent : true,
opacity : 1
});
var mesh = new THREE.Mesh( geometry, material );
if(angle) mesh.rotation.y = angle;
mesh.position.set( loop+1, 4,4);
scene.add( mesh );
}
When I apply roatation mesh.rotation.y = angle; it doesn't come up with my below design, I rather get a cross + because the panel rotates on it's y from center, not from corner...
Thank you
The
There are 3 ways to achieve what you're trying to do. The problem you are facing stems from transform origin, as you noted, origin defaults to position [0,0,0]. So, your options are:
build a transform matrix using a different transform offset for rotation, this is probably an overkill for simple use-cases.
translate geometry to not be centered on [0,0,0], for example you can move the whole quad (your geometry) right so that the left edge of the quad aligns with [0,0,0], then, when you rotate, left edge will stay put.
embed Mesh inside a Group, rotate the Mesh and translate (position.set(....)) the Group.
no matter which route you take - you will still have to deal with the some trigonometry as you will need to compute the position for the next segment to align with the edge of the previous one.
One more way around that is to build the following type of structure
Group[
Mesh 1,
Mesh 2,
Mesh 3,
Group [
Mesh 4,
Mesh 5,
Mesh 6,
Group [
Mesh 7
]
]
]
Last group is unnecessary, it's there purely for consistency.
As far as the trigonometry that I mentioned - it's simple Sin and Cos stuff, so it should be quite simple. Here is some pseudo-code that you'll need:
prevPosition, prevAngle //position and angle of previous segment
// Compute next segment transform
nextPosition.x = Math.cos(prevAngle)*segmentSize + prevPosition.x;
nextPosition.z = Math.sin(prevAngle)*segmentSize + prevPosition.z;

How to create geometry for thick lines with three.js?

I need to create thick lines in 3d that receive shadows. The lines are on a flat plane as in y is the same for all points. The lines all face up. An example would be the yellow line on a road.
I think the best way would be to create the geometry and use MeshLambertMaterial so that it would receive shadows.
Can anyone point me in the right direction to create the geometry from points? I assume I need to create the vertices with BufferGeometry.
I'm not quite sure if you already have an array of points (coordinates) for each vertex of the lines and want to create the line from them, or if you just want to create lines of a width and length that you can specify as your question is quite unclear, so I'll provide an example for the latter (and more simple) option.
If you don't have any specified vertices, you can create an object that looks like a "line" using a PlaneGeometry and specifying it's width and height.
i.e.
var geomLine = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
var matLine = new THREE.MeshPhongMaterial({color: 0xFF0000});
var Line = new THREE.Mesh(geomLine, matLine);
Line.receiveShadow = true;
Line.castShadow = true;
scene.add(Line);
If you want the line to have some height and not be a flat plane, you could use a BoxGeometry instead of a LineGeometry. The code above would almost be the same, the only difference being you would also need to specify a depth for the box geometry, for example:
geomLine = new THREE.BoxGeometry(width, height, depth);
Bare in mind that the height for the BoxGeometry is how tall it is (on the y axis, the depth value is how "long" it is on the z axis)
EDIT: Here's how to create a polygon with pre-defined vertices
You can create a polygon from vertices with the following code:
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(0,500,0);
var v3 = new THREE.Vector3(0,500,500);
geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);
geom.faces.push( new THREE.Face3( 0, 1, 2 ) );
geom.computeFaceNormals();
var object = new THREE.Mesh( geom, new THREE.MeshNormalMaterial() );
scene.add(object);
Copy and paste this code in and then change x, y, and z coordinates of v1, v2, and v3 (or however many vertices you need) to the coordinates of your vertices.
Essentially you are creating vertices using THREE.Vector3 to supply the coordinates and then pushing them to the vertices property of an empty THREE.Geometry();
Code is from this answer
Hope this is what you were looking for!

Find relative position of axes of cube after rotation

I am rotating a cube through a series of 90 degree rotations using quaternions and I want to be able to get relative positions of the quaternions after a rotation compared with its original position that I have stored.
IE I'd like to know which axis is now equivalent to the original x axis (and if it is inverted), and so on...
I'm using threejs, but I'm sure that's not necessary for answering.
Use this pattern to determine the direction the x-axis is pointing after applying a series of rotations.
var dir = new THREE.Vector3( 1, 0, 0 );
dir.applyQuaternion( q1 );
dir.applyQuaternion( q2 ); // etc...
To see it visually, you can add axes as a child of your cube mesh. The axes will be rotated automatically.
var axes = new THREE.AxisHelper( 100 );
mesh.add( axes );
three.js r.71

Resources