ThreeJS bufferGeometry position attribute not updating when translation applied - javascript

I used STLLoader to load an stl onto a threeJS scene returning a BufferGeometry.
I then used
myMesh.position.set( x,y,z )
myMesh.rotation.setFromQuaternion ( quaternion , 'XYZ');
to translate the geometry. This effectively changes the
myMesh.position
myMesh.quaternion
Translation is happening in the scene and all works well.
I expected that the
myMesh.geometry.attributes.position.array
would be different before and after the translation - but it remained identical. I want to extract the new veritces from the buffergeometry after translation.
I tried to call
myMesh.geometry.dynamic = true;
myMesh.geometry.attributes.position.needsUpdate = true;
in the render loop but no luck as I haven't updated the vertices explicity.

You want to get the world position of a mesh's geometry, taking into consideration the mesh's transform matrix, mesh.matrix. Also, your mesh geometry is THREE.BufferGeometry.
Here is the pattern to follow:
mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 10, 10, 10 );
mesh.rotation.set( - Math.PI / 2, 0, 0 );
mesh.scale.set( 1, 1, 1 );
scene.add( mesh );
mesh.updateMatrix(); // make sure the mesh's matrix is updated
var vec = new THREE.Vector3();
var attribute = mesh.geometry.attributes.position; // we want the position data
var index = 1; // index is zero-based, so this the the 2nd vertex
vec.fromAttribute( attribute, index ); // extract the x,y,z coordinates
vec.applyMatrix4( mesh.matrix ); // apply the mesh's matrix transform
three.js r.71

Related

THREE.JS Texture Mapping on ExtrudeGeometry

I'm working on a problem with three.js and ExtrudeGeometry.
I do have a wave-like structure which is made from several individual frames. Each of them is extruded using ExtrudeGeometry.
I'd like to apply a texture to each frame of the structure which is "wrapped around" the structure. For some reason (possibly wrong UV-mapping?) the texture does not display correctly on the extruded edges where the wave-like surface is out of level. (There are some tiny sections in the picture where the texture wraps correctly). I'm using the following script to apply the textures:
// create some simple Geometry
var shape = new THREE.Shape();
shape.moveTo( 0,0 );
shape.lineTo( 0,10 );
shape.lineTo( 100,7 );
shape.lineTo( 100,0 );
var extrudeSettings = {
steps: 2,
amount: 10,
bevelEnabled: false,
bevelThickness: 0,
bevelSize: 0,
bevelSegments: 0
};
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var texture = new THREE.Texture( image );
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
texture.repeat.set( 0.1, 0.1 );
var material = new THREE.MeshBasicMaterial( {map: texture} );
var mesh = new THREE.Mesh( geometry, material ) ;
scene.add( mesh );
Every help is much appreciated! Cheers!
Edit:
I've created this image to better illustrate the problem. White Arrows show, how the texture is supposed to wrap around the object. At some very rare spots it actually does!
Have a look at this example
https://threejs.org/examples/?q=geome#webgl_geometry_shapes
at row 70 there is a comment that states that texture.repeat must be set to (0.008, 0.008)

How to make a object follow the direction of the PointerLockControls in Three.js?

I am using Three.js and PointerLockControls to create simple FPS game. What I am trying to do is to attach a weapon to the camera/controls.
I was able to position the gun in front of the camera and move it along on the x/y axis, but it does not move along the z axis (up/down).
function updateGun() {
if (weapon) {
const yaw = controls.getObject();
weapon.position.set(
yaw.position.x - Math.sin(yaw.rotation.y) * 3,
yaw.position.y - 1,
yaw.position.z - Math.cos(yaw.rotation.y) * 3);
weapon.rotation.set(
yaw.rotation.x,
(yaw.rotation.y - Math.PI),
yaw.rotation.z);
}
}
If you are using PointerLockControls and want to add an object that remains in front of the camera, you can use this pattern:
var mesh = new THREE.Mesh( new THREE.SphereGeometry( 5, 16, 8 ), new THREE.MeshNormalMaterial() );
mesh.position.z = - 100; // some negative number
camera.add( mesh );
If you are not using PointerLockControls, you can still use the same technique, you just have to be sure to add the camera as a child of the scene.
scene.add( camera );
camera.add( mesh );
three.js r.84

Reverse vertex order in THREE.js face

