0

I am using Three.js. Found a really good Decal library written by Benpurdy. It's very easily modifiable and also used the techniques described here

However, the technique uses Geometry. The project I am on, uses BufferGeometry. I traced the code which does the geometry intersects and can't figure out the conversion from faces and vertices to attributes.

this.createGeometry = function(matrix, mesh) {

  var geom = mesh.geometry;

  var decalGeometry = new THREE.Geometry(); 

  var projectorInverse = matrix.clone().getInverse(matrix);
  var meshInverse = mesh.matrixWorld.clone().getInverse(mesh.matrixWorld);
  var faces = [];

  for(var i = 0; i < geom.faces.length; i++){

    var verts = [geom.faces[i].a, geom.faces[i].b, geom.faces[i].c];

    var pts = [];
    var valid = false;

    for(var v = 0; v < 3; v++) {

      var vec = geom.vertices[verts[v]].clone();

      vec.applyMatrix4(mesh.matrixWorld);
      vec.applyMatrix4(matrix);

      if((vec.z > 1) || (vec.z < -1) || (vec.x > 1) || (vec.x < -1) || (vec.y > 1) || (vec.y < -1)) {
      } else {
        valid = true;
      }

      pts.push(vec);
    }

    if(valid) {

      var uv = [];
      for(var n = 0; n < 3; n++){
        uv.push(new THREE.Vector2( (pts[n].x + 1) / 2, (pts[n].y + 1) / 2));

        pts[n].applyMatrix4(projectorInverse);
        pts[n].applyMatrix4(meshInverse);

        decalGeometry.vertices.push( pts[n] );
      }

      // update UV's
      decalGeometry.faceVertexUvs[0].push(uv);

      var newFace = geom.faces[i].clone();

      newFace.a = decalGeometry.vertices.length - 3;
      newFace.b = decalGeometry.vertices.length - 2;
      newFace.c = decalGeometry.vertices.length - 1;

      decalGeometry.faces.push(newFace);
    }

  }

  return decalGeometry;
}

Appreciate if anyone could shed some light on how to go about pursuing this? Thanks.

Kenneth W
  • 1
  • 3

3 Answers3

0

BufferGeometry() has a method .fromGeometry(). Populates this BufferGeometry with data from a Geometry object.

var geom = new THREE.BoxGeometry(1,1,1);
var bufGeom = new THREE.BufferGeometry().fromGeometry(geom);

UPD. You can use the other way round.

var bufGeom = new THREE.BoxBufferGeometry(1,1,1);
var geom = new THREE.Geometry().fromBufferGeometry(bufGeom);
prisoner849
  • 16,894
  • 4
  • 34
  • 68
  • Thanks, I have tried that. While it works, the "decal" feature I am using quickly becomes expensive and slow on moderately large models. But thanks for this. – Kenneth W Nov 15 '16 at 10:01
  • Thanks for the update. Yes, those will transform between geometry and buffergeometry. I have tried them and as mentioned, causes a memory spike from 200mb to 900mb. I have a solution I coded addressed the problem at its root, dealing with mesh intersection and conjuring a mesh capable of handling buffergeometry. – Kenneth W Nov 16 '16 at 05:12
0

I ended up solving the problem by writing another function to compute intersections with buffergeometry. Took me a while trying to understand the original buffer geometry code.

this.createGeometryFromBufferGeometry = function(matrix, mesh) {

  var geom = mesh.geometry;

  var decalGeometry = new THREE.Geometry(); 

  var projectorInverse = matrix.clone().getInverse(matrix);
  var meshInverse = mesh.matrixWorld.clone().getInverse(mesh.matrixWorld);
  var faces = [];

  for(var i = 0; i < geom.attributes.position.array.length; i+=9){

    var pts = [];
    var valid = false;

    for(var v = 0; v < 9; v+=3) {


      var vec = new THREE.Vector3(geom.attributes.position.array[i+v],geom.attributes.position.array[i+v+1],geom.attributes.position.array[i+v+2]);
      console.log((i+v) + " " + (i+v+1) + " " + (i+v+2) );
      console.log(vec);

      vec.applyMatrix4(mesh.matrixWorld);
      vec.applyMatrix4(matrix);

      if((vec.z > 1) || (vec.z < -1) || (vec.x > 1) || (vec.x < -1) || (vec.y > 1) || (vec.y < -1)) {
      } else {
        valid = true;
      }

      pts.push(vec);
    }


    if(valid) {

      var uv = [];
      for(var n = 0; n < 3; n++){
        uv.push(new THREE.Vector2( (pts[n].x + 1) / 2, (pts[n].y + 1) / 2));

        pts[n].applyMatrix4(projectorInverse);
        pts[n].applyMatrix4(meshInverse);

        decalGeometry.vertices.push( pts[n] );
      }

      decalGeometry.faceVertexUvs[0].push(uv);

      var newFace = new THREE.Face3()

      newFace.a = decalGeometry.vertices.length - 3;
      newFace.b = decalGeometry.vertices.length - 2;
      newFace.c = decalGeometry.vertices.length - 1;

      decalGeometry.faces.push(newFace);
    }

  }
  return decalGeometry;
}
Kenneth W
  • 1
  • 3
0

Quick and dirty solution is to create geometry from bufferGeometry and after calculating dispose created geometry

this.compute = function()
{
   this.geometry = mesh.geometry
   if(this.geometry.attributes)
   {
        this.geometry = new THREE.Geometry().fromBufferGeometry(this.geometry);
        this.computeDecal();
        this.geometry.dispose();
    }
    else
    {
        this.computeDecal();
    }
}