public void CopyUVs(int id, bool baseOrBlend, bool setOrGet) { UVNormalBlendMonoBehaviour.Data dstData = Datas[(int)id]; MeshRenderer mr = dstData.renderer.instance; Operations.vMesh m = new Operations.vMesh(mr, false, false); List <Vector2> uvs = baseOrBlend ? dstData.blendUVs : dstData.baseUVs; if (setOrGet) { for (int i = 0; i < m.submeshes.Count; i++) { Operations.vSubmesh s = m.submeshes[i]; for (int j = 0; j < s.vertexList.Count; j++) { s.vertexList[j].uv[0] = uvs[j][0]; s.vertexList[j].uv[1] = -uvs[j][1]; } } m.Flush(); } else { uvs.Clear(); for (int i = 0; i < m.submeshes.Count; i++) { Operations.vSubmesh s = m.submeshes[i]; for (int j = 0; j < s.vertexList.Count; j++) { Vector2 uv = new Vector2(s.vertexList[j].uv[0], -s.vertexList[j].uv[1]); uvs.Add(uv); } } Parser.datas = Datas; } Changed = true; }
public void CopyNormals(int id, AnimatorEditor dstAnimatorEditor, bool minOrMax, bool setOrGet) { GenericMono dstData = GenericMonos[(int)id]; int dstMeshRId = dstAnimatorEditor.GetMeshRendererId(dstData.ObjectName); MeshRenderer mr = (MeshRenderer)dstAnimatorEditor.Meshes[dstMeshRId]; Operations.vMesh m = new Operations.vMesh(mr, false, false); List <Vector3> normals = minOrMax ? dstData.NormalMax : dstData.NormalMin; if (setOrGet) { for (int i = 0; i < m.submeshes.Count; i++) { Operations.vSubmesh s = m.submeshes[i]; for (int j = 0; j < s.vertexList.Count; j++) { s.vertexList[j].normal = normals[j]; } } m.Flush(); } else { normals.Clear(); for (int i = 0; i < m.submeshes.Count; i++) { Operations.vSubmesh s = m.submeshes[i]; for (int j = 0; j < s.vertexList.Count; j++) { normals.Add(s.vertexList[j].normal); } } Parser.Param = GenericMonos; } Changed = true; }
public void CopyNormals(int id, bool baseOrBlend, bool setOrGet) { UVNormalBlendMonoBehaviour.Data dstData = Datas[(int)id]; MeshRenderer mr = dstData.renderer.instance; Operations.vMesh m = new Operations.vMesh(mr, false, false); List <Vector3> normals = baseOrBlend ? dstData.blendNormals : dstData.baseNormals; if (setOrGet) { for (int i = 0; i < m.submeshes.Count; i++) { Operations.vSubmesh s = m.submeshes[i]; for (int j = 0; j < s.vertexList.Count; j++) { s.vertexList[j].normal = normals[j]; } } m.Flush(); } else { normals.Clear(); for (int i = 0; i < m.submeshes.Count; i++) { Operations.vSubmesh s = m.submeshes[i]; for (int j = 0; j < s.vertexList.Count; j++) { normals.Add(s.vertexList[j].normal); } } Parser.datas = Datas; } Changed = true; }
public void ComputeMinMaxNormals(object[] nmlMeshIds, AnimatorEditor dstAnimatorEditor, NmlMonoBehaviourEditor srcNmlEditor, int srcNmlMeshId, AnimatorEditor srcAnimatorEditor, object[] adjacentAnimatorEditorMeshIdPairs, double adjacentSquaredDistance, bool worldCoordinates) { foreach (double id in nmlMeshIds) { int dstMeshRId = dstAnimatorEditor.GetMeshRendererId(GenericMonos[(int)id].ObjectName); SkinnedMeshRenderer dstSMesh = (SkinnedMeshRenderer)dstAnimatorEditor.Meshes[dstMeshRId]; Operations.vMesh dstVMesh = new Operations.vMesh(dstSMesh, false, false); List <Operations.vVertex> dstVertList = dstVMesh.submeshes[0].vertexList; for (int i = 1; i < dstVMesh.submeshes.Count; i++) { dstVertList.AddRange(dstVMesh.submeshes[i].vertexList); } Transform meshTransform = dstSMesh.m_GameObject.instance.FindLinkedComponent(typeof(Transform)); Matrix meshTransformMatrix = Transform.WorldTransform(meshTransform); foreach (var vert in dstVertList) { vert.position = Vector3.TransformCoordinate(vert.position, meshTransformMatrix); } int srcMeshRId = srcAnimatorEditor.GetMeshRendererId(srcNmlMeshId < 0 ? dstSMesh.m_GameObject.instance.m_Name : srcNmlEditor.GenericMonos[srcNmlMeshId].ObjectName); SkinnedMeshRenderer srcSMesh = (SkinnedMeshRenderer)srcAnimatorEditor.Meshes[srcMeshRId]; Operations.vMesh srcVMesh = new Operations.vMesh(srcSMesh, false, false); List <Operations.vVertex> srcVertList = srcVMesh.submeshes[0].vertexList; for (int i = 1; i < srcVMesh.submeshes.Count; i++) { srcVertList.AddRange(srcVMesh.submeshes[i].vertexList); } meshTransform = srcSMesh.m_GameObject.instance.FindLinkedComponent(typeof(Transform)); meshTransformMatrix = Transform.WorldTransform(meshTransform); foreach (var vert in srcVertList) { vert.position = Vector3.TransformCoordinate(vert.position, meshTransformMatrix); } GenericMono dstGenMono = GenericMonos.Find ( delegate(GenericMono m) { return(m.ObjectName == dstSMesh.m_GameObject.instance.m_Name); } ); if (dstGenMono == null) { dstGenMono = new GenericMono(); dstGenMono.ObjectName = dstSMesh.m_GameObject.instance.m_Name; GenericMonos.Add(dstGenMono); } else { dstGenMono.NormalMin.Clear(); dstGenMono.NormalMax.Clear(); } GenericMono srcGenMono = srcNmlMeshId < 0 ? srcNmlEditor.GenericMonos.Find ( delegate(GenericMono m) { return(m.ObjectName == dstSMesh.m_GameObject.instance.m_Name); } ) : srcNmlEditor.GenericMonos[srcNmlMeshId]; if (srcGenMono == null) { throw new Exception("Source GenericMono for " + dstSMesh.m_GameObject.instance.m_Name + " not found"); } if (srcGenMono.NormalMin.Count != srcVertList.Count) { throw new Exception("Source GenericMono for " + dstSMesh.m_GameObject.instance.m_Name + " has " + srcGenMono.NormalMin.Count + " normals, but the source mesh has " + srcVertList.Count + " vertices."); } for (int i = 0; i < dstVertList.Count; i++) { var vert = dstVertList[i]; int vertIdx = -1; float minDistPos = float.MaxValue; float minDistUV = float.MaxValue; for (int j = 0; j < srcVertList.Count; j++) { var srcVert = srcVertList[j]; float distSquare = (vert.position - srcVert.position).LengthSquared(); if (distSquare < minDistPos) { vertIdx = j; if ((minDistPos = distSquare) == 0) { distSquare = (new Vector2(vert.uv[0], vert.uv[1]) - new Vector2(srcVert.uv[0], srcVert.uv[1])).LengthSquared(); if (distSquare < minDistUV) { if ((minDistUV = distSquare) == 0) { break; } } } } else if (distSquare == minDistPos) { distSquare = (new Vector2(vert.uv[0], vert.uv[1]) - new Vector2(srcVert.uv[0], srcVert.uv[1])).LengthSquared(); if (distSquare < minDistUV) { vertIdx = j; if ((minDistUV = distSquare) == 0) { break; } } } } dstGenMono.NormalMin.Add(vert.normal + srcGenMono.NormalMin[vertIdx] - srcGenMono.NormalMax[vertIdx]); dstGenMono.NormalMax.Add(vert.normal); } if (adjacentAnimatorEditorMeshIdPairs != null) { HashSet <int> dstVertIndices = new HashSet <int>(); Operations.vMesh[] adjVMeshes = new Operations.vMesh[adjacentAnimatorEditorMeshIdPairs.Length / 2]; for (int i = 0; i < adjacentAnimatorEditorMeshIdPairs.Length / 2; i++) { MeshRenderer adjMeshR = (MeshRenderer)((AnimatorEditor)adjacentAnimatorEditorMeshIdPairs[i * 2]).Meshes[(int)(double)adjacentAnimatorEditorMeshIdPairs[i * 2 + 1]]; Matrix worldTransform; if (worldCoordinates) { meshTransform = adjMeshR.m_GameObject.instance.FindLinkedComponent(typeof(Transform)); worldTransform = Transform.WorldTransform(meshTransform); } else { worldTransform = Matrix.Identity; } Operations.vMesh adjVMesh = new Operations.vMesh(adjMeshR, false, false); int adjVertsAdapted = 0; foreach (var adjSubmesh in adjVMesh.submeshes) { foreach (var adjVert in adjSubmesh.vertexList) { Vector3 adjPos = worldCoordinates ? Vector3.TransformCoordinate(adjVert.position, worldTransform) : adjVert.position; for (int j = 0; j < dstVertList.Count; j++) { var dstVert = dstVertList[j]; if ((adjPos - dstVert.position).LengthSquared() < adjacentSquaredDistance) { if (dstVertIndices.Add(j)) { dstGenMono.NormalMin[j] = dstGenMono.NormalMax[j] = (dstGenMono.NormalMin[j] + dstGenMono.NormalMax[j]) / 2; } adjVert.normal = dstGenMono.NormalMin[j]; adjVertsAdapted++; break; } } } } if (adjVertsAdapted > 0) { adjVMeshes[i] = adjVMesh; Report.ReportLog("Adjacent MeshRenderer " + adjMeshR.m_GameObject.instance.m_Name + " has " + adjVertsAdapted + " verts smaller squared distance than " + ((float)adjacentSquaredDistance).ToFloatString()); } } for (int i = 0; i < adjVMeshes.Length; i++) { var adjVMesh = adjVMeshes[i]; if (adjVMesh != null) { adjVMesh.Flush(); ((AnimatorEditor)adjacentAnimatorEditorMeshIdPairs[i * 2]).Changed = true; } } } } Parser.Param = GenericMonos; Changed = true; }
private AnimationFrame CreateFrame(Transform frame, AnimatorEditor editor, HashSet<string> extractFrames, HashSet<string> meshNames, Device device, List<AnimationFrame> meshFrames, Dictionary<string, Tuple<Matrix, Matrix>> extractMatrices) { AnimationFrame animationFrame = new AnimationFrame(); animationFrame.Name = frame.GetTransformPath(); animationFrame.TransformationMatrix = Matrix.Scaling(frame.m_LocalScale) * Matrix.RotationQuaternion(frame.m_LocalRotation) * Matrix.Translation(frame.m_LocalPosition); animationFrame.OriginalTransform = animationFrame.TransformationMatrix; animationFrame.CombinedTransform = extractMatrices[animationFrame.Name].Item1; if (meshNames.Contains(animationFrame.Name)) { MeshRenderer meshR = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.SkinnedMeshRenderer); if (meshR == null) { meshR = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.MeshRenderer); } if (meshR != null) { Mesh mesh = Operations.GetMesh(meshR); if (mesh != null) { SkinnedMeshRenderer smr = meshR as SkinnedMeshRenderer; List<PPtr<Transform>> boneList = null; string[] boneNames = null; Matrix[] boneOffsets = null; if (smr != null && smr.m_Bones.Count > 0) { boneList = smr.m_Bones; int numBones = boneList.Count > 0 ? extractFrames.Count : 0; boneNames = new string[numBones]; boneOffsets = new Matrix[numBones]; if (numBones > 0) { string[] extractArray = new string[numBones]; extractFrames.CopyTo(extractArray); HashSet<string> extractCopy = new HashSet<string>(extractArray); int invalidBones = 0; for (int i = 0; i < boneList.Count; i++) { Transform bone = boneList[i].instance; if (bone == null || bone.m_GameObject.instance == null || !extractCopy.Remove(bone.GetTransformPath())) { invalidBones++; } else if (i < numBones) { boneNames[i] = bone.GetTransformPath(); boneOffsets[i] = Operations.Mirror(Matrix.Transpose(mesh.m_BindPose[i])); } } extractCopy.CopyTo(boneNames, boneList.Count - invalidBones); for (int i = boneList.Count; i < extractFrames.Count; i++) { boneOffsets[i] = extractMatrices[boneNames[i]].Item2; } } } AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.m_SubMeshes.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); Operations.vMesh vMesh = new Operations.vMesh(meshR, true, true); for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { Operations.vSubmesh submesh = vMesh.submeshes[i]; List<Operations.vFace> faceList = submesh.faceList; List<Operations.vVertex> vertexList = submesh.vertexList; SlimDX.Direct3D9.Mesh animationMesh = null; PositionBlendWeightsIndexedColored[] normalLines = null; try { animationMesh = new SlimDX.Direct3D9.Mesh(device, faceList.Count, vertexList.Count, MeshFlags.Managed, PositionBlendWeightsIndexedNormalTexturedColoured.Format); using (DataStream indexStream = animationMesh.LockIndexBuffer(LockFlags.None)) { for (int j = 0; j < faceList.Count; j++) { ushort[] indices = faceList[j].index; indexStream.Write(indices[0]); indexStream.Write(indices[2]); indexStream.Write(indices[1]); } animationMesh.UnlockIndexBuffer(); } FillVertexBuffer(animationMesh, vertexList, -1); normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { Operations.vVertex vertex = vertexList[j]; byte[] bIdx; float[] bWeights; if (vertex.boneIndices != null) { bIdx = new byte[4] { (byte)vertex.boneIndices[0], (byte)vertex.boneIndices[1], (byte)vertex.boneIndices[2], (byte)vertex.boneIndices[3] }; bWeights = vertex.weights; } else { bIdx = new byte[4]; bWeights = new float[4]; } normalLines[j * 2] = new PositionBlendWeightsIndexedColored(vertex.position, bWeights, bIdx, Color.Yellow.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(vertex.position + (vertex.normal / 64), bWeights, bIdx, Color.Yellow.ToArgb()); min = Vector3.Minimize(min, vertex.position); max = Vector3.Maximize(max, vertex.position); } } catch { Report.ReportLog("No display of submeshes with more than 64k vertices!"); } AnimationMeshContainer meshContainer = new AnimationMeshContainer(); if (animationMesh != null) { meshContainer.Name = animationFrame.Name; meshContainer.MeshData = new MeshData(animationMesh); meshContainer.NormalLines = normalLines; } meshContainers[i] = meshContainer; if (submesh.matList.Count > 0 && submesh.matList[0].instance != null) { Material mat = submesh.matList[0].instance; int matIdx = editor.Materials.IndexOf(mat); int texIdx; if (!MatTexIndices.TryGetValue(matIdx, out texIdx)) { texIdx = -1; SlimDX.Direct3D9.Material materialD3D = new SlimDX.Direct3D9.Material(); materialD3D.Ambient = GetColour(mat, "_SColor"); materialD3D.Diffuse = GetColour(mat, "_Color"); materialD3D.Emissive = GetColour(mat, "_ReflectColor"); materialD3D.Specular = GetColour(mat, "_SpecColor"); materialD3D.Power = GetFloat(mat, "_Shininess"); Materials[matIdx] = materialD3D; Texture2D matTex = GetTexture(mat, "_MainTex"); if (matTex != null) { texIdx = editor.Textures.IndexOf(matTex); if (Textures[texIdx] == null) { using (MemoryStream mem = new MemoryStream()) { matTex.Export(mem); mem.Position = 0; ImportedTexture image = new ImportedTexture(mem, matTex.m_Name); Textures[texIdx] = Texture.FromMemory(device, image.Data); } } } MatTexIndices.Add(matIdx, texIdx); } meshContainer.MaterialIndex = matIdx; meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } if (boneList != null) { for (int i = 0; i < meshContainers.Length; i++) { meshContainers[i].BoneNames = boneNames; meshContainers[i].BoneOffsets = boneOffsets; meshContainers[i].RealBones = boneList.Count; } } Matrix mirrorCombined = Operations.Mirror(animationFrame.CombinedTransform); min = Vector3.TransformCoordinate(min, mirrorCombined); max = Vector3.TransformCoordinate(max, mirrorCombined); animationFrame.Bounds = new BoundingBox(min, max); animationFrame.MeshContainer = meshContainers[0]; meshFrames.Add(animationFrame); } } } for (int i = 0; i < frame.Count; i++) { Transform child = frame[i]; if (extractFrames.Contains(child.GetTransformPath())) { AnimationFrame childAnimationFrame = CreateFrame(child, editor, extractFrames, meshNames, device, meshFrames, extractMatrices); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return animationFrame; }
public float SetMorphKeyframe(SkinnedMeshRenderer sMesh, int keyframeIdx, bool asStart) { foreach (AnimationFrame frame in meshFrames) { Transform meshTransform = sMesh.m_GameObject.instance.FindLinkedComponent(UnityClassID.Transform); if (frame.Name == meshTransform.GetTransformPath()) { Mesh mesh = Operations.GetMesh(sMesh); AnimationMeshContainer animMesh = frame.MeshContainer as AnimationMeshContainer; if (animMesh != null) { MorphMeshContainer[] morphMeshes = new MorphMeshContainer[mesh.m_SubMeshes.Count]; int startVertexIdx = 0; for (int meshObjIdx = 0; meshObjIdx < mesh.m_SubMeshes.Count; meshObjIdx++) { MorphMeshContainer morphMesh = new MorphMeshContainer(); morphMeshes[meshObjIdx] = morphMesh; morphMesh.FaceCount = (int)mesh.m_SubMeshes[meshObjIdx].indexCount / 3; morphMesh.IndexBuffer = animMesh.MeshData.Mesh.IndexBuffer; morphMesh.VertexCount = (int)mesh.m_SubMeshes[meshObjIdx].vertexCount; Operations.vMesh vMesh = new Operations.vMesh(sMesh, false, false); List<Operations.vVertex> vertexList = vMesh.submeshes[meshObjIdx].vertexList; VertexBuffer vertBuffer = CreateMorphVertexBuffer(mesh.m_Shapes, keyframeIdx, vertexList, startVertexIdx); morphMesh.StartBuffer = morphMesh.EndBuffer = vertBuffer; int vertBufferSize = morphMesh.VertexCount * Marshal.SizeOf(typeof(TweeningWithoutNormalsVertexBufferFormat.Stream2)); vertBuffer = new VertexBuffer(device, vertBufferSize, Usage.WriteOnly, VertexFormat.Texture1, Pool.Managed); using (DataStream vertexStream = vertBuffer.Lock(0, vertBufferSize, LockFlags.None)) { for (int i = 0; i < vertexList.Count; i++) { Operations.vVertex vertex = vertexList[i]; vertexStream.Write(vertex.uv[0]); vertexStream.Write(vertex.uv[1]); } vertBuffer.Unlock(); } morphMesh.CommonBuffer = vertBuffer; morphMesh.MaterialIndex = animMesh.MaterialIndex; morphMesh.TextureIndex = animMesh.TextureIndex; morphMesh.TweenFactor = 0.0f; startVertexIdx += morphMesh.VertexCount; animMesh = (AnimationMeshContainer)animMesh.NextMeshContainer; } for (int meshObjIdx = 0; meshObjIdx < mesh.m_SubMeshes.Count; meshObjIdx++) { morphMeshes[meshObjIdx].NextMeshContainer = meshObjIdx < mesh.m_SubMeshes.Count - 1 ? (MeshContainer)morphMeshes[meshObjIdx + 1] : frame.MeshContainer; } frame.MeshContainer = morphMeshes[0]; return 0; } else { MorphMeshContainer morphMesh = frame.MeshContainer as MorphMeshContainer; Operations.vMesh vMesh = new Operations.vMesh(sMesh, false, false); int startVertexIdx = 0; for (int meshObjIdx = 0; meshObjIdx < mesh.m_SubMeshes.Count; meshObjIdx++) { List<Operations.vVertex> vertexList = vMesh.submeshes[meshObjIdx].vertexList; VertexBuffer vertBuffer = CreateMorphVertexBuffer(mesh.m_Shapes, keyframeIdx, vertexList, startVertexIdx); if (asStart) { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.StartBuffer.Dispose(); } morphMesh.StartBuffer = vertBuffer; morphMesh.TweenFactor = 0.0f; } else { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.EndBuffer.Dispose(); } morphMesh.EndBuffer = vertBuffer; morphMesh.TweenFactor = 1.0f; } startVertexIdx += morphMesh.VertexCount; morphMesh = morphMesh.NextMeshContainer as MorphMeshContainer; } return asStart ? 0 : 1; } } } Report.ReportLog("Mesh frame " + sMesh.m_GameObject.instance.m_Name + " not displayed."); return -1f; }
public void HighlightBone(MeshRenderer meshR, int boneIdx, bool show) { Operations.vMesh vMesh = new Operations.vMesh(meshR, false, true); int submeshIdx = 0; for (AnimationMeshContainer mesh = meshFrames[0].MeshContainer as AnimationMeshContainer; mesh != null; mesh = (AnimationMeshContainer)mesh.NextMeshContainer, submeshIdx++) { if (mesh.MeshData != null && mesh.MeshData.Mesh != null) { List<Operations.vVertex> vertexList = vMesh.submeshes[submeshIdx].vertexList; FillVertexBuffer(mesh.MeshData.Mesh, vertexList, show ? boneIdx : -1); if (show) { Materials[mesh.MaterialIndex].Ambient = new Color4(unchecked((int)0xFF060660)); Materials[mesh.MaterialIndex].Emissive = Color.Black; } else { Material mat = vMesh.submeshes[submeshIdx].matList[0].instance; Materials[mesh.MaterialIndex].Ambient = GetColour(mat, "_SColor"); Materials[mesh.MaterialIndex].Emissive = GetColour(mat, "_ReflectColor"); } } if (mesh.BoneLines != null) { if (boneIdx < mesh.BoneLines.Length / BoneObjSize) { for (int j = 0; j < BoneObjSize; j++) { mesh.BoneLines[boneIdx * BoneObjSize + j].Color = show ? Color.Crimson.ToArgb() : Color.CornflowerBlue.ToArgb(); } mesh.SelectedBone = boneIdx; } } } }
public static void ReplaceMeshRenderer(Transform frame, Transform rootBone, Animator parser, List <Material> materials, WorkspaceMesh mesh, bool merge, CopyMeshMethod normalsMethod, CopyMeshMethod bonesMethod, bool targetFullMesh) { Matrix transform = Transform.WorldTransform(frame); int[] indices; bool[] worldCoords; bool[] replaceSubmeshesOption; SkinnedMeshRenderer sMesh = CreateSkinnedMeshRenderer(parser, materials, mesh, transform, out indices, out worldCoords, out replaceSubmeshesOption); vMesh destMesh = new Operations.vMesh(sMesh, true, false); SkinnedMeshRenderer sFrameMesh = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.SkinnedMeshRenderer); MeshRenderer frameMeshR = sFrameMesh; if (sFrameMesh == null) { frameMeshR = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.MeshRenderer); } Mesh frameMesh = frameMeshR != null?Operations.GetMesh(frameMeshR) : null; vMesh srcMesh = null; List <vVertex> allVertices = null; if (frameMeshR == null || frameMesh == null) { sMesh.m_RootBone = new PPtr <Transform>(rootBone); if (rootBone != null) { sMesh.m_Mesh.instance.m_RootBoneNameHash = parser.m_Avatar.instance.BoneHash(rootBone.m_GameObject.instance.m_Name); } if (frameMeshR != null) { CopyUnknowns(frameMeshR, sMesh); } } else { if (sFrameMesh != null) { sMesh.m_RootBone = new PPtr <Transform>(sFrameMesh.m_RootBone.instance); sMesh.m_Mesh.instance.m_RootBoneNameHash = frameMesh.m_RootBoneNameHash; } else { sMesh.m_RootBone = new PPtr <Transform>((Component)null); } srcMesh = new Operations.vMesh(frameMeshR, true, false); CopyUnknowns(frameMeshR, sMesh); if (targetFullMesh && (normalsMethod == CopyMeshMethod.CopyNear || bonesMethod == CopyMeshMethod.CopyNear)) { allVertices = new List <vVertex>(); HashSet <Vector3> posSet = new HashSet <Vector3>(); foreach (vSubmesh submesh in srcMesh.submeshes) { allVertices.Capacity = allVertices.Count + submesh.vertexList.Count; foreach (vVertex vertex in submesh.vertexList) { if (!posSet.Contains(vertex.position)) { posSet.Add(vertex.position); allVertices.Add(vertex); } } } } } transform.Invert(); vSubmesh[] replaceSubmeshes = (srcMesh == null) ? null : new vSubmesh[srcMesh.submeshes.Count]; List <vSubmesh> addSubmeshes = new List <vSubmesh>(destMesh.submeshes.Count); for (int i = 0; i < destMesh.submeshes.Count; i++) { vSubmesh submesh = destMesh.submeshes[i]; List <vVertex> vVertexList = submesh.vertexList; if (worldCoords[i]) { for (int j = 0; j < vVertexList.Count; j++) { vVertexList[j].position = Vector3.TransformCoordinate(vVertexList[j].position, transform); } } vSubmesh baseSubmesh = null; int idx = indices[i]; if ((srcMesh != null) && (idx >= 0) && (idx < frameMesh.m_SubMeshes.Count)) { baseSubmesh = srcMesh.submeshes[idx]; CopyUnknowns(frameMesh.m_SubMeshes[idx], sMesh.m_Mesh.instance.m_SubMeshes[i]); } if (baseSubmesh != null) { if (normalsMethod == CopyMeshMethod.CopyOrder) { Operations.CopyNormalsOrder(baseSubmesh.vertexList, submesh.vertexList); } else if (normalsMethod == CopyMeshMethod.CopyNear) { Operations.CopyNormalsNear(targetFullMesh ? allVertices : baseSubmesh.vertexList, submesh.vertexList); } if (baseSubmesh.vertexList[0].weights != null) { if (bonesMethod == CopyMeshMethod.CopyOrder) { Operations.CopyBonesOrder(baseSubmesh.vertexList, submesh.vertexList); } else if (bonesMethod == CopyMeshMethod.CopyNear) { Operations.CopyBonesNear(targetFullMesh ? allVertices : baseSubmesh.vertexList, submesh.vertexList); } } } if ((baseSubmesh != null) && merge && replaceSubmeshesOption[i]) { replaceSubmeshes[idx] = submesh; } else { addSubmeshes.Add(submesh); } } if ((srcMesh != null) && merge) { destMesh.submeshes = new List <vSubmesh>(replaceSubmeshes.Length + addSubmeshes.Count); List <vSubmesh> copiedSubmeshes = new List <vSubmesh>(replaceSubmeshes.Length); for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] == null) { vSubmesh srcSubmesh = srcMesh.submeshes[i]; copiedSubmeshes.Add(srcSubmesh); destMesh.submeshes.Add(srcSubmesh); } else { destMesh.submeshes.Add(replaceSubmeshes[i]); } } destMesh.submeshes.AddRange(addSubmeshes); if ((sFrameMesh == null || sFrameMesh.m_Bones.Count == 0) && (sMesh.m_Bones.Count > 0)) { for (int i = 0; i < copiedSubmeshes.Count; i++) { List <vVertex> vertexList = copiedSubmeshes[i].vertexList; for (int j = 0; j < vertexList.Count; j++) { vertexList[j].boneIndices = new int[4] { 0, 0, 0, 0 }; vertexList[j].weights = new float[4] { 0, 0, 0, 0 }; } } } else if (sFrameMesh != null && sFrameMesh.m_Bones.Count > 0) { int[] boneIdxMap; sMesh.m_Bones = MergeBoneList(sFrameMesh.m_Bones, sMesh.m_Bones, out boneIdxMap); uint[] boneHashes = new uint[sMesh.m_Bones.Count]; Matrix[] poseMatrices = new Matrix[sMesh.m_Bones.Count]; for (int i = 0; i < sFrameMesh.m_Bones.Count; i++) { boneHashes[i] = sFrameMesh.m_Mesh.instance.m_BoneNameHashes[i]; poseMatrices[i] = sFrameMesh.m_Mesh.instance.m_BindPose[i]; } for (int i = 0; i < boneIdxMap.Length; i++) { boneHashes[boneIdxMap[i]] = sMesh.m_Mesh.instance.m_BoneNameHashes[i]; poseMatrices[boneIdxMap[i]] = sMesh.m_Mesh.instance.m_BindPose[i]; } sMesh.m_Mesh.instance.m_BoneNameHashes.Clear(); sMesh.m_Mesh.instance.m_BoneNameHashes.AddRange(boneHashes); sMesh.m_Mesh.instance.m_BindPose.Clear(); sMesh.m_Mesh.instance.m_BindPose.AddRange(poseMatrices); if (bonesMethod == CopyMeshMethod.Replace) { for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] != null) { List <vVertex> vertexList = replaceSubmeshes[i].vertexList; if (vertexList[0].boneIndices != null) { for (int j = 0; j < vertexList.Count; j++) { int[] boneIndices = vertexList[j].boneIndices; vertexList[j].boneIndices = new int[4]; for (int k = 0; k < 4; k++) { vertexList[j].boneIndices[k] = boneIdxMap[boneIndices[k]]; } } } } } for (int i = 0; i < addSubmeshes.Count; i++) { List <vVertex> vertexList = addSubmeshes[i].vertexList; if (vertexList[0].boneIndices != null) { for (int j = 0; j < vertexList.Count; j++) { int[] boneIndices = vertexList[j].boneIndices; vertexList[j].boneIndices = new int[4]; for (int k = 0; k < 4; k++) { vertexList[j].boneIndices[k] = boneIdxMap[boneIndices[k]]; } } } } } } } destMesh.Flush(); if (frameMeshR != null) { frame.m_GameObject.instance.RemoveLinkedComponent(frameMeshR); //parser.file.RemoveSubfile(frameMeshR); if (frameMesh != null) { //parser.file.RemoveSubfile(frameMesh); parser.file.ReplaceSubfile(frameMesh, sMesh.m_Mesh.asset); } parser.file.ReplaceSubfile(frameMeshR, sMesh); } frame.m_GameObject.instance.AddLinkedComponent(sMesh); AssetBundle bundle = parser.file.Bundle; if (bundle != null) { if (frameMeshR != null) { if (frameMesh != null) { bundle.ReplaceComponent(frameMesh, sMesh.m_Mesh.asset); } bundle.ReplaceComponent(frameMeshR, sMesh); } else { bundle.RegisterForUpdate(parser.m_GameObject.asset); } } }
public static void ReplaceMeshRenderer(Transform frame, Transform rootBone, Animator parser, List<Material> materials, WorkspaceMesh mesh, bool merge, CopyMeshMethod normalsMethod, CopyMeshMethod bonesMethod, bool targetFullMesh) { Matrix transform = Transform.WorldTransform(frame); int[] indices; bool[] worldCoords; bool[] replaceSubmeshesOption; SkinnedMeshRenderer sMesh = CreateSkinnedMeshRenderer(parser, materials, mesh, transform, out indices, out worldCoords, out replaceSubmeshesOption); vMesh destMesh = new Operations.vMesh(sMesh, true, false); SkinnedMeshRenderer sFrameMesh = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.SkinnedMeshRenderer); MeshRenderer frameMeshR = sFrameMesh; if (sFrameMesh == null) { frameMeshR = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.MeshRenderer); } Mesh frameMesh = frameMeshR != null ? Operations.GetMesh(frameMeshR) : null; vMesh srcMesh = null; List<vVertex> allVertices = null; if (frameMeshR == null || frameMesh == null) { sMesh.m_RootBone = new PPtr<Transform>(rootBone); if (rootBone != null) { sMesh.m_Mesh.instance.m_RootBoneNameHash = parser.m_Avatar.instance.BoneHash(rootBone.m_GameObject.instance.m_Name); } if (frameMeshR != null) { CopyUnknowns(frameMeshR, sMesh); } } else { if (sFrameMesh != null) { sMesh.m_RootBone = new PPtr<Transform>(sFrameMesh.m_RootBone.instance); sMesh.m_Mesh.instance.m_RootBoneNameHash = frameMesh.m_RootBoneNameHash; } else { sMesh.m_RootBone = new PPtr<Transform>((Component)null); } srcMesh = new Operations.vMesh(frameMeshR, true, false); CopyUnknowns(frameMeshR, sMesh); if (targetFullMesh && (normalsMethod == CopyMeshMethod.CopyNear || bonesMethod == CopyMeshMethod.CopyNear)) { allVertices = new List<vVertex>(); HashSet<Vector3> posSet = new HashSet<Vector3>(); foreach (vSubmesh submesh in srcMesh.submeshes) { allVertices.Capacity = allVertices.Count + submesh.vertexList.Count; foreach (vVertex vertex in submesh.vertexList) { if (!posSet.Contains(vertex.position)) { posSet.Add(vertex.position); allVertices.Add(vertex); } } } } } transform.Invert(); vSubmesh[] replaceSubmeshes = (srcMesh == null) ? null : new vSubmesh[srcMesh.submeshes.Count]; List<vSubmesh> addSubmeshes = new List<vSubmesh>(destMesh.submeshes.Count); for (int i = 0; i < destMesh.submeshes.Count; i++) { vSubmesh submesh = destMesh.submeshes[i]; List<vVertex> vVertexList = submesh.vertexList; if (worldCoords[i]) { for (int j = 0; j < vVertexList.Count; j++) { vVertexList[j].position = Vector3.TransformCoordinate(vVertexList[j].position, transform); } } vSubmesh baseSubmesh = null; int idx = indices[i]; if ((srcMesh != null) && (idx >= 0) && (idx < frameMesh.m_SubMeshes.Count)) { baseSubmesh = srcMesh.submeshes[idx]; CopyUnknowns(frameMesh.m_SubMeshes[idx], sMesh.m_Mesh.instance.m_SubMeshes[i]); } if (baseSubmesh != null) { if (normalsMethod == CopyMeshMethod.CopyOrder) { Operations.CopyNormalsOrder(baseSubmesh.vertexList, submesh.vertexList); } else if (normalsMethod == CopyMeshMethod.CopyNear) { Operations.CopyNormalsNear(targetFullMesh ? allVertices : baseSubmesh.vertexList, submesh.vertexList); } if (baseSubmesh.vertexList[0].weights != null) { if (bonesMethod == CopyMeshMethod.CopyOrder) { Operations.CopyBonesOrder(baseSubmesh.vertexList, submesh.vertexList); } else if (bonesMethod == CopyMeshMethod.CopyNear) { Operations.CopyBonesNear(targetFullMesh ? allVertices : baseSubmesh.vertexList, submesh.vertexList); } } } if ((baseSubmesh != null) && merge && replaceSubmeshesOption[i]) { replaceSubmeshes[idx] = submesh; } else { addSubmeshes.Add(submesh); } } if ((srcMesh != null) && merge) { destMesh.submeshes = new List<vSubmesh>(replaceSubmeshes.Length + addSubmeshes.Count); List<vSubmesh> copiedSubmeshes = new List<vSubmesh>(replaceSubmeshes.Length); for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] == null) { vSubmesh srcSubmesh = srcMesh.submeshes[i]; copiedSubmeshes.Add(srcSubmesh); destMesh.submeshes.Add(srcSubmesh); } else { destMesh.submeshes.Add(replaceSubmeshes[i]); } } destMesh.submeshes.AddRange(addSubmeshes); if ((sFrameMesh == null || sFrameMesh.m_Bones.Count == 0) && (sMesh.m_Bones.Count > 0)) { for (int i = 0; i < copiedSubmeshes.Count; i++) { List<vVertex> vertexList = copiedSubmeshes[i].vertexList; for (int j = 0; j < vertexList.Count; j++) { vertexList[j].boneIndices = new int[4] { 0, 0, 0, 0 }; vertexList[j].weights = new float[4] { 0, 0, 0, 0 }; } } } else if (sFrameMesh != null && sFrameMesh.m_Bones.Count > 0) { int[] boneIdxMap; sMesh.m_Bones = MergeBoneList(sFrameMesh.m_Bones, sMesh.m_Bones, out boneIdxMap); uint[] boneHashes = new uint[sMesh.m_Bones.Count]; Matrix[] poseMatrices = new Matrix[sMesh.m_Bones.Count]; for (int i = 0; i < sFrameMesh.m_Bones.Count; i++) { boneHashes[i] = sFrameMesh.m_Mesh.instance.m_BoneNameHashes[i]; poseMatrices[i] = sFrameMesh.m_Mesh.instance.m_BindPose[i]; } for (int i = 0; i < boneIdxMap.Length; i++) { boneHashes[boneIdxMap[i]] = sMesh.m_Mesh.instance.m_BoneNameHashes[i]; poseMatrices[boneIdxMap[i]] = sMesh.m_Mesh.instance.m_BindPose[i]; } sMesh.m_Mesh.instance.m_BoneNameHashes.Clear(); sMesh.m_Mesh.instance.m_BoneNameHashes.AddRange(boneHashes); sMesh.m_Mesh.instance.m_BindPose.Clear(); sMesh.m_Mesh.instance.m_BindPose.AddRange(poseMatrices); if (bonesMethod == CopyMeshMethod.Replace) { for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] != null) { List<vVertex> vertexList = replaceSubmeshes[i].vertexList; if (vertexList[0].boneIndices != null) { for (int j = 0; j < vertexList.Count; j++) { int[] boneIndices = vertexList[j].boneIndices; vertexList[j].boneIndices = new int[4]; for (int k = 0; k < 4; k++) { vertexList[j].boneIndices[k] = boneIdxMap[boneIndices[k]]; } } } } } for (int i = 0; i < addSubmeshes.Count; i++) { List<vVertex> vertexList = addSubmeshes[i].vertexList; if (vertexList[0].boneIndices != null) { for (int j = 0; j < vertexList.Count; j++) { int[] boneIndices = vertexList[j].boneIndices; vertexList[j].boneIndices = new int[4]; for (int k = 0; k < 4; k++) { vertexList[j].boneIndices[k] = boneIdxMap[boneIndices[k]]; } } } } } } } destMesh.Flush(); if (frameMeshR != null) { frame.m_GameObject.instance.RemoveLinkedComponent(frameMeshR); //parser.file.RemoveSubfile(frameMeshR); if (frameMesh != null) { //parser.file.RemoveSubfile(frameMesh); parser.file.ReplaceSubfile(frameMesh, sMesh.m_Mesh.asset); } parser.file.ReplaceSubfile(frameMeshR, sMesh); } frame.m_GameObject.instance.AddLinkedComponent(sMesh); AssetBundle bundle = parser.file.Bundle; if (bundle != null) { if (frameMeshR != null) { if (frameMesh != null) { bundle.ReplaceComponent(frameMesh, sMesh.m_Mesh.asset); } bundle.ReplaceComponent(frameMeshR, sMesh); } else { bundle.RegisterForUpdate(parser.m_GameObject.asset); } } }
public void RemoveSubMesh(int meshId, int subMeshId) { MeshRenderer meshR = Meshes[meshId]; Mesh mesh = Operations.GetMesh(meshR); if (mesh.m_SubMeshes.Count == 1 && subMeshId == 0) { Operations.SetMeshPtr(meshR, null); Parser.file.RemoveSubfile(mesh); if (Parser.file.Bundle != null) { Parser.file.Bundle.DeleteComponent(mesh); } } else { Operations.vMesh vMesh = new Operations.vMesh(meshR, true, false); vMesh.submeshes.RemoveAt(subMeshId); vMesh.Flush(); } if (Parser.file.Bundle != null) { Parser.file.Bundle.RegisterForUpdate(meshR); } Changed = true; }
public void RemoveBone(int meshId, int boneId) { SkinnedMeshRenderer smr = (SkinnedMeshRenderer)Meshes[meshId]; Mesh mesh = smr.m_Mesh.instance; if (mesh != null) { Operations.vMesh vMesh = new Operations.vMesh(smr, false, false); Transform boneFrame = smr.m_Bones[boneId].instance; int parentBoneIdx = -1; if (boneFrame != null) { Transform parentFrame = boneFrame.Parent; parentBoneIdx = Operations.FindBoneIndex(smr.m_Bones, parentFrame); } smr.m_Bones.RemoveAt(boneId); mesh.m_BindPose.RemoveAt(boneId); mesh.m_BoneNameHashes.RemoveAt(boneId); foreach (Operations.vSubmesh submesh in vMesh.submeshes) { foreach (Operations.vVertex vertex in submesh.vertexList) { for (int i = 0; i < vertex.boneIndices.Length; i++) { int boneIdx = vertex.boneIndices[i]; if (boneIdx == boneId) { float[] w4 = vertex.weights; for (int j = i + 1; j < vertex.boneIndices.Length; j++) { vertex.boneIndices[j - 1] = vertex.boneIndices[j]; vertex.weights[j - 1] = w4[j]; } vertex.boneIndices[vertex.boneIndices.Length - 1] = -1; w4 = vertex.weights; float normalize = 1f / (w4[0] + w4[1] + w4[2] + w4[3]); if (w4[3] != 1f) { for (int j = 0; vertex.boneIndices[j] != -1; j++) { vertex.weights[j] *= normalize; } } else if (parentBoneIdx >= 0) { vertex.boneIndices[0] = parentBoneIdx; vertex.weights[0] = 1f; } i--; } else if (boneIdx != -1 && boneIdx > boneId) { vertex.boneIndices[i]--; } } } } vMesh.Flush(); } }
public void MirrorV(int meshId) { MeshRenderer meshR = Meshes[meshId]; Operations.vMesh vMesh = new Operations.vMesh(meshR, true, false); foreach (Operations.vSubmesh submesh in vMesh.submeshes) { foreach (Operations.vVertex vert in submesh.vertexList) { vert.uv.Y *= -1; } } vMesh.Flush(); Changed = true; }
public void CalculateTangents(int id) { MeshRenderer meshR = Meshes[id]; Operations.vMesh vMesh = new Operations.vMesh(meshR, true, false); Operations.CalculateTangents(vMesh.submeshes); Changed = true; }
public void CalculateNormals(int id, double threshold) { MeshRenderer meshR = Meshes[id]; Operations.vMesh vMesh = new Operations.vMesh(meshR, true, false); Operations.CalculateNormals(vMesh.submeshes, (float)threshold); Changed = true; }
private static void ConvertMeshArgs(object[] editors, object[] numMeshes, object[] meshes, List<Operations.vMesh> meshList, List<Operations.vSubmesh> submeshList) { AnimatorEditor editor = null; int editorIdx = -1; int i = 1; foreach (object id in meshes) { if (--i == 0) { editorIdx++; i = (int)(double)numMeshes[editorIdx]; editor = (AnimatorEditor)editors[editorIdx]; } MeshRenderer meshR = editor.Meshes[(int)(double)id]; Operations.vMesh vMesh = new Operations.vMesh(meshR, true, false); meshList.Add(vMesh); submeshList.AddRange(vMesh.submeshes); } }