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); }
// Use this for initialization void Start() { //create a copy of mesh for processing PatchedShape patchedShape = PatchedShape.CreatePatchedShapeFromMesh(GetComponent <MeshFilter>().sharedMesh, Mathf.Max((int)minTrainglesPerpatch, (int)maxTrainglesPerpatch), (int)maxTrainglesPerpatch, randomSeed); OptimizedPatchedShape optimizedShape = OptimizedPatchedShape.CreateOptimizedPatchedShapeFromPatchedShape(patchedShape); finalShape = ExtrudedPatchedShape.CreateExtrudedPatchedShapeFromOptimizedPatchedShape(optimizedShape, extrudeAmount); patchedShapeCopy = new Shape(); patchedShapeCopy.AllocateShape(finalShape.numVertices_, finalShape.numIndices_); finalShape.indices_.CopyTo(patchedShapeCopy.indices_, 0); Mesh mesh = GetComponent <MeshFilter>().mesh; mesh.vertices = finalShape.vertices_; mesh.normals = finalShape.normals_; mesh.uv = finalShape.uvs_; mesh.triangles = finalShape.indices_; //substituting material of the mesh renderer at startup shardsMaterial = new Material(Shader.Find("ArtSpaces/MemoryShardsShader")); MeshRenderer renderer = GetComponent <MeshRenderer>(); Material previewMaterial = null; if (renderer.materials.Length == 1) { previewMaterial = renderer.material; renderer.material = shardsMaterial; } else { Debug.LogError("MemoryShardsEffect only supports meshes with one material!"); } //copy basic attributes if they are present in preview material //shardsMaterial.SetColor("_Color", Color.blue); _vertexToPatch = new ComputeBuffer(finalShape.numVertices_, 4); // 4 = sizeOf(uint) _patchTransforms = new ComputeBuffer(finalShape.nPatches_, (3 + 4) * sizeof(float)); // Vector3, Quaternion _vertexToPatch.SetData(finalShape.vertexToPatchIndex_); shardsMaterial.SetBuffer("_vertexToPatch", _vertexToPatch); _patchTransforms.SetData(finalShape.patchTransforms_); shardsMaterial.SetBuffer("_patchTransforms", _patchTransforms); //setup compute buffers for compute shader _patchStates = new ComputeBuffer(finalShape.nPatches_, (3 + 3) * sizeof(float)); // Vector3, Vector3 _patchInfos = new ComputeBuffer(finalShape.nPatches_, (3 + 3 + 1 + 1) * sizeof(float)); // Vector3, Vector3, float, float shardsMotionCSKernel = shardsMotionCS.FindKernel("cs_updatePatch"); PatchInfo_[] patchInfos = new PatchInfo_[finalShape.nPatches_]; PatchState_[] patchStates = new PatchState_[finalShape.nPatches_]; Random.InitState(GetHashCode()); for (int i = 0; i < finalShape.nPatches_; i++) { patchInfos[i].patchAcceleration = Random.onUnitSphere * 0.01f; patchInfos[i].patchAngularAcceleration = Random.onUnitSphere * 0.05f; patchInfos[i].patchDrag = Random.Range(0.0f, 1.0f); patchInfos[i].patchRandomValue = Random.Range(0.0f, 1.0f); patchStates[i].patchVelocity = Vector3.zero; patchStates[i].patchAngularVelocity = Vector3.zero; } _patchInfos.SetData(patchInfos); _patchStates.SetData(patchStates); }
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); }