in src/engine/actvolume/actvol.js [1116:1320]
updateGeoNormalsUniformityColors(geo, normalSpeed) {
const numVertices = geo.getNumVertices();
// float array
const vertices = geo.getVertices();
// THREE.Vector3 array
const normals = geo.getNormals();
const numTriangles = geo.getNumTriangles();
const indices = geo.getIndices();
// perform laplasian smoother
// ...
if (this.m_lapSmoother === null) {
this.m_lapSmoother = new LaplasianSmoother();
}
this.m_lapSmoother.performSmoothStep(numVertices, vertices, numTriangles, indices, this.m_verticesNew);
const DEEP_DEBUG = false;
// use smoothed vertices to update geo
const NUM_COMPS_VERTEX = 4;
const OFF_0 = 0;
const OFF_1 = 1;
const OFF_2 = 2;
let i, i4;
// when sphere touch edges, this definately means iterations end
let sphereTouchEdge = false;
// if too much matched, than stop iterations
// let numMatchedToColor = 0;
for (i = 0, i4 = 0; i < numVertices; i++, i4 += NUM_COMPS_VERTEX) {
let vx = vertices[i4 + OFF_0];
let vy = vertices[i4 + OFF_1];
let vz = vertices[i4 + OFF_2];
const vn = normals[i];
// pixel coordinate in the volume
let x = Math.floor(vx);
let y = Math.floor(vy);
let z = Math.floor(vz);
if (DEEP_DEBUG && i === 0) {
console.log(`v = ${vx}, ${vy}, ${vz}. int xyz = ${x},${y},${z}`);
console.log(`vn = ${vn.x}, ${vn.y}, ${vn.z}`);
}
if (x >= this.m_xDim) {
sphereTouchEdge = true;
x = this.m_xDim - 1;
}
if (y >= this.m_yDim) {
sphereTouchEdge = true;
y = this.m_yDim - 1;
}
if (z >= this.m_zDim) {
sphereTouchEdge = true;
z = this.m_zDim - 1;
}
if (x < 0) {
sphereTouchEdge = true;
x = 0;
}
if (y < 0) {
sphereTouchEdge = true;
y = 0;
}
if (z < 0) {
sphereTouchEdge = true;
z = 0;
}
const xyDim = this.m_xDim * this.m_yDim;
const off = x + y * this.m_xDim + z * xyDim;
const uni = this.m_imageUniformity[off];
const valGaussCur = this.m_imageGauss[off];
if (DEEP_DEBUG && i === 0) {
console.log(`uni = ${uni}, valGaussCur = ${valGaussCur}`);
}
let compSum = uni;
// predict next position
const NEXT_STEP = 2.5;
let nx = Math.floor(vx + vn.x * NEXT_STEP);
let ny = Math.floor(vy + vn.y * NEXT_STEP);
let nz = Math.floor(vz + vn.z * NEXT_STEP);
if (DEEP_DEBUG && i === 0) {
console.log(`nx = ${nx}, ny = ${ny}, nz = ${nz}`);
}
if (nx < 0 || ny < 0 || nz < 0 || nx >= this.m_xDim || ny >= this.m_yDim || nz >= this.m_zDim) {
sphereTouchEdge = true;
}
nx = nx >= 0 ? nx : 0;
ny = ny >= 0 ? ny : 0;
nz = nz >= 0 ? nz : 0;
nx = nx < this.m_xDim ? nx : this.m_xDim - 1;
ny = ny < this.m_yDim ? ny : this.m_yDim - 1;
nz = nz < this.m_zDim ? nz : this.m_zDim - 1;
const nextOff = nx + ny * this.m_xDim + nz * xyDim;
const valGaussNext = this.m_imageGauss[nextOff];
const KOEF_GAUSS_DEC_MULT = 0.3;
if (valGaussNext > valGaussCur) {
compSum *= KOEF_GAUSS_DEC_MULT;
}
if (DEEP_DEBUG && i === 0) {
console.log(`valGaussNext = ${valGaussNext}`);
}
// use colors
const koef = this.m_colorProbability[Math.floor(valGaussCur)];
compSum *= koef;
const COLOR_MATCH = 0.9;
const isColorMatch = koef <= COLOR_MATCH;
// numMatchedToColor += (isColorMatch) ? 1 : 0;
if (DEEP_DEBUG && i === 0) {
console.log(`koef = ${koef}, isColorMatch = ${isColorMatch}`);
}
const vAddSmooth = new THREE.Vector3();
vAddSmooth.x = this.m_verticesNew[i4 + OFF_0] - vx;
vAddSmooth.y = this.m_verticesNew[i4 + OFF_1] - vy;
vAddSmooth.z = this.m_verticesNew[i4 + OFF_2] - vz;
vAddSmooth.normalize();
vAddSmooth.multiplyScalar(normalSpeed);
const vAddGeo = new THREE.Vector3();
vAddGeo.x = vn.x * compSum * normalSpeed;
vAddGeo.y = vn.y * compSum * normalSpeed;
vAddGeo.z = vn.z * compSum * normalSpeed;
if (DEEP_DEBUG && i === 0) {
console.log(`vAddSmooth = ${vAddSmooth.x}, ${vAddSmooth.y}, ${vAddSmooth.z}`);
console.log(`vAddGeo = ${vAddGeo.x}, ${vAddGeo.y}, ${vAddGeo.z}`);
}
const KOEF_ADD_SMOOTH = 0.3;
const KOEF_ADD_GEO = 1.0 - KOEF_ADD_SMOOTH;
if (isColorMatch) {
// do nothing
} else {
const vNew = new THREE.Vector3();
vNew.x = vx + vAddGeo.x * KOEF_ADD_GEO + vAddSmooth.x * KOEF_ADD_SMOOTH;
vNew.y = vy + vAddGeo.y * KOEF_ADD_GEO + vAddSmooth.y * KOEF_ADD_SMOOTH;
vNew.z = vz + vAddGeo.z * KOEF_ADD_GEO + vAddSmooth.z * KOEF_ADD_SMOOTH;
vx = vNew.x;
vy = vNew.y;
vz = vNew.z;
}
this.m_verticesNew[i4 + OFF_0] = vx;
this.m_verticesNew[i4 + OFF_1] = vy;
this.m_verticesNew[i4 + OFF_2] = vz;
} // for i
// debug
// if (numMatchedToColor > 0) {
// console.log(`numMatchedToColor = ${numMatchedToColor}. geoStage = ${this.m_geoStage}`);
// }
// copy back
let errAve = 0.0;
for (i = 0, i4 = 0; i < numVertices; i++, i4 += NUM_COMPS_VERTEX) {
// estimate error of modification
const dx = this.m_verticesNew[i4 + OFF_0] - vertices[i4 + OFF_0];
const dy = this.m_verticesNew[i4 + OFF_1] - vertices[i4 + OFF_1];
const dz = this.m_verticesNew[i4 + OFF_2] - vertices[i4 + OFF_2];
const err = dx * dx + dy * dy + dz * dz;
errAve += err;
vertices[i4 + OFF_0] = this.m_verticesNew[i4 + OFF_0];
vertices[i4 + OFF_1] = this.m_verticesNew[i4 + OFF_1];
vertices[i4 + OFF_2] = this.m_verticesNew[i4 + OFF_2];
}
errAve /= numVertices;
errAve = Math.sqrt(errAve);
const DIF_VERTICES_LIMIT = 0.12;
if (errAve < DIF_VERTICES_LIMIT) {
this.finalizeUpdatesGeo(geo, DEEP_DEBUG);
return true;
}
const aveUni = this.getAveUniformityForGeoVertices(geo);
const MIN_POSSIBLE_UNIFORMITY = 0.6;
if (aveUni < MIN_POSSIBLE_UNIFORMITY) {
this.finalizeUpdatesGeo(geo, DEEP_DEBUG);
return true;
}
if (sphereTouchEdge) {
this.finalizeUpdatesGeo(geo, DEEP_DEBUG);
return true;
}
const DEEP_ERR_DEBUG = false;
if (DEEP_ERR_DEBUG) {
const VERTICES_UNIFORMITY = 1024;
console.log(`Iters errAve = ${errAve} < ${DIF_VERTICES_LIMIT}. aveUni = ${aveUni} < ${VERTICES_UNIFORMITY}`);
}
return false;
} // updateGeoNormalsUniformityColors