public void finalizePatches() { computeVertexToPatchIndexes(); patchTransforms_ = new PatchTransform_[nPatches_]; //calculate transforms based on patch centers for (int ipatch = 0; ipatch < nPatches_; ++ipatch) { Patch_ patch = patches_[ipatch]; //copy first vertex patchTransforms_[ipatch].position_ = vertices_[patch.startVertex_]; patchTransforms_[ipatch].rotation_ = Quaternion.identity; for (uint ivert = patch.startVertex_ + 1; ivert < patch.startVertex_ + patch.nVertices_; ++ivert) { patchTransforms_[ipatch].position_ += vertices_[ivert]; patchTransforms_[ipatch].position_ /= 2.0f; } //transform patches for (uint ivert = patch.startVertex_ + 0; ivert < patch.startVertex_ + patch.nVertices_; ++ivert) { vertices_[ivert] -= patchTransforms_[ipatch].position_; } } }
public void computeVertexToPatchIndexes() { vertexToPatchIndex_ = new int[numVertices_]; for (int ipatch = 0; ipatch < nPatches_; ++ipatch) { Patch_ patch = patches_[ipatch]; for (uint ivert = patch.startVertex_; ivert < patch.startVertex_ + patch.nVertices_; ++ivert) { vertexToPatchIndex_[ivert] = ipatch; } } }
static public OptimizedPatchedShape CreateOptimizedPatchedShapeFromPatchedShape(PatchedShape patchedShape) { uint idxRemapCapacity = 1024; uint[] idxRemap = new uint[idxRemapCapacity]; OptimizedPatchedShape optimizedShape = new OptimizedPatchedShape(); //allocate optimized shape optimizedShape.AllocateShape(patchedShape.numVertices_, patchedShape.numIndices_); optimizedShape.numIndices_ = 0; //we will be filling it from beginning optimizedShape.patches_ = new Patch_[patchedShape.nPatches_]; optimizedShape.nPatches_ = patchedShape.nPatches_; uint nDstVertices = 0; for (uint ipatch = 0; ipatch < patchedShape.nPatches_; ++ipatch) { Patch_ patch = patchedShape.patches_[ipatch]; //optimizedShape.patches_[ipatch] = new Patch_(); if (patch.nVertices_ > idxRemapCapacity) { idxRemapCapacity = patch.nVertices_; idxRemap = null; idxRemap = new uint[idxRemapCapacity]; } uint dstIndex = nDstVertices; uint srcIndex = patch.startVertex_; // copy first vertex optimizedShape.vertices_[dstIndex] = patchedShape.vertices_[srcIndex]; optimizedShape.normals_[dstIndex] = patchedShape.normals_[srcIndex]; optimizedShape.uvs_[dstIndex] = patchedShape.uvs_[srcIndex]; uint nv = 1; idxRemap[0] = 0; Dictionary <PatchVertex_, uint> vmap = new Dictionary <PatchVertex_, uint>(new PatchVertexComparer_()); PatchVertex_ v0 = new PatchVertex_(patchedShape.vertices_[srcIndex], patchedShape.normals_[srcIndex], patchedShape.uvs_[srcIndex]); vmap[v0] = 0; for (uint ivert = 1; ivert < patch.nVertices_; ++ivert) { PatchVertex_ v = new PatchVertex_(patchedShape.vertices_[srcIndex + ivert], patchedShape.normals_[srcIndex + ivert], patchedShape.uvs_[srcIndex + ivert]); uint val = 0; if (vmap.TryGetValue(v, out val)) { idxRemap[ivert] = val; } else { // not found // optimizedShape.vertices_[dstIndex + nv] = patchedShape.vertices_[srcIndex + ivert]; optimizedShape.normals_[dstIndex + nv] = patchedShape.normals_[srcIndex + ivert]; optimizedShape.uvs_[dstIndex + nv] = patchedShape.uvs_[srcIndex + ivert]; idxRemap[ivert] = nv; vmap[v] = nv; ++nv; } //mesh.vertexToPatchIndex_[ivert] = ipatch; } for (int i = 0; i < patch.nVertices_; ++i) { optimizedShape.indices_[optimizedShape.numIndices_] = (int)(idxRemap[i] + nDstVertices); optimizedShape.numIndices_++; } optimizedShape.patches_[ipatch].startVertex_ = nDstVertices; optimizedShape.patches_[ipatch].nVertices_ = nv; optimizedShape.patches_[ipatch].startIndex_ = patch.startVertex_; optimizedShape.patches_[ipatch].nIndices_ = patch.nVertices_; nDstVertices += nv; } idxRemap = null; optimizedShape.numVertices_ = (int)nDstVertices; return(optimizedShape); }
void _CreatePatchRecurse(Shape inputShape, ref int targetVerticesCount, ref int nTrianglesInThisPatch, int triangleIdx, bool[] triangleUsed, TriangleAdjacency_[] triAdjacency, ref Patch_ curPatch, int srcTriangleIdx, ref uint dstTriangleIdx) { if (nTrianglesInThisPatch == 0) { return; } triangleUsed[triangleIdx] = true; int tri0 = inputShape.indices_[triangleIdx * 3 + 0]; int tri1 = inputShape.indices_[triangleIdx * 3 + 1]; int tri2 = inputShape.indices_[triangleIdx * 3 + 2]; vertices_[targetVerticesCount + 0] = inputShape.vertices_[tri0]; normals_[targetVerticesCount + 0] = inputShape.normals_[tri0]; uvs_[targetVerticesCount + 0] = inputShape.uvs_[tri0]; vertices_[targetVerticesCount + 1] = inputShape.vertices_[tri1]; normals_[targetVerticesCount + 1] = inputShape.normals_[tri1]; uvs_[targetVerticesCount + 1] = inputShape.uvs_[tri1]; vertices_[targetVerticesCount + 2] = inputShape.vertices_[tri2]; normals_[targetVerticesCount + 2] = inputShape.normals_[tri2]; uvs_[targetVerticesCount + 2] = inputShape.uvs_[tri2]; targetVerticesCount += 3; curPatch.nVertices_ += 3; ++dstTriangleIdx; // pick random edges // int randEdge0_0 = Random.Range(0, 2); int randEdge0_1 = wrap_inc(randEdge0_0, 0, 2); int randEdge1_0 = Random.Range(0, 2); if (randEdge1_0 == randEdge0_0) { randEdge1_0 = wrap_inc(randEdge1_0, 0, 2); } int randEdge1_1 = wrap_inc(randEdge1_0, 0, 2); int randEdge2_0 = 0; while (randEdge2_0 == randEdge0_0 || randEdge2_0 == randEdge1_0) { randEdge2_0++; } int randEdge2_1 = wrap_inc(randEdge2_0, 0, 2); int numRolledEdges = 3; //there's a 10% chance that there will be 2 edges //if (Random.Range(1, 10) == 1) // numRolledEdges = 2; for (int iedge = 0; iedge < numRolledEdges; iedge++) { if (nTrianglesInThisPatch > 0) { int tmpEdge_0 = randEdge0_0; int tmpEdge_1 = randEdge0_1; if (iedge == 1) { tmpEdge_0 = randEdge1_0; tmpEdge_1 = randEdge1_1; } else if (iedge == 2) { tmpEdge_0 = randEdge2_0; tmpEdge_1 = randEdge2_1; } int randEdge_0 = inputShape.indices_[triangleIdx * 3 + tmpEdge_0]; int randEdge_1 = inputShape.indices_[triangleIdx * 3 + tmpEdge_1]; //PICO_ASSERT( randEdge_0 != randEdge_1 ); // triangles adjacent to first vertex // TriangleAdjacency_ ta = triAdjacency[randEdge_0]; bool secondVertexTraversed = false; while (ta != null) { uint iinner = ta.triangleIndex_; if (!triangleUsed[iinner]) { //int idx0 = inputShape.indices_[iinner * 3 + 0]; //int idx1 = inputShape.indices_[iinner * 3 + 1]; //int idx2 = inputShape.indices_[iinner * 3 + 2]; //if (((randEdge_0 == idx0) || (randEdge_0 == idx1) || (randEdge_0 == idx2)) // && ((randEdge_1 == idx0) || (randEdge_1 == idx1) || (randEdge_1 == idx2)) // ) { triangleIdx = (int)iinner; nTrianglesInThisPatch -= 1; if (nTrianglesInThisPatch > 0) { _CreatePatchRecurse(inputShape, ref targetVerticesCount, ref nTrianglesInThisPatch, triangleIdx, triangleUsed, triAdjacency, ref curPatch, srcTriangleIdx, ref dstTriangleIdx); // break; } else { break; } } } if (ta.nextTriangle_ != -1) { ta = triAdjacency[ta.nextTriangle_]; } else { if (secondVertexTraversed) { ta = null; } else { ta = triAdjacency[randEdge_1]; secondVertexTraversed = true; } } } } else { break; } } }
static public ExtrudedPatchedShape CreateExtrudedPatchedShapeFromOptimizedPatchedShape(OptimizedPatchedShape optimizedShape, float extrudeAmount) { //uint idxRemapCapacity = 1024; //uint[] idxRemap = new uint[idxRemapCapacity]; ExtrudedPatchedShape extrudedShape = new ExtrudedPatchedShape(); //allocate optimized shape extrudedShape.AllocateShape(optimizedShape.numVertices_ * 8, optimizedShape.numIndices_ * 12); extrudedShape.numIndices_ = 0; //we will be filling it from beginning extrudedShape.patches_ = new Patch_[optimizedShape.nPatches_]; extrudedShape.nPatches_ = optimizedShape.nPatches_; uint nDstVertices = 0; uint nDstIndices = 0; int numberOfNewVertices = 0; for (uint ipatch = 0; ipatch < optimizedShape.nPatches_; ++ipatch) { Patch_ patch = optimizedShape.patches_[ipatch]; extrudedShape.patches_[ipatch].startVertex_ = nDstVertices; extrudedShape.patches_[ipatch].startIndex_ = nDstIndices; int lastNumberOfNewVertices = numberOfNewVertices; //copy all vertices original vertices for (uint ivert = patch.startVertex_; ivert < patch.startVertex_ + patch.nVertices_; ++ivert) { extrudedShape.vertices_[nDstVertices] = optimizedShape.vertices_[ivert]; extrudedShape.normals_[nDstVertices] = optimizedShape.normals_[ivert]; extrudedShape.uvs_[nDstVertices] = optimizedShape.uvs_[ivert]; nDstVertices++; } //taking care of indices for (uint iidx = patch.startIndex_; iidx < patch.startIndex_ + patch.nIndices_; ++iidx) { extrudedShape.indices_[nDstIndices] = optimizedShape.indices_[iidx] + numberOfNewVertices; nDstIndices++; } //adding extruded vertices for (uint ivert = patch.startVertex_; ivert < patch.startVertex_ + patch.nVertices_; ++ivert) { extrudedShape.vertices_[nDstVertices] = optimizedShape.vertices_[ivert] - extrudeAmount * optimizedShape.normals_[ivert]; extrudedShape.normals_[nDstVertices] = -optimizedShape.normals_[ivert]; extrudedShape.uvs_[nDstVertices] = optimizedShape.uvs_[ivert]; nDstVertices++; numberOfNewVertices++; } //adding indices in reverse order for (int iidx = (int)(patch.startIndex_ + patch.nIndices_) - 1; iidx >= patch.startIndex_; --iidx) { extrudedShape.indices_[nDstIndices] = optimizedShape.indices_[iidx] + numberOfNewVertices; nDstIndices++; } //taking care of edge vertices //first find all edges of a patch within just one triangle Dictionary <Edge_, uint> edges = new Dictionary <Edge_, uint>(new EdgeComparer_()); for (uint tidx = patch.startIndex_; tidx < patch.startIndex_ + patch.nIndices_; tidx += 3) { Edge_ e1 = new Edge_(optimizedShape.indices_[tidx + 0], optimizedShape.indices_[tidx + 1]); Edge_ e2 = new Edge_(optimizedShape.indices_[tidx + 1], optimizedShape.indices_[tidx + 2]); Edge_ e3 = new Edge_(optimizedShape.indices_[tidx + 2], optimizedShape.indices_[tidx + 0]); uint val = 0; if (edges.TryGetValue(e1, out val)) { edges[e1] = val + 1; } else { edges[e1] = 1; } if (edges.TryGetValue(e2, out val)) { edges[e2] = val + 1; } else { edges[e2] = 1; } if (edges.TryGetValue(e3, out val)) { edges[e3] = val + 1; } else { edges[e3] = 1; } } foreach (KeyValuePair <Edge_, uint> entry in edges) { if (entry.Value == 1) { //add this edge to extruded geometry //we need to duplicate 4 vertices because of new normals //these are: int v1 = entry.Key.v1_ + lastNumberOfNewVertices; int v2 = entry.Key.v2_ + lastNumberOfNewVertices; int v3 = entry.Key.v1_ + (int)patch.nVertices_ + lastNumberOfNewVertices; int v4 = entry.Key.v2_ + (int)patch.nVertices_ + lastNumberOfNewVertices; Vector3 p1 = extrudedShape.vertices_[v1]; Vector3 p2 = extrudedShape.vertices_[v2]; Vector3 p3 = extrudedShape.vertices_[v3]; Vector3 p4 = extrudedShape.vertices_[v4]; //v1 extrudedShape.vertices_[nDstVertices] = extrudedShape.vertices_[v1]; extrudedShape.normals_[nDstVertices] = Vector3.Cross(p1 - p3, p1 - p2); extrudedShape.uvs_[nDstVertices] = extrudedShape.uvs_[v1]; int newV1index = (int)nDstVertices; nDstVertices++; numberOfNewVertices++; //v2 extrudedShape.vertices_[nDstVertices] = extrudedShape.vertices_[v2]; extrudedShape.normals_[nDstVertices] = Vector3.Cross(p2 - p1, p2 - p4); extrudedShape.uvs_[nDstVertices] = extrudedShape.uvs_[v2]; int newV2index = (int)nDstVertices; nDstVertices++; numberOfNewVertices++; //v3 extrudedShape.vertices_[nDstVertices] = extrudedShape.vertices_[v3]; extrudedShape.normals_[nDstVertices] = Vector3.Cross(p3 - p4, p3 - p1); extrudedShape.uvs_[nDstVertices] = extrudedShape.uvs_[v3]; int newV3index = (int)nDstVertices; nDstVertices++; numberOfNewVertices++; //v4 extrudedShape.vertices_[nDstVertices] = extrudedShape.vertices_[v4]; extrudedShape.normals_[nDstVertices] = Vector3.Cross(p4 - p2, p4 - p3); extrudedShape.uvs_[nDstVertices] = extrudedShape.uvs_[v3]; int newV4index = (int)nDstVertices; nDstVertices++; numberOfNewVertices++; extrudedShape.indices_[nDstIndices++] = newV1index; extrudedShape.indices_[nDstIndices++] = newV3index; extrudedShape.indices_[nDstIndices++] = newV2index; extrudedShape.indices_[nDstIndices++] = newV2index; extrudedShape.indices_[nDstIndices++] = newV3index; extrudedShape.indices_[nDstIndices++] = newV4index; } } extrudedShape.patches_[ipatch].nVertices_ = nDstVertices - extrudedShape.patches_[ipatch].startVertex_; extrudedShape.patches_[ipatch].nIndices_ = nDstIndices - extrudedShape.patches_[ipatch].startIndex_; } extrudedShape.numVertices_ = (int)nDstVertices; extrudedShape.numIndices_ = (int)nDstIndices; //resize final array Array.Resize <Vector3>(ref extrudedShape.vertices_, extrudedShape.numVertices_); Array.Resize <Vector3>(ref extrudedShape.normals_, extrudedShape.numVertices_); Array.Resize <Vector2>(ref extrudedShape.uvs_, extrudedShape.numVertices_); Array.Resize <int>(ref extrudedShape.indices_, extrudedShape.numIndices_); extrudedShape.finalizePatches(); return(extrudedShape); }