_doGridPosNorms()

in packages/miew/src/gfx/geometries/IsoSurface.js [222:364]


  _doGridPosNorms(isoValue, step, appendSimple) {
    const vol = this._volumetricData;
    const volData = this._volumetricData.getData();
    const dim = vol.getDimensions();
    const xSize = dim[0];
    const ySize = dim[1];
    const zSize = dim[2];
    const stepX = step * vol.getStrideX();
    const stepY = step * vol.getStrideY();
    const stepZ = step * vol.getStrideZ();

    const gc = new GridCell();
    const gcVal = gc.val;
    const gcValSize = gc.val.length;
    const additions = [
      new THREE.Vector3(0, 0, 0), // 0
      new THREE.Vector3(step, 0, 0), // 1
      new THREE.Vector3(step, step, 0), // 2
      new THREE.Vector3(0, step, 0), // 3
      new THREE.Vector3(0, 0, step), // 4
      new THREE.Vector3(step, 0, step), // 5
      new THREE.Vector3(step, step, step), // 6
      new THREE.Vector3(0, step, step), // 7
    ];

    const tmpTriCount = 5;
    const triangles = new Array(tmpTriCount);
    for (let j = 0; j < tmpTriCount; ++j) {
      triangles[j] = new Triangle();
    }

    let appendVertex;
    const self = this;
    const positions = this._position;
    const normals = this._normals;
    if (appendSimple) {
      // Special case for axis-aligned grid with positive unit vector normals
      appendVertex = (function () {
        const axis = new THREE.Vector3(self._xAxis.x, self._yAxis.y, self._zAxis.z);
        return function (triVertex) {
          const vertex = triVertex.p.clone();
          vertex.multiply(axis);
          positions.push(vertex.add(self._origin));
          normals.push(triVertex.n.clone());
        };
      }());
    } else {
      appendVertex = (function () {
        const posMtx = new THREE.Matrix3();
        posMtx.set(
          self._xAxis.x,
          self._yAxis.x,
          self._zAxis.x,
          self._xAxis.y,
          self._yAxis.y,
          self._zAxis.y,
          self._xAxis.z,
          self._yAxis.z,
          self._zAxis.z,
        );
        const normMtx = new THREE.Matrix3();
        normMtx.set(
          self._xDir.x,
          self._yDir.x,
          self._zDir.x,
          self._xDir.y,
          self._yDir.y,
          self._zDir.y,
          self._xDir.z,
          self._yDir.z,
          self._zDir.z,
        );

        return function (triVertex) {
          positions.push(triVertex.p.clone().applyMatrix3(posMtx).add(self._origin));
          normals.push(triVertex.n.clone().applyMatrix3(normMtx));
        };
      }());
    }
    const indices = this._indices;

    let globTriCount = 0;

    for (let z = 0; z < (zSize - step); z += step) {
      for (let y = 0; y < (ySize - step); y += step) {
        let idx = vol.getDirectIdx(0, y, z);
        for (let x = 0; x < (xSize - step); x += step, idx += stepX) {
          /* eslint-disable no-multi-spaces */
          /* eslint-disable computed-property-spacing */
          gcVal[0] = volData[idx];
          gcVal[1] = volData[idx + stepX];
          gcVal[3] = volData[idx + stepY];
          gcVal[2] = volData[idx + stepX + stepY];
          gcVal[4] = volData[idx + stepZ];
          gcVal[5] = volData[idx + stepX + stepZ];
          gcVal[7] = volData[idx + stepY + stepZ];
          gcVal[6] = volData[idx + stepX + stepY + stepZ];
          /* eslint-enable no-multi-spaces */
          /* eslint-enable computed-property-spacing */

          // Determine the index into the edge table which
          // tells us which vertices are inside of the surface
          let cubeIndex = 0;
          let i = 0;
          for (; i < gcValSize; ++i) {
            if (gcVal[i] < isoValue) {
              cubeIndex |= (1 << i);
            }
          }

          if (edgeTable[cubeIndex] === 0) {
            continue;
          }

          gc.cubeIndex = cubeIndex;
          for (i = 0; i < gcValSize; ++i) {
            gc.p[i].set(x + additions[i].x, y + additions[i].y, z + additions[i].z);
            _voxelGradientFast(this._gradient, gc.p[i], gc.g[i]);
          }

          // calculate vertices and facets for this cube,
          // calculate normals by interpolating between the negated
          // normalized volume gradients for the 8 reference voxels
          const triCount = this._polygonize(gc, isoValue, triangles);
          globTriCount += triCount;

          // append triangles using different techniques
          for (i = 0; i < triCount; ++i) {
            indices.push(this._numTriangles * 3);
            indices.push(this._numTriangles * 3 + 1);
            indices.push(this._numTriangles * 3 + 2);
            ++this._numTriangles;

            appendVertex(triangles[i].a);
            appendVertex(triangles[i].b);
            appendVertex(triangles[i].c);
          }
        }
      }
    }

    return globTriCount;
  }