three.js "exploding" an object in predefined pieces - javascript

This is a sort of a follow up question of my last problem. I want to explode (technical drawing style) an imported .obj geometry which contains n .obj parts.
For example a table as object, each part is one .obj, four legs and a table top.
5 files. loading them is no problem. Now each objects position is 0,0,0 that means I need to get the world position of them, which I did with this function:
function absPos( myMesh ) {
myMesh.geometry.computeBoundingBox();
var boundingBox = myMesh.geometry.boundingBox;
var position = new THREE.Vector3();
position.subVectors( boundingBox.max, boundingBox.min );
position.multiplyScalar( 0.5 );
position.add( boundingBox.min );
position.applyMatrix4( myMesh.matrixWorld );
var abspos = {x:position.x,y:position.y,z:position.z};
return abspos;
}
now I did assume that setting the object´s position to their world positions would just happen to move them to another world position but keep their relation but that is not the case. So I cannot just use the objects world position and use it to translate the objects until I mess with the world position?
As the objects position is 0,0,0 they don´t have a relation to each other and I cannot just multiply the values to "explode" the geometry.
Is there any chance to achieve this without messing with the world positions?

Related

three.js box3 of a imported sphere

i have a short question:
I know how to calculate the boxes of my (imported) 3dobjects f.e.
var box = new THREE.Box3().setFromObject(obj);
With this i can compute boxes for my objects and i can merge them together if i want.
The problem is, now i have these 2 objects https://imgur.com/gallery/NbPwcmB
The solution seems quite simple: i need to compute the left and right spherebox and put them together, but both of these 2 objects are imported with stlloader. I'm not sure how stlloader exactly works, (it seems for me like its all 1 huge mesh) so i'm not even sure if this is possible.
so my questions:
1. how can i compute a box with the shape of a sphere of my sphere object.
2. Is this even possible for my stl object? (I will try when i get the answer for question 1)
Edit: Question 1 should somehow be working with .computeBoundingSphere..
is there a way to make this visible?
how can i compute a box with the shape of a sphere of my sphere object.
Well, in three.js you have the choice between two bounding volumes. THREE.Box3 represents an axis-aligned bounding box (AABB) whereas THREE.Sphere represents a bounding sphere. If you need a box with the shape of a sphere, use THREE.Sphere.
Is this even possible for my stl object?
The method setFromObject() does only exist for THREE.Box3. However, you can compute the bounding sphere via THREE.BufferGeometry.computeBoundingSphere(). This sphere is defined in local space, however. You can use THREE.Sphere.applyMatrix4() to transform it into world space by passing in the world matrix of the 3D object.
is there a way to make this visible?
There is no helper class for bounding spheres. But you can easily create a helper mesh based on THREE.SphereBufferGeometry. Something like:
const geometry = new THREE.SphereBufferGeometry( boundingSphere.radius );
const material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
const mesh = new THREE.Mesh( geometry, material );
mesh.position.copy( boundingSphere.center );
scene.add( mesh );
three.js R109

Three.js: Find the subset of faces visible to camera at a given time

I'm working on a three.js scene in which it would be hugely beneficial to be able to determine the subset of all faces (among all geometries) that are visible to the camera at a given time.
I understand one can determine whether a vertex is visible to the camera by doing something like:
camera.updateMatrix();
camera.updateMatrixWorld();
var frustum = new THREE.Frustum();
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));
// The 3d point to check
var pos = new THREE.Vector3(x, y, z);
if (frustum.containsPoint(pos)) {
// Do something crazy...
}
My geometry has tens of thousands of 2d plane faces, all sitting on a larger plane, and I'd like to determine the set of of their faces that are visible to the camera fairly often (each time the camera zooms past a certain hyperplane, if possible).
I know one can do scene.children[childIndex].visible to see if a mesh is visible, but I have many faces on a mesh and want to determine which of the faces are visible. (All of my meshes are always rendered unless the user zooms wildly). I also know one can adapt this approach:
var frustum = new THREE.Frustum();
var cameraViewProjectionMatrix = new THREE.Matrix4();
// every time the camera or objects change position (or every frame)
camera.updateMatrixWorld(); // make sure the camera matrix is updated
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
cameraViewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromMatrix( cameraViewProjectionMatrix );
console.log( frustum.intersectsBox( meshes[0].geometry.vertices[0] ) );
Is there a shortcut one can take to find the set of all faces visible to the camera at a given time? In my case, I could precompute the geometric mean of each planar face then use the code above to determine which of the faces is visible, but is there anything better than O(n) in this case?
I'd be very grateful for any ideas others can offer on this question!
Better than O(n)?
Given a sorted array of integers I believe one can determine the subset of those integers that line between an upper and lower bound in ~O(log(n)). Each face's geometric mean is a 3d point, so it seems possible to determine the set of points within the frustum with 3*O(log(n)), i.e. better than O(n) complexity.
Better than O(log(n))
An approximation better than O(log(n)) after some precomputing. Suppose we're dealing with only 1D (then we can generalize to 3D). Quantize the space of each axis then create a hash table with the following structure. For each unit in the quantized space, store the index position of the first point in the sorted array with that unit +- error value. Then given an upper and lower bound, round each to the nearest quantized unit and look up the values for those keys to identify the range of index positions within the span. This returns a list. Repeat for the other two dimensions and take the set intersection. [The frustum provides the upper and lower bounds for each dimension.]

