I have a 3D model , containing many child meshes.
I want to "explode" that mesh ... meaning that every child mesh has to move away from a central point exactly like that thread :
Exploded view algorithm for CAD
To do that , I generate a bounding box of the ancestor mesh , with THREE.Box3
, and compute the center with .getCenter()
.
The issue here comes from threeJS's scene graph ...
when setting the position of each child , the whole 3D model does explode when I set it to do so in all directions (XYZ) , but when I choose other combinations like X alone , the explode either bugs and spreads in all directions when it shouldn't, or doesn't explode at all .
Here is the code I am using:
/**
* obj : the current node on the scene graph
* box_ct_world : a vec3 center of the bounding box
*
*/
explode : function(obj , parent , box_ct_world , dif){
var scene = this.el.sceneEl.object3D ; //I am using Aframe , so this is how I retrieve the whole scene .
var object = this.el.object3D ; //same here , this for retrieving the whole 3D model .
var speed = 1 ;
if(obj instanceof THREE.Mesh){
var box_center = box_ct_world ;
var position = obj.position ;
/**
* so this is the beginning of my troubles : I am considering retrieving a world position instead of a local position...
* I have to translate the nodes without the parent matrices interfering .
* The current ligne works the same way as if I retrieved local transformations ... exploding on XYZ , but glitching on the other cases .
*/
position.setFromMatrixPosition(scene.matrixWorld) ;
var addx =0 ;
var addy =0 ;
var addz =0 ;
/**
* This is the vector from the center of the box to the node . we use that to translate every meshes away from the center
*/
if(this.data.X === true){
var addx =(position.x - box_center.x)*this.data.factor *speed ;
}
if(this.data.Y === true){
var addy =(position.y - box_center.y)*this.data.factor *speed;
}
if(this.data.Z === true){
var addz =(position.z - box_center.z)*this.data.factor *speed;
}
var explode_vectorx= addx;
var explode_vectory= addy;
var explode_vectorz= addz;
/**
* this is for making the nodes translate back to their original locations
*/
if(diff < 0 ){
if(explode_vectorx > 0)
explode_vectorx = -explode_vectorx ;
if(explode_vectory > 0)
explode_vectory = -explode_vectory;
if(explode_vectorz > 0)
explode_vectorz = -explode_vectorz;
}
if(diff > 0 ){
if(explode_vectorx < 0)
explode_vectorx = -explode_vectorx ;
if(explode_vectory < 0)
explode_vectory = -explode_vectory;
if(explode_vectorz < 0)
explode_vectorz = -explode_vectorz;
}
var vector = new THREE.Vector3(explode_vectorx , explode_vectory, explode_vectorz) ;
console.log(vector.x+" " + vector.y+ " " + vector.z );
/**
* and here is my biggest problem :
* this function seems to use ancestors matrices
* I need the nodes to move without calling the ancestors matrices , but still keep their original rotation and scale .
*/
obj.position.set(vector.x , vector.y , vector.z ) ;
if(obj.children.length != 0 ){
for(var i = 0 ; i < obj.children.length ; i++){
this.explode(obj.children[i] ,obj, box_ct_world , dif);
}
}
}
else{
if(obj.children.length != 0 )
{
for(var i = 0 ; i < obj.children.length ; i++){
this.explode(obj.children[i] ,obj, box_ct_world , dif);
}
}
}
},
so here is a screenshot using a XYZ explode :
It works pretty fine .
But when using a single axis , like X :
the mesh still goes on all axis as if it was random, when it is supposed to translate only on the X axis .
I think this could be fixed by translating the meshes directly in world space , but I don't know how that can be done in threeJS , especially in that case , because I cannot change the values in matrixWorld (A frame is updating the world matrix every frame I think for these objects , so even if I change any value in the matrixWorld , these will be overriden)
thank you all for your help.