public static CopyMeshJob <T> Create(Simplifier.MappingLinkedNode *pHeadArray, int length) { CopyMeshJob <T> job = new CopyMeshJob <T>(); job._pHeadArray = pHeadArray; job._array = new NativeArray <T>(length, Allocator.TempJob); job._pArray = job._array.GetUnsafePtr(); return(job); }
///////////////////////////////////////////////////////////////////////////////////////////////// // 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"; }