I need to reverse vertex order in faces of my geometry.
In example:
// create geometry
var geometry = new THREE.Geometry();
// create vertices
geometry.vertices.push( new THREE.Vector3( 0, 0, 0 ) );
geometry.vertices.push( new THREE.Vector3( 0, 100, 0 ) );
geometry.vertices.push( new THREE.Vector3( 100, 0, 0 ) );
// create face
var face = new THREE.Face3( 0, 1, 2 );
geometry.faces.push ( face );
// compute normals
geometry.computeFaceNormals();
geometry.computeVertexNormals();
// add to scene
var mesh = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({color: 0x00ffff})
);
scene.add( mesh );
Now I need to change order of vertices in face from 0,1,2 to 2,1,0. But when I do this manually it does not work no matter which flags for update I set to true.
The question - is it possible to reverse vertices order on the fly and if yes then how?
Important - It's better to avoid using negative scale for geometry in this case. And it's also better to avoid re-creating of object.
THREE.js: r73
delete mesh.geometry.__directGeometry;
This should apply yours changes. In some reason in r72 and r73 __directGeometry not updated automatically.

How to transform a cube mesh into a diamond shape

Is there a way in three.js to turn a cube mesh shape into a diamond shape doing something like rotating the axis of the scale and then scaling it? I'm trying to create a flat-ish diamond shape, something like x50,y50,x10. If not, then what's the best way to create a diamond mesh, or a triangle mesh shape?
If you just turn the cube on its end and scale x you'll still have a (now imbalanced) rectangle shape, but if you turn it on it's end, reorient the axis of scale somehow so it's stretching across the middle from point to point, now you could just squeeze the cube with scale x, and you'd have a nice diamond shape with a thin waist.
For clarification, here's a pic of the mesh shape I am trying to make, ideally the diamond shape on the left, but the triangle shape will do also.
So, is there some way to rotate the axis of the scale? Is that what new THREE.Matrix4().makeTranslation is for? How do I use that in this context?
See plunker of my attempt here. Clearly my cube.scale.x = 0.5; code is not working and needs the axis of transform to be shifted.
Here's the js:
cube = new THREE.Mesh( geometry, material );
cube.rotation.z = Math.PI / 4 ;
cube.position.y = 35;
cube.scale.x = 0.5;
scene.add( cube );
If you want to convert your cube or box into a diamond shape, then the easiest method is to transform your geometry using a pattern like this one:
var geometry = new THREE.BoxGeometry( 100, 100, 20 );
geometry.applyMatrix( new THREE.Matrix4().makeRotationZ( Math.PI / 4 ) );
geometry.applyMatrix( new THREE.Matrix4().makeScale( 1, 2, 1 ) ); // optional
Once you create your mesh, you still have the option of further scaling the mesh, itself.
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( sz, sy, sz );
scene.add( mesh );
three.js r.71
What you need to do is to create a hierarchy of objects, the inner object will rotate around the z-axis and the outer object will scale on the x-axis.
mesh = new THREE.Mesh(geometry, material);
mesh.rotation.z = Math.PI / 4; // rotate by 45 degrees
var group = new THREE.Group();
group.add( mesh );
group.scale.x = 0.5; // scale by 0.5
scene.add( group );
Here is a fiddle: http://jsfiddle.net/3gxqboer/

Three.js: Rotate Cylinder into Vector3 direction

I've already searched, but didn't find anything that helps:
I got an vector and a CylinderGeometry Mesh. I want to acchieve, that the cylinder is facing the point where the vector is showing. As input I got a position (c) and a direction (m) (like a line equation: y = mx + c):
function draw (m,c, _color) {
//... create the geometry and mesh
// set the position
line.position.x = c.x;
line.position.y = c.y;
line.position.z = c.z;
// i've tried something like this:
line.lookAt(c.add(m));
//.. and add to scene
}
But it looks like the direction is the direct opposite of what I want to acchieve.
I've also tried stuff like translation:
geometry.applyMatrix( new THREE.Matrix4().makeTranslation(0, length/2, 0));
and tried to get the rotation manually like line.rotation.x = direction.angleTo(vec3(1,0,0))* 180 / Math.PI;. But none of them worked like I needed.
This works for me:
// Make the geometry (of "distance" length)
var geometry = new THREE.CylinderGeometry( 0.6, 0.6, distance, 8, 1, true );
// shift it so one end rests on the origin
geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, distance / 2, 0 ) );
// rotate it the right way for lookAt to work
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( THREE.Math.degToRad( 90 ) ) );
// Make a mesh with the geometry
var mesh = new THREE.Mesh( geometry, material );
// Position it where we want
mesh.position.copy( from.sceneObject.position );
// And make it point to where we want
mesh.lookAt( to.sceneObject.position );

Categories

Resources