Webgl three.js Dependency of several objects

I have a problem with the dependency of objects. I want to make one object dependent on two other objects. If I change the position of one parent object (for example the y-Position), the dependent object (the child object) should rotate und should also move.
Here is a link where I realized it on a picture. On the left side is the initial state, on the right side the changed condition. The Cylinder should be dependent on the two boxes. That means that the cylinder is the child object and the boxes should be both parent objects of this child object.
I tried it with using parent and child properties, but I could not make the child object dependent on two parent objects.
Can someone help me?
This is my current code, but the lookAt Function does not work correctly.
//cube 1
var cube=new THREE.BoxGeometry(4,4,4);
var material=new THREE.MeshBasicMaterial ({ color: 0xffffff });
mesh1=new THREE.Mesh(cube,material);
mesh1.position.set(-2,2,0);
scene.add(mesh1);
//cube 2
var cube2=new THREE.BoxGeometry(2,2,2);
var material=new THREE.MeshBasicMaterial ({ color:0x000000 });
mesh2=new THREE.Mesh(cube2,material);
mesh2.position.x=6;
mesh2.position.y=2;
//mesh2.position.y=-2;
scene.add(mesh2);
//cylinder
var cylinder=new THREE.CylinderGeometry(1,1,6,30);
var material=new THREE.MeshBasicMaterial({ color:0xff3399 });
mesh3=new THREE.Mesh(cylinder,material);
mesh1.add(mesh3);
mesh3.lookAt(mesh2.position);
You need to two levels of hierarchy, eg:
cube1.add(cylinder)
cylinder.add(cube2)
Yeah, 2pha is right actually. I think what he actually needs is something like this (note you'll need to scale the cylinder or move the squares unless they are exactly cylinder height apart):
cylinder.position.x=cube1.position.x
cylinder.position.y=cube1.position.y
cylinder.position.z=cube1.position.z
cylinder.lookAt(cube2.position)
You may be able to do what you're after with the lookAt function on the Object3D class.
eg.
Add your cylinder as a child of cube1 so moving cube1 will also move the cylinder.
cube1.add(cylinder)
then when cube1 (or / and cube2) is moved call the lookAt function on cylinder to look at the cube2's position.
cylinder.lookAt(cube2.position)

Collision detection with boundingSphere

For each mesh (THREE.Object3D) Three.js provide a very handy properties - boundingSphere and boundingSphere that have intersectsSphere and isIntersectionBox methods.
With all this I thought I can use it for simple collision detection but when I try it appears that collision happens all the time because (I tried boundingSphere) boundingSphere.center is always in (0, 0, 0); So If I want to check collisions between 2 meshes I should for each object - clone boundingSphere object and then get it world coordinates and only then to use intersectsSphere.
something like this:
var bs = component.object.geometry.boundingSphere.clone();
bs.center.setFromMatrixPosition(component.object.matrixWorld);
...
if (_bs.intersectsSphere(bs)){
is this how it suppose to be used or am I missing something and there are more convenient way of doing collisions detection based on boundingBox/boundingSphere?
If you want to do collision detection with bounding boxes you need the boxes in the world coordinate system. The bounding volumes in the intersectsSphere and isIntersectionBox properties of the mesh are in the local coordinate system of the object.
You can do like you did: clone the volumes and move them to the correct position in the world coordinate system, that is a good solution.
Otherwise you can also set a new box from your meshes and do collision using those boxes. Let's say you have a THREE.Mesh called mesh then you can do:
sphere = new THREE.Sphere.setFromPoints( mesh.vertices );
box = new THREE.Box3.setFromObject( mesh );
A little tip. During development it can be nice to see the bounding boxes in your scene, for this you can use the THREE.BoundingBoxHelper:
var helper = new THREE.BoundingBoxHelper( mesh );
scene.add( helper );

Mesh position with Repulsion

Right now, my code read multiple object store into a json file. I create cube, sphere and more with different size and materials.
But I would like those mesh to have a random position around (0,0,0) base on a repulsion force to avoid overlaps like this :
This is generate with position.x = Math.random() * 20 - 10;
I would like something like this d3.js example. To have random position of my mesh without overlaping but all to be around the center of the scene.
I'm searching for something, but found nothing right now. I'm really new the WebGL/Three.js.

Categories