how to make a transition from one mesh to another? - javascript

I have mesh1 and Mesh2. Each has extrusion.
mesh1 ->100 vertices
mesh2 ->200 vertices
In my code I do the following:
mesh1.geometry.verticesNeedUpdate = true;
mesh1 = Mesh2;
mesh1.geometry.computeBoundingBox ();
and so I manage to update mesh1 (this works in my original code), but I do not want you to see any abrupt change. I want an animation while mesh1 becomes the geometry Mesh2.
I've always used the library tween.js. So for example:
new TWEEN.Tween (mesh1.scale) .to ({x: 1, and 1, z 1}, 1000) .start ();
but I don't know how to do animation in this case.
With transition or animation, you see the changes in real time of the vertices of mesh2 to mesh1. I do not want to display any abrupt change.

You can use morphTarget for it. You have sets of vertices with same length, but with different positions. Then you set the morphTargetInfluences to effect the transition from that set of vertices to another set of vertices.
This is from Threejs Geometry documentation
.morphTargets
Array of morph targets. Each morph target is a Javascript object:
{ name: "targetName", vertices: [ new THREE.Vector3(), ... ] } Morph vertices match number and order of primary vertices.
This is a good example. View it's source code for better understanding.

Related

Dynamically adding faces to a three.js geometry

I'm working on some webgl software for generating 3D models and am relying on dynamic geometry. I've observed some very bizarre behavior that I've been able to isolate in this jsfiddle.
It seems that any new faces added after a geometry instance has been added to the scene, any new faces added will not be rendered (properly). In wireframe mode (as in the example), the new geometry is not rendered at all. When using textured materials, I also observed that sometimes new geometry is not rendered depending on the angle of the camera.
Here's a video of that in action.
Back to the jsfiddle, I used an existing three.js code sample (misc_exporter_obj.html) as a scaffold but on line 7 I made a generic function to add a triangle to the geometry. The addGeometry function is called on startup, and if you uncomment line 36 you can see what the expected result should have been:
var material = new THREE.MeshBasicMaterial( { wireframe : true} );
geometry = new THREE.Geometry();
addTriangle(-50, -50, 50, -50, 50, 50);
//addTriangle(-50, -50, -50, 50, 50, 50); // UNCOMMENT TO TEST WHAT FINAL OUTPUT SHOULD LOOK LIKE.
scene.add( new THREE.Mesh( geometry, material ) );
And as per the threejs guide on how to update things, lines 43-47 attempt to add a new triangle when you click the "transform triangle" button by setting the verticesNeedUpdate and elementsNeedUpdate flags:
function addTriangleFace(){
addTriangle(-50, -50, -50, 50, 50, 50);
geometry.verticesNeedUpdate = true;
geometry.elementsNeedUpdate = true;
}
Am I doing this wrong? Or should I submit a bug report?
Thanks.
Disappearing Mesh Update:
I may have discovered the cause of the weird behavior that was causing my mesh to be erased based on camera orientation. This answer suggests that Three.js may have thought that the mesh was not inside the camera's frustum.
I'm guessing the new vertices were not being considered when trying to determine whether the object was in the frustum, so I just disabled culling since the object being drawn is the main object in the scene.
You want to add faces to an existing geometry.
Since buffers can't be resized, the best solution is to switch to BufferGeometry, preallocate sufficiently-sized buffers, and set the drawRange. See this SO answer. This answer, too.
If you add vertices, you will need to recompute the bounding sphere for frustum culling to work correctly.
geometry.computeBoundingSphere();
Or, as you said, you can disable frustum culling:
mesh.frustumCulled = false;
three.js.r.91

How to Change a Box's dimensions/size after creation?

One can easily create a THREE.BoxGeometry where you have to pass arguments when creating as three separated arguments for width, height, and depth.
I would like to create any and all THREE[types]() with no parameters and set the values after that.
Is there a way to set the dimensions/size of the box geometry after creation (possibly buried in a Mesh already too)? other then scaling etc.
I couldn't find this in the documentation if so, otherwise maybe a major feature request if not a bug there. Any thoughts on how to classify this? maybe just a documentation change.
If you want to scale a mesh, you have two choices: scale the mesh
mesh.scale.set( x, y, z );
or scale the mesh's geometry
mesh.geometry.scale( x, y, z );
The first method modifies the mesh's matrix transform.
The second method modifies the vertices of the geometry.
Look at the source code so you understand what each scale method is doing.
three.js r.73
When you instantiate a BoxGeometry object, or any other geometry for that matter, the vertices and such buffers are created on the spot using the parameters provided. As such, it is not possible to simply change a property of the geometry and have the vertices update; the entire object must be re-instantiated.
You will need to create your geometries as you have the parameters for them available. You can however create meshes without geometries, add them to a scene, and update the mesh's geometry property once you have enough information to instantiate the object. If not that, you could also set a default value at first and then scale to reach your target.
Technically, scaling only creates the illusion of an updated geometry and the question did say (other then scaling). So, I would say a better approach would be to reassign the geometry property of your mesh to a new geometry.
mesh.geometry = new THREE.BoxGeometry(newSize, newSize, newSize)
With this approach you can update any aspect of the geometry including width segments for example. This is especially useful when working with non box geometries like cylinders or spheres.
Here is a full working example using this approach:
let size = 10
let newSize = 20
// Create a blank geometry and make a mesh from it.
let geometry = new THREE.BoxGeometry()
let material = new THREE.MeshNormalMaterial()
let mesh = new THREE.Mesh(geometry, material)
// Adding this mesh to the scene won't display anything because ...
// the geometry has no parameters yet.
scene.add(mesh)
// Unless you intend to reuse your old geometry dispose of it...
// this will significantly reduce memory footprint.
mesh.geometry.dispose()
// Update the mesh geometry to a new geometry with whatever parameters you desire.
// You will now see these changes reflected in the scene.
mesh.geometry = new THREE.BoxGeometry(size, size, size)
// You can update the geometry as many times as you like.
// This can be done before or after adding the mesh to the scene.
mesh.geometry = new THREE.BoxGeometry(newSize, newSize, newSize)

