/// <summary> /// Generate vertices and normals for cube /// </summary> /// <param name="vertex"></param> /// <param name="corners"></param> private void GenerateVertex(Vertex vertex, Voxel[] corners) { var data = new HermiteData { intersectionPoints = new List <Vector3>(), gradientVectors = new List <Vector3>() }; // Find the point of intersection of the surface in each of the 12 edges for (int i = 0; i < 12; i++) { int n1 = Tables.EdgeConnection[i, 0]; int n2 = Tables.EdgeConnection[i, 1]; if ((vertex.edgeFlags & (1 << i)) == 0) { continue; } if (Mathf.Abs(corners[n1].density) < ToleranceDensity) { data.intersectionPoints.Add(corners[n1].pos); } else if (Mathf.Abs(corners[n2].density) < ToleranceDensity) { data.intersectionPoints.Add(corners[n2].pos); } else { Vector3 vDiff = corners[n1].pos - corners[n2].pos; if (Mathf.Abs(vDiff.x) > ToleranceDensity) { Vector3 pos = IntersectXAxis(corners[n1], corners[n2]); data.intersectionPoints.Add(pos); } if (Mathf.Abs(vDiff.y) > ToleranceDensity) { Vector3 pos = IntersectYAxis(corners[n1], corners[n2]); data.intersectionPoints.Add(pos); } if (Mathf.Abs(vDiff.z) > ToleranceDensity) { Vector3 pos = IntersectZAxis(corners[n1], corners[n2]); data.intersectionPoints.Add(pos); } } Vector3 normal = GetNormal(data.intersectionPoints[data.intersectionPoints.Count - 1]); data.gradientVectors.Add(normal); } vertex.pos = SchmitzVertexFromHermiteData(data, 0.001f); vertex.normal = GetNormal(vertex.pos); vertex.pos -= offset; }
/// <summary> /// Calculates an approximated vertex for a row. /// Based on the algorithm described in the paper "Analysis and Acceleration of High Quality Isosurface Contouring". /// </summary> /// <param name="data">The hermite data for a row</param> /// <param name="threshold">When has a force has a value below it will return the approximated position</param> /// <returns>Approximated vertex for the row</returns> private static Vector3 SchmitzVertexFromHermiteData(HermiteData data, float threshold) { threshold *= threshold; List <Vector3> xPoints = data.intersectionPoints; List <Vector3> grads = data.gradientVectors; int pointsCount = xPoints.Count; if (pointsCount == 0) { return(new Vector3()); } // start mass point // calculated by mean of intersection points Vector3 c = new Vector3(); for (int i = 0; i < pointsCount; i++) { c += xPoints[i]; } c /= pointsCount; for (int i = 0; i < MaxParticleIterations; i++) { // force that acts on mass Vector3 force = new Vector3(); for (int j = 0; j < pointsCount; j++) { Vector3 xPoint = xPoints[j]; Vector3 xNormal = grads[j]; force += xNormal * -1 * Vector3.Dot(xNormal, c - xPoint); } // dampen force float damping = 1 - (float)i / MaxParticleIterations; c += force * damping / pointsCount; if (force.sqrMagnitude < threshold) { break; } } return(c); }