protected bool CreateUnCutCubeCap(Volume volume, bool partialBuild) { List <Vector3> mesh = volume.Points; List <Vector3> profile = volume.Profile.Points; int maxS = volume.Profile.PointCount; int maxT = volume.Path.PointCount; int gridSize = (profile.Count - 1) / 4; // VFExtents change Vector3 min = ExtentsMin; Vector3 max = ExtentsMax; int offset = ((TypeMask & VolumeFaceMask.Top) != 0) ? (maxT - 1) * maxS : BeginS; { VertexData[] corners = new VertexData[4]; VertexData baseVert = new VertexData(); for (int t = 0; t < 4; t++) { corners[t] = new VertexData { Position = mesh[offset + (gridSize * t)], TexCoord = new Vector2(profile[gridSize * t].x + 0.5f, 0.5f - profile[gridSize * t].y) }; } { Vector3 lhs = corners[1].Position - corners[0].Position; Vector3 rhs = corners[2].Position - corners[1].Position; baseVert.Normal = Vector3.Cross(lhs, rhs); baseVert.Normal.Normalize(); } if ((TypeMask & VolumeFaceMask.Top) == 0) { baseVert.Normal *= -1.0f; } else { //Swap the UVs on the U(X) axis for top face Vector2 swap; swap = corners[0].TexCoord; corners[0].TexCoord = corners[3].TexCoord; corners[3].TexCoord = swap; swap = corners[1].TexCoord; corners[1].TexCoord = corners[2].TexCoord; corners[2].TexCoord = swap; } int size = (gridSize + 1) * (gridSize + 1); //resizeVertices(size); Positions.Clear(); Normals.Clear(); Tangents.Clear(); TexCoords.Clear(); Indices.Clear(); Edge.Clear(); for (int gx = 0; gx < gridSize + 1; gx++) { for (int gy = 0; gy < gridSize + 1; gy++) { VertexData newVert = LerpPlanarVertex(corners[0], corners[1], corners[3], (float)gx / (float)gridSize, (float)gy / (float)gridSize); Positions.Add(newVert.Position); Normals.Add(baseVert.Normal); TexCoords.Add(newVert.TexCoord); if (gx == 0 && gy == 0) { min = newVert.Position; max = min; } else { UpdateMinMax(ref min, ref max, newVert.Position); } } } Centre = (min + max) * 0.5f; ExtentsMin = min; ExtentsMax = max; } if (!partialBuild) { int[] idxs = { 0, 1, (gridSize + 1) + 1, (gridSize + 1) + 1, (gridSize + 1), 0 }; for (int gx = 0; gx < gridSize; gx++) { for (int gy = 0; gy < gridSize; gy++) { if ((TypeMask & VolumeFaceMask.Top) != 0) { for (int i = 5; i >= 0; i--) { Indices.Add((gy * (gridSize + 1)) + gx + idxs[i]); } int edgeValue = gridSize * 2 * gy + gx * 2; if (gx > 0) { Edge.Add(edgeValue); } else { Edge.Add(-1); // Mark face to higlight it } if (gy < gridSize - 1) { Edge.Add(edgeValue); } else { Edge.Add(-1); } Edge.Add(edgeValue); if (gx < gridSize - 1) { Edge.Add(edgeValue); } else { Edge.Add(-1); } if (gy > 0) { Edge.Add(edgeValue); } else { Edge.Add(-1); } Edge.Add(edgeValue); } else { for (int i = 0; i < 6; i++) { Indices.Add((gy * (gridSize + 1)) + gx + idxs[i]); } int edgeValue = gridSize * 2 * gy + gx * 2; if (gy > 0) { Edge.Add(edgeValue); } else { Edge.Add(-1); } if (gx < gridSize - 1) { Edge.Add(edgeValue); } else { Edge.Add(-1); } Edge.Add(edgeValue); if (gy < gridSize - 1) { Edge.Add(edgeValue); } else { Edge.Add(-1); } if (gx > 0) { Edge.Add(edgeValue); } else { Edge.Add(-1); } Edge.Add(edgeValue); } } } } return(true); }
protected bool CreateCap(Volume volume, bool partialBuild) { if ((TypeMask & VolumeFaceMask.Hollow) == 0 && (TypeMask & VolumeFaceMask.Open) == 0 && ((volume.Parameters.PathParameters.Begin == 0.0f) && (volume.Parameters.PathParameters.End == 1.0f)) && (volume.Parameters.ProfileParameters.ProfileType == ProfileType.Square && volume.Parameters.PathParameters.PathType == PathType.Line) ) { return(CreateUnCutCubeCap(volume, partialBuild)); } int numVertices = 0, numIndices = 0; List <Vector3> mesh = volume.Points; List <Vector3> profile = volume.Profile.Points; // All types of caps have the same number of vertices and indices numVertices = profile.Count; numIndices = (profile.Count - 2) * 3; //if ((TypeMask & VolumeFaceMask.Hollow) == 0 && (TypeMask & VolumeFaceMask.Open) == 0) //{ // resizeVertices(num_vertices + 1); // //if (!partial_build) // { // resizeIndices(num_indices + 3); // } //} //else //{ // resizeVertices(num_vertices); // //if (!partial_build) // { // resizeIndices(num_indices); // } //} Positions.Clear(); Normals.Clear(); Tangents.Clear(); TexCoords.Clear(); Indices.Clear(); Edge.Clear(); int maxS = volume.Profile.PointCount; int maxT = volume.Path.PointCount; Centre = Vector3.zero; int offset = ((TypeMask & VolumeFaceMask.Top) != 0) ? (maxT - 1) * maxS : BeginS; // Figure out the normal, assume all caps are flat faces. // Cross product to get normals. Vector2 cuv; Vector2 min_uv, max_uv; // VFExtents change Vector3 min = ExtentsMin; Vector3 max = ExtentsMax; // Copy the vertices into the array int srcIndex = offset; // Index in mesh int endIndex = srcIndex + numVertices; // Index in mesh min = mesh[srcIndex]; max = min; int pIndex = 0; // Index in profile if ((TypeMask & VolumeFaceMask.Top) != 0) { min_uv.x = profile[pIndex].x + 0.5f; min_uv.y = profile[pIndex].y + 0.5f; max_uv = min_uv; while (srcIndex < endIndex) { Vector2 tc = new Vector2(profile[pIndex].x + 0.5f, profile[pIndex].y + 0.5f); UpdateMinMax(ref min_uv, ref max_uv, tc); TexCoords.Add(tc); UpdateMinMax(ref min, ref max, mesh[srcIndex]); Positions.Add(mesh[srcIndex]); ++pIndex; ++srcIndex; } } else { min_uv.x = profile[pIndex].x + 0.5f; min_uv.y = 0.5f - profile[pIndex].y; max_uv = min_uv; while (srcIndex < endIndex) { // Mirror for underside. Vector2 tc = new Vector2(profile[pIndex].x + 0.5f, 0.5f - profile[pIndex].y); UpdateMinMax(ref min_uv, ref max_uv, tc); TexCoords.Add(tc); UpdateMinMax(ref min, ref max, mesh[srcIndex]); Positions.Add(mesh[srcIndex]); ++pIndex; ++srcIndex; } } Centre = (min + max) * 0.5f; cuv = (min_uv + max_uv) * 0.5f; VertexData vd = new VertexData { Position = Centre, TexCoord = cuv }; if ((TypeMask & VolumeFaceMask.Hollow) == 0 && (TypeMask & VolumeFaceMask.Open) == 0) { Positions.Add(Centre); TexCoords.Add(cuv); numVertices++; } //if (partial_build) //{ // return TRUE; //} if ((TypeMask & VolumeFaceMask.Hollow) != 0) { CreateHollowCap(numVertices, profile, (TypeMask & VolumeFaceMask.Top) == 0); } else { // Not hollow, generate the triangle fan. CreateSolidCap(numVertices); } Vector3 d0 = Positions[Indices[1]] - Positions[Indices[0]]; Vector3 d1 = Positions[Indices[2]] - Positions[Indices[0]]; Vector3 normal = Vector3.Cross(d0, d1); if (Vector3.Dot(normal, normal) > 0.00001f) { normal.Normalize(); } else { //degenerate, make up a value normal = normal.z >= 0 ? new Vector3(0f, 0f, 1f) : new Vector3(0f, 0f, -1f); } //llassert(llfinite(normal.getF32ptr()[0])); //llassert(llfinite(normal.getF32ptr()[1])); //llassert(llfinite(normal.getF32ptr()[2])); //llassert(!llisnan(normal.getF32ptr()[0])); //llassert(!llisnan(normal.getF32ptr()[1])); //llassert(!llisnan(normal.getF32ptr()[2])); for (int i = 0; i < numVertices; i++) { Normals.Add(normal); } return(true); }