title: THREE js : Simplify a mesh to optimize performance
body: <p>I have a mesh (image 1) and a parallelepipede, I add the intersection result of this 2 objects in a scene and I move the parallelepipede along my mesh repeating the same process to "cut" my mesh and get an exploded view of my mesh (image 2).</p>
  
  <p>Problem is that the process time is more than 2 mins... I have tryed to reduce the mesh with meshmixxer but it's not enough... Does someone has another idea ?</p>
  
  <p><a href="https://i.stack.imgur.com/UW1B1.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UW1B1.png" alt="image 1"></a> 
  <a href="https://i.stack.imgur.com/x3XDM.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/x3XDM.png" alt="image 2"></a> </p>
  
  <pre><code>function FirstCut() {
  
      var scene, camera, renderer, controls;
  
      //stl loader from https://threejs.org/examples/webgl_loader_stl.html
      // cf example https://stemkoski.github.io/Three.js/CSG.html
  
      //with obj
  
      init();
      animate();
  
      function init() {
  
          scene = new THREE.Scene();
          scene.background = new THREE.Color(0xeeeeee);
  
          camera = new THREE.PerspectiveCamera(75, 800 / 500, 1, 2000);
  
          //camera.position.set(50, 500, 0);
          camera.position.x = 50;
          camera.position.y = 500;
          camera.position.z = 0;
  
          //var axeX = new THREE.Vector3(1, 0, 0);
          //camera.rotateOnAxis(axeX, -1);
          camera.lookAt(new THREE.Vector3(0, 500, 0));
  
          controls = new THREE.OrbitControls(camera);
          //les valeurs de min and max distance sont choisies pour que le filet ne disparaisse pas quand on le fait tourner
          controls.minDistance = 0;
          controls.maxDistance = 1000;
          //scene
          //var ambient = new THREE.AmbientLight(0x101030);
          //scene.add(ambient);
          //scene.add(new THREE.GridHelper(1000, 20));
          //var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
          //directionalLight.position.set(0, 1, 0);
          //scene.add(directionalLight);
  
          var widthH = parseInt(document.getElementById("wdthH").value) || 0; // H for Head
          var widthT = parseInt(document.getElementById("wdthT").value) || 0; // T for tail
          var height = parseInt(document.getElementById("hght").value) || 0;  // flank
  
          //création du pavé
          var EmportePieceH = new THREE.BoxGeometry(300, 60, widthH);
          var EmportePieceT = new THREE.BoxGeometry(300, 60, widthT);
          var EmportePieceB = new THREE.BoxGeometry(height, 60, 520);
  
          var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  
          // création du meshage et material
          var EmportePieceMeshH = new THREE.Mesh(EmportePieceH, paveMaterial);
          var EmportePieceMeshT = new THREE.Mesh(EmportePieceT, paveMaterial);
          var paveMeshB = new THREE.Mesh(EmportePieceB, paveMaterial);
  
          var zH = 247 - widthH / 2;
          var zT = -247 + widthT / 2;
          EmportePieceMeshH.position.set(0, 30, zH);
          EmportePieceMeshT.position.set(0, 30, zT);
          paveMeshB.position.set(-95 + height / 2, 30, 0);
          var EmportePieceBSPH = new ThreeBSP(EmportePieceMeshH);
          var EmportePieceBSPT = new ThreeBSP(EmportePieceMeshT);
          var paveBSPB = new ThreeBSP(paveMeshB);
  
          //scene.add(EmportePieceMeshH);
          //scene.add(EmportePieceMeshT);
          //scene.add(paveMeshB);
  
  
          // texture
          var manager = new THREE.LoadingManager();
          manager.onProgress = function (item, loaded, total) {
              console.log(item, loaded, total);
          };
          var texture = new THREE.Texture();
          var onProgress = function (xhr) {
              if (xhr.lengthComputable) {
                  var percentComplete = xhr.loaded / xhr.total * 100;
                  console.log(Math.round(percentComplete, 2) + '% downloaded');
              }
          };
          var onError = function (xhr) {
          };
  
          var loader = new THREE.ImageLoader(manager);
          loader.load('/Scan/filet_1kg500-reposition-reduit_material_0.jpg', function (image) {
              texture.image = image;
              texture.needsUpdate = true;
          });
  
          var width = parseInt(document.getElementById("wdth").value) || 0;
  
          //création du pavé
          var paveGeom = new THREE.BoxGeometry(250, 250, width);
          var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  
          // création du meshage parallélépipède avec material
          var paveMesh = new THREE.Mesh(paveGeom, paveMaterial);
  
          var z0 = -247 + widthH;
          paveMesh.position.set(0, 0, z0);
  
          var paveBSP = new ThreeBSP(paveMesh);
          //scene.add(paveMesh);
  
          //tableau des volumes
          var tabVolumes = new Array();
  
          // model
          var loader = new THREE.OBJLoader(manager);
          loader.load('/Scan/filet_1kg500-reposition-reduit.obj', function (object) {
              object.traverse(function (child) {
                  if (child instanceof THREE.Mesh) {
                      child.material.map = texture;
  
                      var geo = new THREE.Geometry().fromBufferGeometry(child.geometry);
                      var filetMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
                      var filetMesh = new THREE.Mesh(geo, filetMaterial);
                      //scene.add(filetMesh);
                      var newBSPH, newBSPT, newBSPB, newBSP2, newBSP1, filletBSP
                      var filetBSP = new ThreeBSP(filetMesh);
  
                      newBSPH = filetBSP.intersect(EmportePieceBSPH);
                      newBSPT = filetBSP.intersect(EmportePieceBSPT);
                      newBSPB = filetBSP.intersect(paveBSPB);
                      newBSP2 = filetBSP.subtract(EmportePieceBSPH);
                      newBSP1 = newBSP2.subtract(paveBSPB);
                      filletBSP = newBSP1.subtract(EmportePieceBSPT);
  
                      ////////////////////subtract//////////////////////////////
  
                      var newFilet = new THREE.Geometry();
                      newFilet = filletBSP.toGeometry();
                      var newFilletMesh = new THREE.Mesh(newFilet, new THREE.MeshBasicMaterial({ map: texture }));
                      newFilletMesh.position.set(0, 0, 0);
  
                      ///////////////////////////////////création morceaux découpés///////////////////////////////////////////
  
                      var HeadFillet = new THREE.Geometry();
                      var TailFillet = new THREE.Geometry();
                      var degraissageFillet = new THREE.Geometry();
                      HeadFillet = newBSPH.toGeometry();
                      TailFillet = newBSPT.toGeometry();
                      degraissageFillet = newBSPB.toGeometry();
  
  
                      /////////////////////////////////calcul des volumes des 1ers morceaux/////////////////////////////////////////
  
                      if (widthH != 0) {
                          tabVolumes[0] = calculateVolume2(HeadFillet);
                      } else { tabVolumes[0] = 0;}
  
                      if (widthT != 0) {
                          //alert(tabVolumes[0]);
                          tabVolumes[1] = calculateVolume2(TailFillet);
                      } else { tabVolumes[1] = 0; }
  
                      if (height != 0) {
                          tabVolumes[2] = calculateVolume2(degraissageFillet);
                      } else { tabVolumes[2] = 0; }
  
                      var ind = 3;
  
                      var HeadFilletMesh = new THREE.Mesh(HeadFillet, new THREE.MeshBasicMaterial({ map: texture }));
                      var TailFilletMesh = new THREE.Mesh(TailFillet, new THREE.MeshBasicMaterial({ map: texture }));
                      var degraissageFilletMesh = new THREE.Mesh(degraissageFillet, new THREE.MeshBasicMaterial({ map: texture }));
  
                      HeadFilletMesh.position.set(0, 0, 20);
                      degraissageFilletMesh.position.set(-20, 0, 0);
                      TailFilletMesh.position.set(0, 0, -20);
                      scene.add(HeadFilletMesh);
                      scene.add(TailFilletMesh);
                      scene.add(degraissageFilletMesh);
  
                      //scene.add(newFilletMesh);
                      var cloneHeadFilletMesh = HeadFilletMesh.clone();
                      var cloneTailFilletMesh = TailFilletMesh.clone();
                      var clonedegraissageFilletMesh = degraissageFilletMesh.clone();
  
                      var mesh_decoupe = new THREE.Object3D;
                      mesh_decoupe.add(cloneHeadFilletMesh);
                      mesh_decoupe.add(cloneTailFilletMesh);
                      mesh_decoupe.add(clonedegraissageFilletMesh);
  
                      if (width != 0) {
                          var paveGeom = new THREE.BoxGeometry(300, 300, width);
                          var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  
  
                          var fillet2BSP = new ThreeBSP(newFilletMesh);
  
                          var intersectionPave = new THREE.Geometry();
                          intersectionPave = fillet2BSP.intersect(paveBSP);
  
                          var geometryPave = new THREE.Geometry();
                          geometryPave = intersectionPave.toGeometry();
                          var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
  
  
                          //alert(geometryPave.faces.length);
  
                          while (geometryPave.faces.length != 0) {
  
  
                              var z = paveMesh.position.z + width + 5;
  
                              paveMesh.position.set(0, 0, z);
                              paveBSP = new ThreeBSP(paveMesh);
                              //scene.add(paveMesh);
  
                              fillet2BSP = new ThreeBSP(newFilletMesh);
  
                              intersectionPave = filletBSP.intersect(paveBSP);
                              geometryPave = intersectionPave.toGeometry();
  
                              tabVolumes[ind] = calculateVolume2(geometryPave);
                              ind = ind + 1;
  
                              var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
                              newMesh.position.set(0, 0, newMesh.position.z);
                              scene.add(newMesh);
  
                              var meshSave = newMesh.clone();
                              mesh_decoupe.add(meshSave);
                          }
  
                          document.body.style.cursor = '';
  
                      } else {
                          scene.add(newFilletMesh);
                          document.body.style.cursor = '';
  
  
                          tabVolumes[3] = 0;
                          tabVolumes[4] = calculateVolume2(newFilet);
                      }
  
  
  
                      //    }
                      //}
                      //else {
                      //    scene.add(newFilletMesh);
  
                      //    tabVolumes[ind] = calculateVolume2(newFilet);
                      //}
  
  
                      //alert(calculateVolume2(newBSP.toGeometry()));
  
                      //afficher les volumes dans la textarea
  
  
                      var txtVolume = document.getElementById("txtVolume");
                      txtVolume.value = tabVolumes.join("\n");
  
                      //var exporter = new THREE.OBJExporter();
                      //var result = exporter.parse(mesh_decoupe);
                      //var blob = new Blob([result], { type: 'text/plain' });
                      //saveAs(blob, 'dechets.obj');
  
                  }
              });
              //scene.add(object);
  
          }, onProgress, onError);
  
          renderer = new THREE.WebGLRenderer();
          renderer.setSize(800, 500, false);
  
          document.getElementById('canvas3D').innerHTML = "";
          document.getElementById('canvas3D').appendChild(renderer.domElement);
      }
          function animate() {
  
              requestAnimationFrame(animate);
              camin();
              renderer.render(scene, camera);
  
  
          }
  
          function camin() {
              camera.position.y -= .1;
          }
  
  
              function volumeOfT(p1, p2, p3) {
              var v321 = p3.x * p2.y * p1.z;
              var v231 = p2.x * p3.y * p1.z;
              var v312 = p3.x * p1.y * p2.z;
              var v132 = p1.x * p3.y * p2.z;
              var v213 = p2.x * p1.y * p3.z;
              var v123 = p1.x * p2.y * p3.z;
              return (-v321 + v231 + v312 - v132 - v213 + v123) / 6.0;
          }
  
          function calculateVolume2(object) {
              var volumes = 0.0;
  
              for (var i = 0; i &lt; object.faces.length; i++) {
                  var Pi = object.faces[i].a;
                  var Qi = object.faces[i].b;
                  var Ri = object.faces[i].c;
                  //alert (Pi);
  
                  var P = new THREE.Vector3(object.vertices[Pi].x, object.vertices[Pi].y, object.vertices[Pi].z);
                  //alert(object.vertices[Pi].x);
                  var Q = new THREE.Vector3(object.vertices[Qi].x, object.vertices[Qi].y, object.vertices[Qi].z);
                  var R = new THREE.Vector3(object.vertices[Ri].x, object.vertices[Ri].y, object.vertices[Ri].z);
                  volumes += volumeOfT(P, Q, R);
              }
  
              return Math.abs(volumes);
  
        }
  }
  
  
  
  function FirstCut() {
  
      var scene, camera, renderer, controls;
  
      //stl loader from https://threejs.org/examples/webgl_loader_stl.html
      // cf example https://stemkoski.github.io/Three.js/CSG.html
  
      //with obj
  
      init();
      animate();
  
      function init() {
  
          scene = new THREE.Scene();
          scene.background = new THREE.Color(0xeeeeee);
  
          camera = new THREE.PerspectiveCamera(75, 800 / 500, 1, 2000);
  
          //camera.position.set(50, 500, 0);
          camera.position.x = 50;
          camera.position.y = 500;
          camera.position.z = 0;
  
          //var axeX = new THREE.Vector3(1, 0, 0);
          //camera.rotateOnAxis(axeX, -1);
          camera.lookAt(new THREE.Vector3(0, 500, 0));
  
          controls = new THREE.OrbitControls(camera);
          //les valeurs de min and max distance sont choisies pour que le filet ne disparaisse pas quand on le fait tourner
          controls.minDistance = 0;
          controls.maxDistance = 1000;
          //scene
          //var ambient = new THREE.AmbientLight(0x101030);
          //scene.add(ambient);
          //scene.add(new THREE.GridHelper(1000, 20));
          //var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
          //directionalLight.position.set(0, 1, 0);
          //scene.add(directionalLight);
  
          var widthH = parseInt(document.getElementById("wdthH").value) || 0; // H for Head
          var widthT = parseInt(document.getElementById("wdthT").value) || 0; // T for tail
          var height = parseInt(document.getElementById("hght").value) || 0;  // flank
  
          //création du pavé
          var EmportePieceH = new THREE.BoxGeometry(300, 60, widthH);
          var EmportePieceT = new THREE.BoxGeometry(300, 60, widthT);
          var EmportePieceB = new THREE.BoxGeometry(height, 60, 520);
  
          var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  
          // création du meshage et material
          var EmportePieceMeshH = new THREE.Mesh(EmportePieceH, paveMaterial);
          var EmportePieceMeshT = new THREE.Mesh(EmportePieceT, paveMaterial);
          var paveMeshB = new THREE.Mesh(EmportePieceB, paveMaterial);
  
          var zH = 247 - widthH / 2;
          var zT = -247 + widthT / 2;
          EmportePieceMeshH.position.set(0, 30, zH);
          EmportePieceMeshT.position.set(0, 30, zT);
          paveMeshB.position.set(-95 + height / 2, 30, 0);
          var EmportePieceBSPH = new ThreeBSP(EmportePieceMeshH);
          var EmportePieceBSPT = new ThreeBSP(EmportePieceMeshT);
          var paveBSPB = new ThreeBSP(paveMeshB);
  
          //scene.add(EmportePieceMeshH);
          //scene.add(EmportePieceMeshT);
          //scene.add(paveMeshB);
  
  
          // texture
          var manager = new THREE.LoadingManager();
          manager.onProgress = function (item, loaded, total) {
              console.log(item, loaded, total);
          };
          var texture = new THREE.Texture();
          var onProgress = function (xhr) {
              if (xhr.lengthComputable) {
                  var percentComplete = xhr.loaded / xhr.total * 100;
                  console.log(Math.round(percentComplete, 2) + '% downloaded');
              }
          };
          var onError = function (xhr) {
          };
  
          var loader = new THREE.ImageLoader(manager);
          loader.load('/Scan/filet_1kg500-reposition-reduit_material_0.jpg', function (image) {
              texture.image = image;
              texture.needsUpdate = true;
          });
  
          var width = parseInt(document.getElementById("wdth").value) || 0;
  
          //création du pavé
          var paveGeom = new THREE.BoxGeometry(250, 250, width);
          var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  
          // création du meshage parallélépipède avec material
          var paveMesh = new THREE.Mesh(paveGeom, paveMaterial);
  
          var z0 = -247 + widthH;
          paveMesh.position.set(0, 0, z0);
  
          var paveBSP = new ThreeBSP(paveMesh);
          //scene.add(paveMesh);
  
          //tableau des volumes
          var tabVolumes = new Array();
  
          // model
          var loader = new THREE.OBJLoader(manager);
          loader.load('/Scan/filet_1kg500-reposition-reduit.obj', function (object) {
              object.traverse(function (child) {
                  if (child instanceof THREE.Mesh) {
                      child.material.map = texture;
  
                      var geo = new THREE.Geometry().fromBufferGeometry(child.geometry);
                      var filetMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
                      var filetMesh = new THREE.Mesh(geo, filetMaterial);
                      //scene.add(filetMesh);
                      var newBSPH, newBSPT, newBSPB, newBSP2, newBSP1, filletBSP
                      var filetBSP = new ThreeBSP(filetMesh);
  
                      newBSPH = filetBSP.intersect(EmportePieceBSPH);
                      newBSPT = filetBSP.intersect(EmportePieceBSPT);
                      newBSPB = filetBSP.intersect(paveBSPB);
                      newBSP2 = filetBSP.subtract(EmportePieceBSPH);
                      newBSP1 = newBSP2.subtract(paveBSPB);
                      filletBSP = newBSP1.subtract(EmportePieceBSPT);
  
                      ////////////////////subtract//////////////////////////////
  
                      var newFilet = new THREE.Geometry();
                      newFilet = filletBSP.toGeometry();
                      var newFilletMesh = new THREE.Mesh(newFilet, new THREE.MeshBasicMaterial({ map: texture }));
                      newFilletMesh.position.set(0, 0, 0);
  
                      ///////////////////////////////////création morceaux découpés///////////////////////////////////////////
  
                      var HeadFillet = new THREE.Geometry();
                      var TailFillet = new THREE.Geometry();
                      var degraissageFillet = new THREE.Geometry();
                      HeadFillet = newBSPH.toGeometry();
                      TailFillet = newBSPT.toGeometry();
                      degraissageFillet = newBSPB.toGeometry();
  
  
                      /////////////////////////////////calcul des volumes des 1ers morceaux/////////////////////////////////////////
  
                      if (widthH != 0) {
                          tabVolumes[0] = calculateVolume2(HeadFillet);
                      } else { tabVolumes[0] = 0;}
  
                      if (widthT != 0) {
                          //alert(tabVolumes[0]);
                          tabVolumes[1] = calculateVolume2(TailFillet);
                      } else { tabVolumes[1] = 0; }
  
                      if (height != 0) {
                          tabVolumes[2] = calculateVolume2(degraissageFillet);
                      } else { tabVolumes[2] = 0; }
  
                      var ind = 3;
  
                      var HeadFilletMesh = new THREE.Mesh(HeadFillet, new THREE.MeshBasicMaterial({ map: texture }));
                      var TailFilletMesh = new THREE.Mesh(TailFillet, new THREE.MeshBasicMaterial({ map: texture }));
                      var degraissageFilletMesh = new THREE.Mesh(degraissageFillet, new THREE.MeshBasicMaterial({ map: texture }));
  
                      HeadFilletMesh.position.set(0, 0, 20);
                      degraissageFilletMesh.position.set(-20, 0, 0);
                      TailFilletMesh.position.set(0, 0, -20);
                      scene.add(HeadFilletMesh);
                      scene.add(TailFilletMesh);
                      scene.add(degraissageFilletMesh);
  
                      //scene.add(newFilletMesh);
                      var cloneHeadFilletMesh = HeadFilletMesh.clone();
                      var cloneTailFilletMesh = TailFilletMesh.clone();
                      var clonedegraissageFilletMesh = degraissageFilletMesh.clone();
  
                      var mesh_decoupe = new THREE.Object3D;
                      mesh_decoupe.add(cloneHeadFilletMesh);
                      mesh_decoupe.add(cloneTailFilletMesh);
                      mesh_decoupe.add(clonedegraissageFilletMesh);
  
                      if (width != 0) {
                          var paveGeom = new THREE.BoxGeometry(300, 300, width);
                          var paveMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  
  
                          var fillet2BSP = new ThreeBSP(newFilletMesh);
  
                          var intersectionPave = new THREE.Geometry();
                          intersectionPave = fillet2BSP.intersect(paveBSP);
  
                          var geometryPave = new THREE.Geometry();
                          geometryPave = intersectionPave.toGeometry();
                          var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
  
  
                          //alert(geometryPave.faces.length);
  
                          while (geometryPave.faces.length != 0) {
  
  
                              var z = paveMesh.position.z + width + 5;
  
                              paveMesh.position.set(0, 0, z);
                              paveBSP = new ThreeBSP(paveMesh);
                              //scene.add(paveMesh);
  
                              fillet2BSP = new ThreeBSP(newFilletMesh);
  
                              intersectionPave = filletBSP.intersect(paveBSP);
                              geometryPave = intersectionPave.toGeometry();
  
                              tabVolumes[ind] = calculateVolume2(geometryPave);
                              ind = ind + 1;
  
                              var newMesh = new THREE.Mesh(geometryPave, new THREE.MeshBasicMaterial({ map: texture }));
                              newMesh.position.set(0, 0, newMesh.position.z);
                              scene.add(newMesh);
  
                              var meshSave = newMesh.clone();
                              mesh_decoupe.add(meshSave);
                          }
  
                          document.body.style.cursor = '';
  
                      } else {
                          scene.add(newFilletMesh);
                          document.body.style.cursor = '';
  
  
                          tabVolumes[3] = 0;
                          tabVolumes[4] = calculateVolume2(newFilet);
                      }
  
  
  
                      //    }
                      //}
                      //else {
                      //    scene.add(newFilletMesh);
  
                      //    tabVolumes[ind] = calculateVolume2(newFilet);
                      //}
  
  
                      //alert(calculateVolume2(newBSP.toGeometry()));
  
                      //afficher les volumes dans la textarea
  
  
                      var txtVolume = document.getElementById("txtVolume");
                      txtVolume.value = tabVolumes.join("\n");
  
                      //var exporter = new THREE.OBJExporter();
                      //var result = exporter.parse(mesh_decoupe);
                      //var blob = new Blob([result], { type: 'text/plain' });
                      //saveAs(blob, 'dechets.obj');
  
                  }
              });
              //scene.add(object);
  
          }, onProgress, onError);
  
          renderer = new THREE.WebGLRenderer();
          renderer.setSize(800, 500, false);
  
          document.getElementById('canvas3D').innerHTML = "";
          document.getElementById('canvas3D').appendChild(renderer.domElement);
      }
          function animate() {
  
              requestAnimationFrame(animate);
              camin();
              renderer.render(scene, camera);
  
  
          }
  
          function camin() {
              camera.position.y -= .1;
          }
  
  
              function volumeOfT(p1, p2, p3) {
              var v321 = p3.x * p2.y * p1.z;
              var v231 = p2.x * p3.y * p1.z;
              var v312 = p3.x * p1.y * p2.z;
              var v132 = p1.x * p3.y * p2.z;
              var v213 = p2.x * p1.y * p3.z;
              var v123 = p1.x * p2.y * p3.z;
              return (-v321 + v231 + v312 - v132 - v213 + v123) / 6.0;
          }
  
          function calculateVolume2(object) {
              var volumes = 0.0;
  
              for (var i = 0; i &lt; object.faces.length; i++) {
                  var Pi = object.faces[i].a;
                  var Qi = object.faces[i].b;
                  var Ri = object.faces[i].c;
                  //alert (Pi);
  
                  var P = new THREE.Vector3(object.vertices[Pi].x, object.vertices[Pi].y, object.vertices[Pi].z);
                  //alert(object.vertices[Pi].x);
                  var Q = new THREE.Vector3(object.vertices[Qi].x, object.vertices[Qi].y, object.vertices[Qi].z);
                  var R = new THREE.Vector3(object.vertices[Ri].x, object.vertices[Ri].y, object.vertices[Ri].z);
                  volumes += volumeOfT(P, Q, R);
              }
  
              return Math.abs(volumes);
  
        }
  }
  </code></pre>