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;
}