_innerBuild()

in packages/miew/src/gfx/geometries/SSIsosurfaceGeometry.js [721:862]


  _innerBuild() {
    let ok;
    const expandFactor = 1.2;

    // performance test
    // this.performanceTest();

    // Create temporary atoms (but colored)
    const packedArrays = {
      posRad: this._posRad,
      colors: this._colors,
      atoms: this._opts.atoms,
    };
    this.complex = this._opts.parent;
    this.atoms = packedArrays.atoms;
    this.meshResolution = this._opts.gridSpacing;
    this.atomRadiusScale = this._opts.radScale;
    this.colorMode = this._opts.colorMode;
    this.probeRadius = this._opts.probeRadius;
    this.useVertexColors = true;
    this.excludeProbe = this._opts.excludeProbe;
    this.visibilitySelector = this._opts.visibilitySelector;

    this.geoOut = null;

    this.hashLines = null;
    this.hashEntries = null;
    this.numHashEtriesAllocated = 0;
    this.numHashEntryIndex = 0;
    this.maxNumVertices = 0;
    this.maxNumTriangles = 0;

    const atomsColored = new Array(this.atoms.length);
    this.convertToAtomsColored(packedArrays, atomsColored);

    // find bbox for spheres scene
    const vBoxMin = this.vBoxMin = new THREE.Vector3();
    const vBoxMax = this.vBoxMax = new THREE.Vector3();
    this.getBoundingBox(atomsColored, vBoxMin, vBoxMax);

    const marCubeResoultion = this.marCubeResoultion = this.meshResolution * (2 + 2);

    // build grid corners for Marching cube algorithm
    const side = marCubeResoultion;
    const side2 = side * side;
    const side3 = side2 * side;
    const corners = utils.allocateTyped(Float32Array, side3);
    const rProbeRadius = this.probeRadius * this.atomRadiusScale;

    this.calculateGridCorners(corners, side, vBoxMin, vBoxMax, atomsColored, rProbeRadius);

    const numCells = marCubeResoultion - 1;
    const cube = new IsoSurfaceMarchCube();
    ok = cube.create(numCells);
    if (ok < 0) {
      return ok;
    }
    // copy corners to cells
    const vCellStep = new THREE.Vector3();
    vCellStep.x = (vBoxMax.x - vBoxMin.x) / numCells;
    vCellStep.y = (vBoxMax.y - vBoxMin.y) / numCells;
    vCellStep.z = (vBoxMax.z - vBoxMin.z) / numCells;

    let numIntersectedCellsEstim = this.getNumIntersectedCells(side, numCells, corners, cube);
    let maxNumVertices = Math.floor(numIntersectedCellsEstim * expandFactor);
    let maxNumTriangles = Math.floor(numIntersectedCellsEstim * expandFactor * 2);

    this.geoOut = new IsoSurfaceGeo(maxNumVertices, maxNumTriangles, this.useVertexColors);

    ok = this.createVertexHash(maxNumVertices, maxNumTriangles);
    if (ok < 0) {
      return ok;
    }

    // build voxel world (used to check triangle-to-atom tie and to calculate normals and colors)
    let probeRadForNormalsColors = rProbeRadius;
    if (this.excludeProbe) {
      probeRadForNormalsColors = 0.01;
    }
    this.voxelWorld = new IsosurfaceBuildNormals(
      atomsColored.length,
      atomsColored,
      vBoxMin,
      vBoxMax,
      probeRadForNormalsColors,
    );
    this.voxelWorld.createVoxels();

    ok = this.buildGeoFromCorners(marCubeResoultion, vBoxMin, vBoxMax, corners, vCellStep, cube);
    if (this.excludeProbe) {
      // using 3d mesh (geoOut) as a surface points
      // move probe sphere and try to minimuze corners values
      this.modifyExcludedFromGeo(side, rProbeRadius, vBoxMin, vBoxMax, this.geoOut, corners);

      // delete old builded geo
      this.geoOut._vertices = null;
      this.geoOut._colors = null;
      this.geoOut._indices = null;
      this.geoOut._normals = null;
      this.geoOut._numVertices = 0;
      this.geoOut._numTriangles = 0;
      this.geoOut = null;

      // estimage geo vertices budget again
      numIntersectedCellsEstim = this.getNumIntersectedCells(side, numCells, corners, cube);
      maxNumVertices = Math.floor(numIntersectedCellsEstim * expandFactor);
      maxNumTriangles = Math.floor(numIntersectedCellsEstim * expandFactor * 2);

      // creates empty new geometry
      this.geoOut = new IsoSurfaceGeo(maxNumVertices, maxNumTriangles, this.useVertexColors);
      ok = this.createVertexHash(maxNumVertices, maxNumTriangles);
      if (ok < 0) {
        return ok;
      }
      // build vertices and triangles from corners values
      ok = this.buildGeoFromCorners(side, vBoxMin, vBoxMax, corners, vCellStep, cube);
    }

    // build vertex normals
    this.voxelWorld.buildNormals(this.geoOut._vertices.length, this.geoOut._vertices, this.geoOut._normals);
    // More value : more smooth color mixing
    // value about 0.7: very rough colors borders
    let radiusColorSmoothness = 6.5;
    if (this.excludeProbe) {
      radiusColorSmoothness -= 1.5;
    }
    if (this.useVertexColors) {
      this.voxelWorld.buildColors(
        this.geoOut._vertices.length,
        this.geoOut._vertices,
        this.geoOut._colors,
        radiusColorSmoothness,
      );
    }
    this.voxelWorld.destroyVoxels();
    this.voxelWorld = null;

    // remove objects
    cube.destroy();

    return ok;
  }