///////////////////////////////////////////////////////////////////////////////////////////////// // Private methods ///////////////////////////////////////////////////////////////////////////////////////////////// unsafe void ConsolidateMesh(GameObject gameObject, Mesh meshOut, int[] permutation, int[] collapseMap, int nVertices) { int subMeshCount = _aSubMeshesOriginal.Length; if (null == _av3Vertices) { _av3Vertices = (Vector3[])_av3VerticesOriginal.Clone(); } else { _av3VerticesOriginal.CopyTo(_av3Vertices, 0); } if (null == _av3NormalsIn) { _av3NormalsIn = (Vector3[])_av3NormalsOriginal.Clone(); } else { _av3NormalsOriginal.CopyTo(_av3NormalsIn, 0); } if (null == _av4TangentsIn) { _av4TangentsIn = (Vector4[])_av4TangentsOriginal.Clone(); } else { _av4TangentsOriginal.CopyTo(_av4TangentsIn, 0); } if (null == _av2Mapping1In) { _av2Mapping1In = (Vector2[])_av2Mapping1Original.Clone(); } else { _av2Mapping1Original.CopyTo(_av2Mapping1In, 0); } if (null == _av2Mapping2In) { _av2Mapping2In = (Vector2[])_av2Mapping2Original.Clone(); } else { _av2Mapping2Original.CopyTo(_av2Mapping2In, 0); } if (null == _aColors32In) { _aColors32In = (Color32[])_aColors32Original.Clone(); } else { _aColors32Original.CopyTo(_aColors32In, 0); } if (null == _aBoneWeights) { _aBoneWeights = (BoneWeight[])_aBoneWeightsOriginal.Clone(); } else { _aBoneWeightsOriginal.CopyTo(_aBoneWeights, 0); } if (null == _aSubMeshes) { _aSubMeshes = new int[subMeshCount][]; } if (null == _aTriangleCount) { _aTriangleCount = new int[subMeshCount]; } bool bUV1 = _av2Mapping1In != null && _av2Mapping1In.Length > 0; bool bUV2 = _av2Mapping2In != null && _av2Mapping2In.Length > 0; bool bNormal = _av3NormalsIn != null && _av3NormalsIn.Length > 0; bool bTangent = _av4TangentsIn != null && _av4TangentsIn.Length > 0; bool bColor32 = (_aColors32In != null && _aColors32In.Length > 0); bool bBone = _aBoneWeights != null && _aBoneWeights.Length > 0; _vertexMap = _vertexMap ?? new int[_av3Vertices.Length]; for (int i = 0, imax = _vertexMap.Length; i < imax; i++) { _vertexMap[i] = -1; } int n = 0; for (int nSubMesh = 0; nSubMesh < subMeshCount; nSubMesh++) { if (null == _aSubMeshes[nSubMesh]) { _aSubMeshes[nSubMesh] = (int[])_aSubMeshesOriginal[nSubMesh].Clone(); } else { _aSubMeshesOriginal[nSubMesh].CopyTo(_aSubMeshes[nSubMesh], 0); } int[] triangles = _aSubMeshes[nSubMesh]; for (int i = 0; i < triangles.Length; i += 3) { int idx0 = triangles[i]; int idx1 = triangles[i + 1]; int idx2 = triangles[i + 2]; while (permutation[idx0] >= nVertices) { int idx = collapseMap[idx0]; if (idx == -1 || idx1 == idx || idx2 == idx) { idx0 = -1; break; } idx0 = idx; } while (permutation[idx1] >= nVertices) { int idx = collapseMap[idx1]; if (idx == -1 || idx0 == idx || idx2 == idx) { idx1 = -1; break; } idx1 = idx; } while (permutation[idx2] >= nVertices) { int idx = collapseMap[idx2]; if (idx == -1 || idx1 == idx || idx0 == idx) { idx2 = -1; break; } idx2 = idx; } if (idx0 == -1 || idx1 == -1 || idx2 == -1) { triangles[i] = -1; triangles[i + 1] = -1; triangles[i + 2] = -1; continue; } if (_vertexMap[idx0] == -1) { _vertexMap[idx0] = n++; } triangles[i] = _vertexMap[idx0]; if (_vertexMap[idx1] == -1) { _vertexMap[idx1] = n++; } triangles[i + 1] = _vertexMap[idx1]; if (_vertexMap[idx2] == -1) { _vertexMap[idx2] = n++; } triangles[i + 2] = _vertexMap[idx2]; } int l = triangles.Length; int h = 0; int t = l - 1; while (h < t) { if (triangles[t] == -1) { t -= 3; continue; } if (triangles[h] != -1) { h += 3; continue; } triangles[h] = triangles[t - 2]; triangles[h + 1] = triangles[t - 1]; triangles[h + 2] = triangles[t]; triangles[t - 2] = -1; triangles[t - 1] = -1; triangles[t] = -1; h += 3; t -= 3; } if (t < l - 1) { _aTriangleCount[nSubMesh] = t + 1; //#if DEBUG // if (t >= 0 && triangles[t] == -1) // { // throw new Exception("triangles[t] == -1"); // } //#endif } else { _aTriangleCount[nSubMesh] = l; } } #if false//UNITY_2018_1_OR_NEWER NativeArray <MappingLinkedNode> headArray = new NativeArray <MappingLinkedNode>(_vertexMap.Length, Allocator.TempJob); NativeArray <MappingLinkedNode> nodeArray = new NativeArray <MappingLinkedNode>(_vertexMap.Length, Allocator.TempJob); MappingLinkedNode *pNodeArray = (MappingLinkedNode *)nodeArray.GetUnsafeReadOnlyPtr(); MappingLinkedNode *pHeadArray = (MappingLinkedNode *)headArray.GetUnsafeReadOnlyPtr(); int headCount = 0; for (int i = _vertexMap.Length - 1; i >= 0; i--) { if (_vertexMap[i] == -1) { continue; } int idx = i; MappingLinkedNode *head = pNodeArray + i; head->Next = null; head->Mapping = i; MappingLinkedNode *node = head; while (_vertexMap[idx] != -1) { int vidx = _vertexMap[idx]; MappingLinkedNode *next = pNodeArray + vidx; next->Next = null; next->Mapping = vidx; node->Next = next; _vertexMap[idx] = -1; idx = vidx; node = next; } //if (headHash[idx].Next != null) //{ // MappingLinkedNode h = headHash[idx]; // node->Next = h.Next; // headHash[idx] = default(MappingLinkedNode); //} if (head->Next != null) { UnsafeUtility.WriteArrayElement(pHeadArray, headCount++, new MappingLinkedNode() { Mapping = -1, Next = head }); //headArray[headCount++] = new MappingLinkedNode() //{ // Mapping = -1, // Next = head, //}; } } //for (int i = 0; i < _vertexMap.Length; i++) //{ // if (headHash[i].Next != null) // { // headArray[headCount++] = headHash[i]; // headHash[i] = default(MappingLinkedNode); // } //} int hi = 0; NativeArray <JobHandle> handles = new NativeArray <JobHandle>(7, Allocator.TempJob); int arrLen = _av3Vertices.Length; CopyMeshJob <Vector3> jobVert = CopyMeshJob <Vector3> .Create(pHeadArray, arrLen); jobVert.CopyFromArray(_av3Vertices); handles[hi++] = jobVert.Schedule(headCount, 1); CopyMeshJob <Vector2> jobUV = default(CopyMeshJob <Vector2>); if (bUV1) { jobUV = CopyMeshJob <Vector2> .Create(pHeadArray, arrLen); jobUV.CopyFromArray(_av2Mapping1In); handles[hi++] = jobUV.Schedule(headCount, 1); } CopyMeshJob <Vector2> jobUV2 = default(CopyMeshJob <Vector2>); if (bUV2) { jobUV2 = CopyMeshJob <Vector2> .Create(pHeadArray, arrLen); jobUV2.CopyFromArray(_av2Mapping2In); handles[hi++] = jobUV2.Schedule(headCount, 1); } CopyMeshJob <Vector3> jobNorm = default(CopyMeshJob <Vector3>); if (bNormal) { jobNorm = CopyMeshJob <Vector3> .Create(pHeadArray, arrLen); jobNorm.CopyFromArray(_av3NormalsIn); handles[hi++] = jobNorm.Schedule(headCount, 1); } CopyMeshJob <Vector4> jobTang = default(CopyMeshJob <Vector4>); if (bTangent) { jobTang = CopyMeshJob <Vector4> .Create(pHeadArray, arrLen); jobTang.CopyFromArray(_av4TangentsIn); handles[hi++] = jobTang.Schedule(headCount, 1); } CopyMeshJob <Color32> jobCol = default(CopyMeshJob <Color32>); if (bColor32) { jobCol = CopyMeshJob <Color32> .Create(pHeadArray, arrLen); jobCol.CopyFromArray(_aColors32In); handles[hi++] = jobCol.Schedule(headCount, 1); } CopyMeshJob <BoneWeight> jobBone = default(CopyMeshJob <BoneWeight>); if (bBone) { jobBone = CopyMeshJob <BoneWeight> .Create(pHeadArray, arrLen); jobBone.CopyFromArray(_aBoneWeights); handles[hi++] = jobBone.Schedule(headCount, 1); } JobHandle.CompleteAll(handles); jobVert.CopyToArrayAndDispose(_av3Vertices, n); if (bUV1) { jobUV.CopyToArrayAndDispose(_av2Mapping1In, n); } if (bUV2) { jobUV2.CopyToArrayAndDispose(_av2Mapping2In, n); } if (bNormal) { jobNorm.CopyToArrayAndDispose(_av3NormalsIn, n); } if (bTangent) { jobTang.CopyToArrayAndDispose(_av4TangentsIn, n); } if (bColor32) { jobCol.CopyToArrayAndDispose(_aColors32In, n); } if (bBone) { jobBone.CopyToArrayAndDispose(_aBoneWeights, n); } //for (int i = 0; i < headCount; i++) //{ // MappingLinkedNode head = UnsafeUtility.ReadArrayElement<MappingLinkedNode>(pHeadArray, i); // MappingLinkedNode* node = head.Next; // while (node != null) // { // MappingLinkedNode* oldNode = node; // node = node->Next; // UnsafeUtility.Free(oldNode, Allocator.TempJob); // } //} handles.Dispose(); nodeArray.Dispose(); headArray.Dispose(); //for (int i = 0; i < headCount; i++) //{ // MappingLinkedNode head = headArray[i]; // MappingLinkedNode *node = &head; // int idx = node->Mapping; // Vector3 tmp = _av3Vertices[idx]; // if (bUV1) tmpUV = _av2Mapping1In[idx]; // if (bUV2) tmpUV2 = _av2Mapping2In[idx]; // if (bNormal) tmpNormal = _av3NormalsIn[idx]; // if (bTangent) tmpTangent = _av4TangentsIn[idx]; // if (bColor32) tmpColor = _aColors32In[idx]; // if (bBone) tmpBoneWeight = _aBoneWeights[idx]; // node = node->Next; // while (node != null) // { // int vidx = node->Mapping; // Vector3 tmp_ = _av3Vertices[vidx]; // if (bUV1) tmpUV_ = _av2Mapping1In[vidx]; // if (bUV2) tmpUV2_ = _av2Mapping2In[vidx]; // if (bNormal) tmpNormal_ = _av3NormalsIn[vidx]; // if (bTangent) tmpTangent_ = _av4TangentsIn[vidx]; // if (bColor32) tmpColor_ = _aColors32In[vidx]; // if (bBone) tmpBoneWeight_ = _aBoneWeights[vidx]; // _av3Vertices[vidx] = tmp; // if (bUV1) _av2Mapping1In[vidx] = tmpUV; // if (bUV2) _av2Mapping2In[vidx] = tmpUV2; // if (bNormal) _av3NormalsIn[vidx] = tmpNormal; // if (bTangent) _av4TangentsIn[vidx] = tmpTangent; // if (bColor32) _aColors32In[vidx] = tmpColor; // if (bBone) _aBoneWeights[vidx] = tmpBoneWeight; // tmp = tmp_; // tmpUV = tmpUV_; // tmpUV2 = tmpUV2_; // tmpNormal = tmpNormal_; // tmpTangent = tmpTangent_; // tmpColor = tmpColor_; // tmpBoneWeight = tmpBoneWeight_; // MappingLinkedNode* oldNode = node; // node = node->Next; // UnsafeUtility.Free(oldNode, Allocator.TempJob); // } //} //headArray.Dispose(); #else Vector2 tmpUV = Vector2.zero; Vector2 tmpUV2 = Vector2.zero; Vector3 tmpNormal = Vector3.zero; Vector4 tmpTangent = Vector4.zero; Color32 tmpColor = Color.black; BoneWeight tmpBoneWeight = new BoneWeight(); Vector2 tmpUV_ = Vector2.zero; Vector2 tmpUV2_ = Vector2.zero; Vector3 tmpNormal_ = Vector3.zero; Vector4 tmpTangent_ = Vector4.zero; Color32 tmpColor_ = Color.black; BoneWeight tmpBoneWeight_ = new BoneWeight(); for (int i = 0; i < _vertexMap.Length; i++) { int idx = i; Vector3 tmp = _av3Vertices[idx]; if (bUV1) { tmpUV = _av2Mapping1In[idx]; } if (bUV2) { tmpUV2 = _av2Mapping2In[idx]; } if (bNormal) { tmpNormal = _av3NormalsIn[idx]; } if (bTangent) { tmpTangent = _av4TangentsIn[idx]; } if (bColor32) { tmpColor = _aColors32In[idx]; } if (bBone) { tmpBoneWeight = _aBoneWeights[idx]; } while (_vertexMap[idx] != -1) { Vector3 tmp_ = _av3Vertices[_vertexMap[idx]]; if (bUV1) { tmpUV_ = _av2Mapping1In[_vertexMap[idx]]; } if (bUV2) { tmpUV2_ = _av2Mapping2In[_vertexMap[idx]]; } if (bNormal) { tmpNormal_ = _av3NormalsIn[_vertexMap[idx]]; } if (bTangent) { tmpTangent_ = _av4TangentsIn[_vertexMap[idx]]; } if (bColor32) { tmpColor_ = _aColors32In[_vertexMap[idx]]; } if (bBone) { tmpBoneWeight_ = _aBoneWeights[_vertexMap[idx]]; } _av3Vertices[_vertexMap[idx]] = tmp; if (bUV1) { _av2Mapping1In[_vertexMap[idx]] = tmpUV; } if (bUV2) { _av2Mapping2In[_vertexMap[idx]] = tmpUV2; } if (bNormal) { _av3NormalsIn[_vertexMap[idx]] = tmpNormal; } if (bTangent) { _av4TangentsIn[_vertexMap[idx]] = tmpTangent; } if (bColor32) { _aColors32In[_vertexMap[idx]] = tmpColor; } if (bBone) { _aBoneWeights[_vertexMap[idx]] = tmpBoneWeight; } tmp = tmp_; tmpUV = tmpUV_; tmpUV2 = tmpUV2_; tmpNormal = tmpNormal_; tmpTangent = tmpTangent_; tmpColor = tmpColor_; tmpBoneWeight = tmpBoneWeight_; int tmpI = _vertexMap[idx]; _vertexMap[idx] = -1; idx = tmpI; } } #endif //#if DEBUG // // Check // for (int i = 0; i < n; i++) // { // if (_vertexMap[i] != -1) // { // throw new Exception(""); // } // } //#endif this._meshOut = meshOut; _assignVertices = _assignVertices ?? (arr => this._meshOut.vertices = arr); if (bNormal) { _assignNormals = _assignNormals ?? (arr => this._meshOut.normals = arr); } if (bTangent) { _assignTangents = _assignTangents ?? (arr => this._meshOut.tangents = arr); } if (bUV1) { _assignUV = _assignUV ?? (arr => this._meshOut.uv = arr); } if (bUV2) { _assignUV2 = _assignUV2 ?? (arr => this._meshOut.uv2 = arr); } if (bColor32) { _assignColor32 = _assignColor32 ?? (arr => this._meshOut.colors32 = arr); } if (bBone) { _assignBoneWeights = _assignBoneWeights ?? (arr => this._meshOut.boneWeights = arr); } if (null == _setTriangles) { _setTriangles = new Action <int[]> [subMeshCount]; for (int i = 0; i < subMeshCount; i++) { int idx = i; _setTriangles[i] = (arr => this._meshOut.SetTriangles(arr, idx)); } } meshOut.triangles = null; // NOTE: 禁术 UnsafeUtil.Vector3HackArraySizeCall(_av3Vertices, n, _assignVertices); if (bNormal) { UnsafeUtil.Vector3HackArraySizeCall(_av3NormalsIn, n, _assignNormals); } if (bTangent) { UnsafeUtil.Vector4HackArraySizeCall(_av4TangentsIn, n, _assignTangents); } if (bUV1) { UnsafeUtil.Vector2HackArraySizeCall(_av2Mapping1In, n, _assignUV); } if (bUV2) { UnsafeUtil.Vector2HackArraySizeCall(_av2Mapping2In, n, _assignUV2); } if (bColor32) { UnsafeUtil.Color32HackArraySizeCall(_aColors32In, n, _assignColor32); } if (bBone) { UnsafeUtil.BoneWeightHackArraySizeCall(_aBoneWeights, n, _assignBoneWeights); } if (bBone) { meshOut.bindposes = _aBindPoses; } meshOut.subMeshCount = _aSubMeshes.Length; for (int i = 0; i < subMeshCount; i++) { UnsafeUtil.IntegerHackArraySizeCall(_aSubMeshes[i], _aTriangleCount[i], _setTriangles[i]); } meshOut.UploadMeshData(false); //meshOut.name = gameObject.name + " simplified mesh"; }
///////////////////////////////////////////////////////////////////////////////////////////////// // Private methods ///////////////////////////////////////////////////////////////////////////////////////////////// unsafe void ConsolidateMesh(GameObject gameObject, Mesh meshOut, int[] permutation, int[] collapseMap, int nVertices) { int subMeshCount = _aSubMeshesOriginal.Length; if (null == _av3Vertices) { _av3Vertices = (Vector3[])_av3VerticesOriginal.Clone(); } else { _av3VerticesOriginal.CopyTo(_av3Vertices, 0); } if (null == _av3NormalsIn) { _av3NormalsIn = (Vector3[])_av3NormalsOriginal.Clone(); } else { _av3NormalsOriginal.CopyTo(_av3NormalsIn, 0); } if (null == _av4TangentsIn) { _av4TangentsIn = (Vector4[])_av4TangentsOriginal.Clone(); } else { _av4TangentsOriginal.CopyTo(_av4TangentsIn, 0); } if (null == _av2Mapping1In) { _av2Mapping1In = (Vector2[])_av2Mapping1Original.Clone(); } else { _av2Mapping1Original.CopyTo(_av2Mapping1In, 0); } if (null == _av2Mapping2In) { _av2Mapping2In = (Vector2[])_av2Mapping2Original.Clone(); } else { _av2Mapping2Original.CopyTo(_av2Mapping2In, 0); } if (null == _aColors32In) { _aColors32In = (Color32[])_aColors32Original.Clone(); } else { _aColors32Original.CopyTo(_aColors32In, 0); } if (null == _aBoneWeights) { _aBoneWeights = (BoneWeight[])_aBoneWeightsOriginal.Clone(); } else { _aBoneWeightsOriginal.CopyTo(_aBoneWeights, 0); } if (null == _aSubMeshes) { _aSubMeshes = new int[subMeshCount][]; } if (null == _aTriangleCount) { _aTriangleCount = new int[subMeshCount]; } bool bUV1 = _av2Mapping1In != null && _av2Mapping1In.Length > 0; bool bUV2 = _av2Mapping2In != null && _av2Mapping2In.Length > 0; bool bNormal = _av3NormalsIn != null && _av3NormalsIn.Length > 0; bool bTangent = _av4TangentsIn != null && _av4TangentsIn.Length > 0; bool bColor32 = (_aColors32In != null && _aColors32In.Length > 0); bool bBone = _aBoneWeights != null && _aBoneWeights.Length > 0; _vertexMap = _vertexMap ?? new int[_av3Vertices.Length]; for (int i = 0, imax = _vertexMap.Length; i < imax; i++) { _vertexMap[i] = -1; } int n = 0; for (int nSubMesh = 0; nSubMesh < subMeshCount; nSubMesh++) { if (null == _aSubMeshes[nSubMesh]) { _aSubMeshes[nSubMesh] = (int[])_aSubMeshesOriginal[nSubMesh].Clone(); } else { _aSubMeshesOriginal[nSubMesh].CopyTo(_aSubMeshes[nSubMesh], 0); } int[] triangles = _aSubMeshes[nSubMesh]; for (int i = 0; i < triangles.Length; i += 3) { int idx0 = triangles[i]; int idx1 = triangles[i + 1]; int idx2 = triangles[i + 2]; while (permutation[idx0] >= nVertices) { int idx = collapseMap[idx0]; if (idx == -1 || idx1 == idx || idx2 == idx) { idx0 = -1; break; } idx0 = idx; } while (permutation[idx1] >= nVertices) { int idx = collapseMap[idx1]; if (idx == -1 || idx0 == idx || idx2 == idx) { idx1 = -1; break; } idx1 = idx; } while (permutation[idx2] >= nVertices) { int idx = collapseMap[idx2]; if (idx == -1 || idx1 == idx || idx0 == idx) { idx2 = -1; break; } idx2 = idx; } if (idx0 == -1 || idx1 == -1 || idx2 == -1) { triangles[i] = -1; triangles[i + 1] = -1; triangles[i + 2] = -1; continue; } if (_vertexMap[idx0] == -1) { _vertexMap[idx0] = n++; } triangles[i] = _vertexMap[idx0]; if (_vertexMap[idx1] == -1) { _vertexMap[idx1] = n++; } triangles[i + 1] = _vertexMap[idx1]; if (_vertexMap[idx2] == -1) { _vertexMap[idx2] = n++; } triangles[i + 2] = _vertexMap[idx2]; } int l = triangles.Length; int h = 0; int t = l - 1; while (h < t) { if (triangles[t] == -1) { t -= 3; continue; } if (triangles[h] != -1) { h += 3; continue; } triangles[h] = triangles[t - 2]; triangles[h + 1] = triangles[t - 1]; triangles[h + 2] = triangles[t]; triangles[t - 2] = -1; triangles[t - 1] = -1; triangles[t] = -1; h += 3; t -= 3; } if (t < l - 1) { _aTriangleCount[nSubMesh] = t + 1; //#if DEBUG // if (t >= 0 && triangles[t] == -1) // { // throw new Exception("triangles[t] == -1"); // } //#endif } else { _aTriangleCount[nSubMesh] = l; } } Vector2 tmpUV = Vector2.zero; Vector2 tmpUV2 = Vector2.zero; Vector3 tmpNormal = Vector3.zero; Vector4 tmpTangent = Vector4.zero; Color32 tmpColor = Color.black; BoneWeight tmpBoneWeight = new BoneWeight(); Vector2 tmpUV_ = Vector2.zero; Vector2 tmpUV2_ = Vector2.zero; Vector3 tmpNormal_ = Vector3.zero; Vector4 tmpTangent_ = Vector4.zero; Color32 tmpColor_ = Color.black; BoneWeight tmpBoneWeight_ = new BoneWeight(); #if UNITY_2018_1_OR_NEWER NativeArray <MappingLinkedNode> headArray = new NativeArray <MappingLinkedNode>(_vertexMap.Length, Allocator.TempJob); int headCount = 0; int nodeSize = UnsafeUtility.AlignOf <MappingLinkedNode>(); for (int i = 0; i < _vertexMap.Length; i++) { int idx = i; MappingLinkedNode *head = (MappingLinkedNode *)UnsafeUtility.Malloc(1, nodeSize, Allocator.TempJob); head->Next = null; head->Mapping = i; MappingLinkedNode *node = head; while (_vertexMap[idx] != -1) { MappingLinkedNode *next = (MappingLinkedNode *)UnsafeUtility.Malloc(1, nodeSize, Allocator.TempJob); next->Next = null; next->Mapping = _vertexMap[idx]; node->Next = next; int tmpI = _vertexMap[idx]; _vertexMap[idx] = -1; idx = tmpI; node = next; } if (head->Next != null) { headArray[headCount++] = *head; } } for (int i = 0; i < headCount; i++) { MappingLinkedNode head = headArray[i]; MappingLinkedNode *node = &head; int idx = node->Mapping; Vector3 tmp = _av3Vertices[idx]; if (bUV1) { tmpUV = _av2Mapping1In[idx]; } if (bUV2) { tmpUV2 = _av2Mapping2In[idx]; } if (bNormal) { tmpNormal = _av3NormalsIn[idx]; } if (bTangent) { tmpTangent = _av4TangentsIn[idx]; } if (bColor32) { tmpColor = _aColors32In[idx]; } if (bBone) { tmpBoneWeight = _aBoneWeights[idx]; } node = node->Next; while (node != null) { int vidx = node->Mapping; Vector3 tmp_ = _av3Vertices[vidx]; if (bUV1) { tmpUV_ = _av2Mapping1In[vidx]; } if (bUV2) { tmpUV2_ = _av2Mapping2In[vidx]; } if (bNormal) { tmpNormal_ = _av3NormalsIn[vidx]; } if (bTangent) { tmpTangent_ = _av4TangentsIn[vidx]; } if (bColor32) { tmpColor_ = _aColors32In[vidx]; } if (bBone) { tmpBoneWeight_ = _aBoneWeights[vidx]; } _av3Vertices[vidx] = tmp; if (bUV1) { _av2Mapping1In[vidx] = tmpUV; } if (bUV2) { _av2Mapping2In[vidx] = tmpUV2; } if (bNormal) { _av3NormalsIn[vidx] = tmpNormal; } if (bTangent) { _av4TangentsIn[vidx] = tmpTangent; } if (bColor32) { _aColors32In[vidx] = tmpColor; } if (bBone) { _aBoneWeights[vidx] = tmpBoneWeight; } tmp = tmp_; tmpUV = tmpUV_; tmpUV2 = tmpUV2_; tmpNormal = tmpNormal_; tmpTangent = tmpTangent_; tmpColor = tmpColor_; tmpBoneWeight = tmpBoneWeight_; MappingLinkedNode *oldNode = node; node = node->Next; UnsafeUtility.Free(oldNode, Allocator.TempJob); } } headArray.Dispose(); #else for (int i = 0; i < _vertexMap.Length; i++) { int idx = i; Vector3 tmp = _av3Vertices[idx]; if (bUV1) { tmpUV = _av2Mapping1In[idx]; } if (bUV2) { tmpUV2 = _av2Mapping2In[idx]; } if (bNormal) { tmpNormal = _av3NormalsIn[idx]; } if (bTangent) { tmpTangent = _av4TangentsIn[idx]; } if (bColor32) { tmpColor = _aColors32In[idx]; } if (bBone) { tmpBoneWeight = _aBoneWeights[idx]; } while (_vertexMap[idx] != -1) { Vector3 tmp_ = _av3Vertices[_vertexMap[idx]]; if (bUV1) { tmpUV_ = _av2Mapping1In[_vertexMap[idx]]; } if (bUV2) { tmpUV2_ = _av2Mapping2In[_vertexMap[idx]]; } if (bNormal) { tmpNormal_ = _av3NormalsIn[_vertexMap[idx]]; } if (bTangent) { tmpTangent_ = _av4TangentsIn[_vertexMap[idx]]; } if (bColor32) { tmpColor_ = _aColors32In[_vertexMap[idx]]; } if (bBone) { tmpBoneWeight_ = _aBoneWeights[_vertexMap[idx]]; } _av3Vertices[_vertexMap[idx]] = tmp; if (bUV1) { _av2Mapping1In[_vertexMap[idx]] = tmpUV; } if (bUV2) { _av2Mapping2In[_vertexMap[idx]] = tmpUV2; } if (bNormal) { _av3NormalsIn[_vertexMap[idx]] = tmpNormal; } if (bTangent) { _av4TangentsIn[_vertexMap[idx]] = tmpTangent; } if (bColor32) { _aColors32In[_vertexMap[idx]] = tmpColor; } if (bBone) { _aBoneWeights[_vertexMap[idx]] = tmpBoneWeight; } tmp = tmp_; tmpUV = tmpUV_; tmpUV2 = tmpUV2_; tmpNormal = tmpNormal_; tmpTangent = tmpTangent_; tmpColor = tmpColor_; tmpBoneWeight = tmpBoneWeight_; int tmpI = _vertexMap[idx]; _vertexMap[idx] = -1; idx = tmpI; } } #endif //#if DEBUG // // Check // for (int i = 0; i < n; i++) // { // if (_vertexMap[i] != -1) // { // throw new Exception(""); // } // } //#endif //如果有法线 TODO:操作为了 if (bNormal) { for (int i = 0; i < n; i++) { _av3NormalsIn[i] = _av3NormalsIn[i] * 0.1f; } for (int i = 0; i < subMeshCount; i++) { int[] triangles = _aSubMeshes[i]; for (int j = 0; j < _aTriangleCount[i]; j += 3) { int i0 = triangles[j]; int i1 = triangles[j + 1]; int i2 = triangles[j + 2]; Vector3 v0 = _av3Vertices[i0]; Vector3 v1 = _av3Vertices[i1]; Vector3 v2 = _av3Vertices[i2]; Vector3 normal = Vector3.Cross((v1 - v0), (v2 - v1)); _av3NormalsIn[i0] += normal; _av3NormalsIn[i1] += normal; _av3NormalsIn[i2] += normal; } } for (int i = 0; i < n; i++) { _av3NormalsIn[i] = _av3NormalsIn[i].normalized; } } this._meshOut = meshOut; _assignVertices = _assignVertices ?? (arr => this._meshOut.vertices = arr); if (bNormal) { _assignNormals = _assignNormals ?? (arr => this._meshOut.normals = arr); } if (bTangent) { _assignTangents = _assignTangents ?? (arr => this._meshOut.tangents = arr); } if (bUV1) { _assignUV = _assignUV ?? (arr => this._meshOut.uv = arr); } if (bUV2) { _assignUV2 = _assignUV2 ?? (arr => this._meshOut.uv2 = arr); } if (bColor32) { _assignColor32 = _assignColor32 ?? (arr => this._meshOut.colors32 = arr); } if (bBone) { _assignBoneWeights = _assignBoneWeights ?? (arr => this._meshOut.boneWeights = arr); } if (null == _setTriangles) { _setTriangles = new Action <int[]> [subMeshCount]; for (int i = 0; i < subMeshCount; i++) { int idx = i; _setTriangles[i] = (arr => this._meshOut.SetTriangles(arr, idx)); } } meshOut.triangles = null; // NOTE: 禁术 UnsafeUtil.Vector3HackArraySizeCall(_av3Vertices, n, _assignVertices); if (bNormal) { UnsafeUtil.Vector3HackArraySizeCall(_av3NormalsIn, n, _assignNormals); } if (bTangent) { UnsafeUtil.Vector4HackArraySizeCall(_av4TangentsIn, n, _assignTangents); } if (bUV1) { UnsafeUtil.Vector2HackArraySizeCall(_av2Mapping1In, n, _assignUV); } if (bUV2) { UnsafeUtil.Vector2HackArraySizeCall(_av2Mapping2In, n, _assignUV2); } if (bColor32) { UnsafeUtil.Color32HackArraySizeCall(_aColors32In, n, _assignColor32); } if (bBone) { UnsafeUtil.BoneWeightHackArraySizeCall(_aBoneWeights, n, _assignBoneWeights); } if (bBone) { meshOut.bindposes = _aBindPoses; } meshOut.subMeshCount = _aSubMeshes.Length; for (int i = 0; i < subMeshCount; i++) { UnsafeUtil.IntegerHackArraySizeCall(_aSubMeshes[i], _aTriangleCount[i], _setTriangles[i]); } meshOut.UploadMeshData(false); //meshOut.name = gameObject.name + " simplified mesh"; }
///////////////////////////////////////////////////////////////////////////////////////////////// // Private methods ///////////////////////////////////////////////////////////////////////////////////////////////// unsafe void ConsolidateMesh(GameObject gameObject, Mesh meshOut, int[] permutation, int[] collapseMap, int nVertices) { int subMeshCount = _subMeshesOriginal.Length; if (null == _vertices) { _vertices = (Vector3[])_verticesOriginal.Clone(); } else { _verticesOriginal.CopyTo(_vertices, 0); } if (null == _normalsIn) { _normalsIn = (Vector3[])_normalsOriginal.Clone(); } else { _normalsOriginal.CopyTo(_normalsIn, 0); } if (null == _tangentsIn) { _tangentsIn = (Vector4[])_tangentsOriginal.Clone(); } else { _tangentsOriginal.CopyTo(_tangentsIn, 0); } if (null == _texCoord1In) { _texCoord1In = (Vector2[])_texCoord1Original.Clone(); } else { _texCoord1Original.CopyTo(_texCoord1In, 0); } if (null == _texCoord2In) { _texCoord2In = (Vector2[])_texCoord2Original.Clone(); } else { _texCoord2Original.CopyTo(_texCoord2In, 0); } if (null == _colors32In) { _colors32In = (Color32[])_colors32Original.Clone(); } else { _colors32Original.CopyTo(_colors32In, 0); } if (null == _boneWeights) { _boneWeights = (BoneWeight[])_boneWeightsOriginal.Clone(); } else { _boneWeightsOriginal.CopyTo(_boneWeights, 0); } if (null == _subMeshes) { _subMeshes = new int[subMeshCount][]; } if (null == _triangleCount) { _triangleCount = new int[subMeshCount]; } bool bUV1 = _texCoord1In != null && _texCoord1In.Length > 0; bool bUV2 = _texCoord2In != null && _texCoord2In.Length > 0; bool bNormal = _normalsIn != null && _normalsIn.Length > 0; bool bTangent = _tangentsIn != null && _tangentsIn.Length > 0; bool bColor32 = (_colors32In != null && _colors32In.Length > 0); bool bBone = _boneWeights != null && _boneWeights.Length > 0; _vertexMap = _vertexMap ?? new int[_vertices.Length]; for (int i = 0, imax = _vertexMap.Length; i < imax; i++) { _vertexMap[i] = -1; } int n = 0; for (int nSubMesh = 0; nSubMesh < subMeshCount; nSubMesh++) { if (null == _subMeshes[nSubMesh]) { _subMeshes[nSubMesh] = (int[])_subMeshesOriginal[nSubMesh].Clone(); } else { _subMeshesOriginal[nSubMesh].CopyTo(_subMeshes[nSubMesh], 0); } int[] triangles = _subMeshes[nSubMesh]; for (int i = 0; i < triangles.Length; i += 3) { int idx0 = triangles[i]; int idx1 = triangles[i + 1]; int idx2 = triangles[i + 2]; while (permutation[idx0] >= nVertices) { int idx = collapseMap[idx0]; if (idx == -1 || idx1 == idx || idx2 == idx) { idx0 = -1; break; } idx0 = idx; } while (permutation[idx1] >= nVertices) { int idx = collapseMap[idx1]; if (idx == -1 || idx0 == idx || idx2 == idx) { idx1 = -1; break; } idx1 = idx; } while (permutation[idx2] >= nVertices) { int idx = collapseMap[idx2]; if (idx == -1 || idx1 == idx || idx0 == idx) { idx2 = -1; break; } idx2 = idx; } if (idx0 == -1 || idx1 == -1 || idx2 == -1) { triangles[i] = -1; triangles[i + 1] = -1; triangles[i + 2] = -1; continue; } if (_vertexMap[idx0] == -1) { _vertexMap[idx0] = n++; } triangles[i] = _vertexMap[idx0]; if (_vertexMap[idx1] == -1) { _vertexMap[idx1] = n++; } triangles[i + 1] = _vertexMap[idx1]; if (_vertexMap[idx2] == -1) { _vertexMap[idx2] = n++; } triangles[i + 2] = _vertexMap[idx2]; } int l = triangles.Length; int h = 0; int t = l - 1; while (h < t) { if (triangles[t] == -1) { t -= 3; continue; } if (triangles[h] != -1) { h += 3; continue; } triangles[h] = triangles[t - 2]; triangles[h + 1] = triangles[t - 1]; triangles[h + 2] = triangles[t]; triangles[t - 2] = -1; triangles[t - 1] = -1; triangles[t] = -1; h += 3; t -= 3; } if (t < l - 1) { _triangleCount[nSubMesh] = t + 1; //#if DEBUG // if (t >= 0 && triangles[t] == -1) // { // throw new Exception("triangles[t] == -1"); // } //#endif } else { _triangleCount[nSubMesh] = l; } } Vector2 tmpUV = Vector2.zero; Vector2 tmpUV2 = Vector2.zero; Vector3 tmpNormal = Vector3.zero; Vector4 tmpTangent = Vector4.zero; Color32 tmpColor = Color.black; BoneWeight tmpBoneWeight = new BoneWeight(); Vector2 tmpUV_ = Vector2.zero; Vector2 tmpUV2_ = Vector2.zero; Vector3 tmpNormal_ = Vector3.zero; Vector4 tmpTangent_ = Vector4.zero; Color32 tmpColor_ = Color.black; BoneWeight tmpBoneWeight_ = new BoneWeight(); for (int i = 0; i < _vertexMap.Length; i++) { int idx = i; Vector3 tmp = _vertices[idx]; if (bUV1) { tmpUV = _texCoord1In[idx]; } if (bUV2) { tmpUV2 = _texCoord2In[idx]; } if (bNormal) { tmpNormal = _normalsIn[idx]; } if (bTangent) { tmpTangent = _tangentsIn[idx]; } if (bColor32) { tmpColor = _colors32In[idx]; } if (bBone) { tmpBoneWeight = _boneWeights[idx]; } while (_vertexMap[idx] != -1) { Vector3 tmp_ = _vertices[_vertexMap[idx]]; if (bUV1) { tmpUV_ = _texCoord1In[_vertexMap[idx]]; } if (bUV2) { tmpUV2_ = _texCoord2In[_vertexMap[idx]]; } if (bNormal) { tmpNormal_ = _normalsIn[_vertexMap[idx]]; } if (bTangent) { tmpTangent_ = _tangentsIn[_vertexMap[idx]]; } if (bColor32) { tmpColor_ = _colors32In[_vertexMap[idx]]; } if (bBone) { tmpBoneWeight_ = _boneWeights[_vertexMap[idx]]; } _vertices[_vertexMap[idx]] = tmp; if (bUV1) { _texCoord1In[_vertexMap[idx]] = tmpUV; } if (bUV2) { _texCoord2In[_vertexMap[idx]] = tmpUV2; } if (bNormal) { _normalsIn[_vertexMap[idx]] = tmpNormal; } if (bTangent) { _tangentsIn[_vertexMap[idx]] = tmpTangent; } if (bColor32) { _colors32In[_vertexMap[idx]] = tmpColor; } if (bBone) { _boneWeights[_vertexMap[idx]] = tmpBoneWeight; } tmp = tmp_; tmpUV = tmpUV_; tmpUV2 = tmpUV2_; tmpNormal = tmpNormal_; tmpTangent = tmpTangent_; tmpColor = tmpColor_; tmpBoneWeight = tmpBoneWeight_; int tmpI = _vertexMap[idx]; _vertexMap[idx] = -1; idx = tmpI; } } this._meshOut = meshOut; _assignVertices = _assignVertices ?? (arr => this._meshOut.vertices = arr); if (bNormal) { _assignNormals = _assignNormals ?? (arr => this._meshOut.normals = arr); } if (bTangent) { _assignTangents = _assignTangents ?? (arr => this._meshOut.tangents = arr); } if (bUV1) { _assignUV = _assignUV ?? (arr => this._meshOut.uv = arr); } if (bUV2) { _assignUV2 = _assignUV2 ?? (arr => this._meshOut.uv2 = arr); } if (bColor32) { _assignColor32 = _assignColor32 ?? (arr => this._meshOut.colors32 = arr); } if (bBone) { _assignBoneWeights = _assignBoneWeights ?? (arr => this._meshOut.boneWeights = arr); } if (null == _setTriangles) { _setTriangles = new Action <int[]> [subMeshCount]; for (int i = 0; i < subMeshCount; i++) { int idx = i; _setTriangles[i] = (arr => this._meshOut.SetTriangles(arr, idx)); } } meshOut.triangles = null; // NOTE: 禁术 UnsafeUtil.Vector3HackArraySizeCall(_vertices, n, _assignVertices); if (bNormal) { UnsafeUtil.Vector3HackArraySizeCall(_normalsIn, n, _assignNormals); } if (bTangent) { UnsafeUtil.Vector4HackArraySizeCall(_tangentsIn, n, _assignTangents); } if (bUV1) { UnsafeUtil.Vector2HackArraySizeCall(_texCoord1In, n, _assignUV); } if (bUV2) { UnsafeUtil.Vector2HackArraySizeCall(_texCoord2In, n, _assignUV2); } if (bColor32) { UnsafeUtil.Color32HackArraySizeCall(_colors32In, n, _assignColor32); } if (bBone) { UnsafeUtil.BoneWeightHackArraySizeCall(_boneWeights, n, _assignBoneWeights); } if (bBone) { meshOut.bindposes = _bindPoses; } meshOut.subMeshCount = _subMeshes.Length; for (int i = 0; i < subMeshCount; i++) { UnsafeUtil.IntegerHackArraySizeCall(_subMeshes[i], _triangleCount[i], _setTriangles[i]); } meshOut.UploadMeshData(false); //meshOut.name = gameObject.name + " simplified mesh"; }