How do I change the basic parameters of a Geometry in Three.js (for example, radius, number of vertices, etc.)

I create a tetrahedron of radius 3
// create a tetrahedron
var tetGeometry = new THREE.TetrahedronGeometry(3);
var tetMaterial = new THREE.MeshLambertMaterial(
{color: 0x20f020, transparent:true, opacity:0.6});
tet = new THREE.Mesh(tetGeometry, tetMaterial);
tet.name='tet';
tet.castShadow = true;
Later, I want the tetrahedron to grow:
// change hedron
scene.getObjectByName('tet').radius = control.hedronRadius;
That doesn't work.
// change vertices
scene.getObjectByName('tet').detail = control.hedronVertices;
That doesn't work either.
scene.getObjectByName('tet').verticesNeedUpdate;
And this doesn't help.
So how do I change the radius of a tetrahedron (or any Geometry) and how do I change the vertices.
In the documentation I see references to:
Geometry
.dynamic
.morph
.verticesNeedUpdate
.scale
And also references to bones and skeletons and skinned meshes used to animate geometries.
How do I change these aspects of Geometries in general?
What's the most reasonable, suggested way then to grow the radius of a Tetrahedron, or change the number of vertices show it becomes a different number polyhedron?
To change geometry you need to use:
morphTargets: true
I've prepared an example using a tetrahedron as you mention in jsfiddle.
Use sliders to change geometry.
To make some custom vertices and "fill" them by faces, you need to understand a lot of things from math, like; point, vector, etc.
I've done 2 simple flat objects, triangle and square in jsfiddle.
I hope that you'll easy understand how it works in general.

How to change the normal of a PlaneGeometry in three.js?

I'm using Three.js to display planes, however I can't seem to find a way to change the normal of it. There's a Plane class that has a normal property so is there any way to use this instead of the PlaneGeometry one?
PlaneGeometry offers no means to change its normal, which is effectively always (0,0,1).
To make the plane geometry face in a different direction, you need to transform its vertices. This
is done by converting a Plane object to a transformation matrix and applying that
matrix to the PlaneGeometry. Here is code that generates a transformation matrix:
// Assumes that "plane" is the source THREE.Plane object.
// Normalize the plane
var normPlane=new THREE.Plane().copy(plane).normalize();
// Rotate from (0,0,1) to the plane's normal
var quaternion=new THREE.Quaternion()
.setFromUnitVectors(new THREE.Vector3(0,0,1),normPlane.normal);
// Calculate the translation
var position=new THREE.Vector3(
-normPlane.constant*normPlane.normal.x,
-normPlane.constant*normPlane.normal.y,
-normPlane.constant*normPlane.normal.z);
// Create the matrix
var matrix=new THREE.Matrix4()
.compose(position,quaternion,new THREE.Vector3(1,1,1));
// Transform the geometry (assumes that "geometry"
// is a THREE.PlaneGeometry or indeed any
// THREE.Geometry)
geometry.applyMatrix(matrix);
There is another option that perhaps can suit you. You can use lookAt method from the Mesh class. This method is inherited from Object3D class. You just need to specify the point where the plane will look. This way you can reuse your PlaneGeometry for other Mesh instances.
var geometry = new THREE.PlaneGeometry( 12, 12 );
var material = new THREE.MeshBasicMaterial( { color: 0x005E99 } );
var plane = new THREE.Mesh( geometry, material );
plane.lookAt(new THREE.Vector3(0.7, 0.7, 0.7));

Face normals on dynamic geometry

I'm trying to create a vertex animation for a mesh.
Just imagine a vertex shader, but in software instead of hardware.
Basically what I do is to apply a transformation matrix to each vertex. The mesh it's ok but the normals doesn't look good at all.
I've try to use both computeVertexNormals() and computeFaceNormals() but it just doesn't work.
The following code is the one I used for the animation (initialVertices are the initial vertices generated by the CubeGeometry):
for (var i=0;i<mesh1.geometry.vertices.length; i++)
{
var vtx=initialVertices[i].clone();
var dist = vtx.y;
var rot=clock.getElapsedTime() - dist*0.02;
matrix.makeRotationY(rot);
vtx.applyMatrix4(matrix);
mesh1.geometry.vertices[i]=vtx;
}
mesh1.geometry.verticesNeedUpdate = true;
Here there're two examples, one working correctly with CanvasRenderer:
http://kile.stravaganza.org/lab/js/dynamic/canvas.html
and the one that doesn't works in WebGL:
http://kile.stravaganza.org/lab/js/dynamic/webgl.html
Any idea what I'm missing?
You are missing several things.
(1) You need to set the ambient reflectance of the material. It is reasonable to set it equal to the diffuse reflectance, or color.
var material = new THREE.MeshLambertMaterial( {
color:0xff0000,
ambient:0xff0000
} );
(2) If you are moving vertices, you need to update centroids, face normals, and vertex normals -- in the proper order. See the source code.
mesh1.geometry.computeCentroids();
mesh1.geometry.computeFaceNormals();
mesh1.geometry.computeVertexNormals();
(3) When you are using WebGLRenderer, you need to set the required update flags:
mesh1.geometry.verticesNeedUpdate = true;
mesh1.geometry.normalsNeedUpdate = true;
Tip: is it a good idea to avoid new and clone in tight loops.
three.js r.63

Categories

Resources