public void SubdivideDetail(Vector origin, Vector forward, Vector up, double size) { var right = Vector.Cross(up, forward); Func <Vector, bool> isDetail = v => GeoUtil.RectContains(GeoUtil.ProjectOnPlaneTransformed(v, origin, up, right), size); int triCount = TriangleCount; for (int i = 0; i < triCount; i++) { var n = normals[i]; var v0 = vertices[i * 3 + 0]; var v1 = vertices[i * 3 + 1]; var v2 = vertices[i * 3 + 2]; var dot = Vector.Dot(forward, n); bool shouldSubdivide = isDetail(v0) || isDetail(v1) || isDetail(v2); shouldSubdivide &= dot < -0.01; if (!shouldSubdivide) { continue; } var v01 = (v0 + v1) * 0.5; var v12 = (v1 + v2) * 0.5; var v20 = (v2 + v0) * 0.5; vertices[i * 3 + 0] = v01; vertices[i * 3 + 1] = v1; vertices[i * 3 + 2] = v12; vertices.Add(v12); vertices.Add(v2); vertices.Add(v20); vertices.Add(v20); vertices.Add(v0); vertices.Add(v01); vertices.Add(v01); vertices.Add(v12); vertices.Add(v20); var normal = normals[i]; normals.Add(normal); normals.Add(normal); normals.Add(normal); } }
/// <summary> /// /// </summary> /// <param name="id">ID in base 10 to be converted and embedded onto the mesh</param> /// <param name="mesh">Mesh to be modified</param> /// <param name="size">Size of the largest dimension of the shape matrix, in input file's units</param> /// <param name="margin">Space between shape cells. (Closest distance between two crevice vertex minus thickness)</param> /// <param name="thickness">Thickness of crevices</param> /// <param name="displacement">Displacement of crevice vertices in the forward direction</param> /// <param name="origin">Origin of the projection plane</param> /// <param name="forward">Direction of the projection</param> /// <param name="up">Up direction of the projection plane to determine the matrix orientation</param> public void Embed(int id, Mesh mesh, double size, double margin, double thickness, double displacement, Vector origin, Vector forward, Vector up) { var right = Vector.Cross(up, forward); var encodedShapes = GetEncodedShapes(id); var lines = ConstructMatrix(encodedShapes, size, thickness + margin); var vertices = mesh.vertices; var normals = mesh.normals; for (var i = 0; i < vertices.Count; i++) { var v = vertices[i]; var n = normals[i]; if (Vector.Dot(forward, n) >= -0.01) { // Not facing the projection plane, no need to continue further. continue; } // TODO: Additional check to see if the face is facing the projection plane but occluded by other faces in the geometry. // Required for complex geometry. var vProj = GeoUtil.ProjectOnPlaneTransformed(v, origin, up, right); // Check for each line if the projected point lies inside it, with the thickness used as the threshold. foreach (var line in lines) { var dist = GeoUtil.PointLineDistance(vProj, line); if (dist < thickness * 0.5) { // Point inside a line, modify the vertex and early exit the loop, no need to check any other line. bool smoothDisplacement = false; if (smoothDisplacement) { vertices[i] = v + forward * displacement * Smoothstep(1 - dist / (thickness * 0.5)); } else { vertices[i] = v + forward * displacement; } break; } } } }