public static BoneWeight Create() { BoneWeight boneWeight = new BoneWeight(); boneWeight.boneIndex0 = -1; boneWeight.boneIndex1 = -1; boneWeight.boneIndex2 = -1; boneWeight.boneIndex3 = -1; return boneWeight; }
BoneWeight[] EntryBoneWeights(PMD.PMDFormat format) { int vcount = (int)format.vertex_list.vert_count; BoneWeight[] weights = new BoneWeight[vcount]; for (int i = 0; i < vcount; i++) { weights[i].boneIndex0 = (int)format.vertex_list.vertex[i].bone_num[0]; weights[i].boneIndex1 = (int)format.vertex_list.vertex[i].bone_num[1]; weights[i].weight0 = format.vertex_list.vertex[i].bone_weight; weights[i].weight1 = 100 - format.vertex_list.vertex[i].bone_weight; } return weights; }
public static BoneWeight Weight(BoneWeight boneWeight,int weightIndex, string[] names, bool mixedBoneIndex = false, bool mixedWeight = false) { int boneIndex = 0; float weight = 0f; boneWeight.GetWeight(weightIndex,out boneIndex,out weight); EditorGUIUtility.labelWidth = 30f; EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = mixedBoneIndex; int newBoneIndex = EditorGUILayout.Popup(boneIndex + 1,names,GUILayout.Width(100f)) - 1; EditorGUI.BeginDisabledGroup(newBoneIndex == -1); EditorGUI.showMixedValue = mixedWeight; weight = EditorGUILayout.Slider(weight,0f,1f); EditorGUI.EndDisabledGroup(); EditorGUILayout.EndHorizontal(); if(EditorGUI.EndChangeCheck()) { if(newBoneIndex == -1) { boneWeight.Unassign(boneIndex); } boneWeight.SetWeight(weightIndex,newBoneIndex,weight); } return boneWeight; }
// This is for editing control points void OnSceneGUI() { if (Weightpainter.isPainting) { if (skin != null) { skin.editingPoints = false; } return; } // If we have a skin and control points then update them if (skin != null && skinnedMeshRenderer != null && skinnedMesh != null && skin.controlPoints != null && skin.controlPoints.Length > 0 && skin.points != null) { e = Event.current; EditorGUI.BeginChangeCheck(); r = HandleUtility.GUIPointToWorldRay(e.mousePosition); mousePos = r.origin; selectDistance = HandleUtility.GetHandleSize(mousePos) * baseSelectDistance; // Create the vertices here for the handle points if (!skin.editingPoints) { bakeMesh = new Mesh(); #if UNITY_2020_2_OR_NEWER skinnedMeshRenderer.BakeMesh(bakeMesh, true); #else skinnedMeshRenderer.BakeMesh(bakeMesh); #endif skinnedMesh = skinnedMeshRenderer.sharedMesh; // Always clear vertices before getting new ones #if UNITY_2020_1_OR_NEWER using (var dataArray = Mesh.AcquireReadOnlyMeshData(bakeMesh)) { var data = dataArray[0]; if (vertices == null || vertices != null && vertices.Length != bakeMesh.vertexCount) { if (vertices.IsCreated) { vertices.Dispose(); } vertices = new NativeArray <Vector3>(bakeMesh.vertexCount, Allocator.Persistent); } data.GetVertices(vertices); } #else if (vertices != null && vertices.IsCreated) { vertices.Dispose(); } vertices = new NativeArray <Vector3>(bakeMesh.vertices, Allocator.Persistent); #endif boneMatrices = new Matrix4x4[skinnedMeshRenderer.bones.Length]; weights = skinnedMesh.boneWeights; bindposes = skinnedMesh.bindposes; bones = skinnedMeshRenderer.bones; // First apply the scale, then transform it to World Space for (int i = 0; i < bakeMesh.vertexCount; i++) { #if !UNITY_2020_2_OR_NEWER vertices[i] = Vector3.Scale(bakeMesh.vertices[i], skinnedMeshRenderer.transform.lossyScale); #endif vertices[i] = skinnedMeshRenderer.transform.TransformPoint(vertices[i]); } // Always clear vertices before getting new ones #if UNITY_2020_1_OR_NEWER using (var dataArray = Mesh.AcquireReadOnlyMeshData(skinnedMesh)) { var data = dataArray[0]; if (newVertices == null || newVertices != null && newVertices.Length != skinnedMesh.vertexCount) { if (newVertices.IsCreated) { newVertices.Dispose(); } newVertices = new NativeArray <Vector3>(skinnedMesh.vertexCount, Allocator.Persistent); } data.GetVertices(newVertices); } #else if (newVertices != null && newVertices.IsCreated) { newVertices.Dispose(); } newVertices = new NativeArray <Vector3>(skinnedMesh.vertices, Allocator.Persistent); #endif // Debug.Log("Created new baked mesh."); } if (e.type == EventType.MouseDrag && e.button == 0 && e.isMouse) { /*if (!skin.editingPoints) { * Debug.Log("Started editing points"); * }*/ skin.editingPoints = true; } else if (e.type == EventType.MouseUp || vertices.Length != skinnedMeshRenderer.sharedMesh.vertexCount) { skin.editingPoints = false; // Debug.Log("Stopped editing points"); } #region Draw vertex handles Handles.color = handleColor; for (int i = 0; i < skin.controlPoints.Length; i++) { if (Handles.Button(vertices[i], Quaternion.identity, selectDistance, selectDistance, Handles.CircleHandleCap)) { selectedIndex = i; } if (selectedIndex == i) { EditorGUI.BeginChangeCheck(); // If we are editing points then the position handle drives the vertex if (skin.editingPoints) { vertices[i] = Handles.PositionHandle(vertices[i], Quaternion.identity); // Need to create matrices based on the skin's bones for (int b = 0; b < boneMatrices.Length; b++) { if (bones[b] != null) { boneMatrices[b] = bones[b].localToWorldMatrix * bindposes[b]; } } weight = weights[i]; vertexMatrix = new Matrix4x4(); // Since we are only using 2 bones for the Skin2D, only use the first 2 bones and weights for (int n = 0; n < 16; n++) { vertexMatrix[n] = boneMatrices[weight.boneIndex0][n] * weight.weight0 + boneMatrices[weight.boneIndex1][n] * weight.weight1; } // DEBUG HERE TO CHECK FOR DISCREPANCIES // /*Vector3 debugVert = vertexMatrix.MultiplyPoint(skinnedMesh.vertices[i]); * * Debug.Log("New Vertex: " + debugVert.x + ", " + debugVert.y + ", " + debugVert.z); * Debug.Log("Original Vertex: " + vertices[i].x + ", " + vertices[i].y + ", " + vertices[i].z); * * Handles.DotHandleCap( * i, * debugVert, * Quaternion.identity, * selectDistance, * EventType.Repaint * );*/ // Invert the matrix to get the local space position of the vertex newVert = vertexMatrix.inverse.MultiplyPoint(vertices[i]); skin.controlPoints[i].position = newVert; skin.points.SetPoint(skin.controlPoints[i]); newVertices[i] = skin.points.GetPoint(skin.controlPoints[i]); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(skin, "Changed Control Point"); Undo.RecordObject(skin.points, "Changed Control Point"); EditorUtility.SetDirty(this); } } else { currentControlPoint = skin.points.GetPoint(skin.controlPoints[i]); // If we are not editing points then just use the world space offset for the position handle offset = vertices[i] - skin.transform.TransformPoint(currentControlPoint); vertices[i] = Handles.PositionHandle(skin.transform.TransformPoint(currentControlPoint) + offset, Quaternion.identity); // Debug.Log("Not editing points."); } } } if (skin.editingPoints) { skinnedMeshRenderer.sharedMesh.SetVertices(newVertices); skin.UpdateControlPoints(); // Debug.Log("Set new vertices"); } #endregion } else { skin.editingPoints = false; } }
void InitializeBuffers() { argBuffer = new ComputeBuffer(1, sizeof(uint) * 5, ComputeBufferType.IndirectArguments); uint[] args = new uint[] { model.GetIndexCount(0), (uint)inXforms.Length, 0, 0, 0 }; argBuffer.SetData(args); hierarchyBuf = new ComputeBuffer(hierarchy.Count, sizeof(int)); hierarchyBuf.SetData(hierarchy.ToArray()); jointDataBuf = new ComputeBuffer(numJoints, sizeof(int) * 21 + sizeof(float) * 32); jointDataBuf.SetData(jointData); tXBuf = new ComputeBuffer(keyframes[0].Count, sizeof(float) * 2); tXBuf.SetData(keyframes[0].ToArray()); tYBuf = new ComputeBuffer(keyframes[1].Count, sizeof(float) * 2); tYBuf.SetData(keyframes[1].ToArray()); tZBuf = new ComputeBuffer(keyframes[2].Count, sizeof(float) * 2); tZBuf.SetData(keyframes[2].ToArray()); rXBuf = new ComputeBuffer(keyframes[3].Count, sizeof(float) * 2); rXBuf.SetData(keyframes[3].ToArray()); rYBuf = new ComputeBuffer(keyframes[4].Count, sizeof(float) * 2); rYBuf.SetData(keyframes[4].ToArray()); rZBuf = new ComputeBuffer(keyframes[5].Count, sizeof(float) * 2); rZBuf.SetData(keyframes[5].ToArray()); rWBuf = new ComputeBuffer(keyframes[6].Count, sizeof(float) * 2); rWBuf.SetData(keyframes[6].ToArray()); sXBuf = new ComputeBuffer(keyframes[7].Count, sizeof(float) * 2); sXBuf.SetData(keyframes[7].ToArray()); sYBuf = new ComputeBuffer(keyframes[8].Count, sizeof(float) * 2); sYBuf.SetData(keyframes[8].ToArray()); sZBuf = new ComputeBuffer(keyframes[9].Count, sizeof(float) * 2); sZBuf.SetData(keyframes[9].ToArray()); xforms = model.bindposes; xformBuf = new ComputeBuffer(numJoints, sizeof(float) * 16); xformBuf.SetData(xforms); instanceXBuf.SetData(inXforms); int kid = jointComputer.FindKernel("CalculateTransforms"); jointComputer.SetBuffer(kid, "hierarchyBuf", hierarchyBuf); jointComputer.SetBuffer(kid, "jointBuf", jointDataBuf); jointComputer.SetBuffer(kid, "tXBuf", tXBuf); jointComputer.SetBuffer(kid, "tYBuf", tYBuf); jointComputer.SetBuffer(kid, "tZBuf", tZBuf); jointComputer.SetBuffer(kid, "rXBuf", rXBuf); jointComputer.SetBuffer(kid, "rYBuf", rYBuf); jointComputer.SetBuffer(kid, "rZBuf", rZBuf); jointComputer.SetBuffer(kid, "rWBuf", rWBuf); jointComputer.SetBuffer(kid, "sXBuf", sXBuf); jointComputer.SetBuffer(kid, "sYBuf", sYBuf); jointComputer.SetBuffer(kid, "sZBuf", sZBuf); jointComputer.SetBuffer(kid, "xformBuf", xformBuf); jointComputer.SetInt("numJoints", numJoints); modelMat.SetBuffer("xforms", xformBuf); modelMat.SetBuffer("instanceXforms", instanceXBuf); var wghts = model.boneWeights; Vector4[] boneIndices = new Vector4[wghts.Length]; Vector4[] boneWeights = new Vector4[wghts.Length]; for (int i = 0; i < wghts.Length; i++) { BoneWeight w = wghts[i]; boneIndices[i] = new Vector4(w.boneIndex0, w.boneIndex1, w.boneIndex2, w.boneIndex3); boneWeights[i] = new Vector4(w.weight0, w.weight1, w.weight2, w.weight3); } boneIdxBuf = new ComputeBuffer(wghts.Length, sizeof(float) * 4); boneWeightBuf = new ComputeBuffer(wghts.Length, sizeof(float) * 4); boneIdxBuf.SetData(boneIndices); boneWeightBuf.SetData(boneWeights); modelMat.SetBuffer("weights", boneWeightBuf); modelMat.SetBuffer("boneIndices", boneIdxBuf); jointComputer.SetInt("numJoints", numJoints); //jointComputer.SetBuffer(kid, "debugBuf", debugBuf); }
private bool InitializeGPUSkinDeform() { bool succeeded = true; try { m_gpuBoneTexWidth = Mathf.NextPowerOfTwo(m_boneCount); m_gpuBoneTexHeight = 4; m_gpuVertexTexWidth = Mathf.NextPowerOfTwo(Mathf.CeilToInt(Mathf.Sqrt(m_vertexCount))); m_gpuVertexTexHeight = Mathf.NextPowerOfTwo(m_vertexCount / m_gpuVertexTexWidth); // gpu skin deform material m_gpuSkinDeformMat = new Material(Shader.Find("Hidden/Amplify Motion/GPUSkinDeform")) { hideFlags = HideFlags.DontSave }; // bone matrix texture m_gpuBones = new Texture2D(m_gpuBoneTexWidth, m_gpuBoneTexHeight, TextureFormat.RGBAFloat, false, true); m_gpuBones.filterMode = FilterMode.Point; m_gpuBoneData = new Color[m_gpuBoneTexWidth * m_gpuBoneTexHeight]; UpdateBonesGPU(); // vertex bone index/weight textures TextureFormat boneIDWFormat = TextureFormat.RHalf; boneIDWFormat = (m_weightCount == 2) ? TextureFormat.RGHalf : boneIDWFormat; boneIDWFormat = (m_weightCount == 4) ? TextureFormat.RGBAHalf : boneIDWFormat; m_gpuBoneIndices = new Texture2D(m_gpuVertexTexWidth, m_gpuVertexTexHeight, boneIDWFormat, false, true); m_gpuBoneIndices.filterMode = FilterMode.Point; m_gpuBoneIndices.wrapMode = TextureWrapMode.Clamp; BoneWeight[] meshBoneWeights = m_renderer.sharedMesh.boneWeights; Color[] boneIndices = new Color[m_gpuVertexTexWidth * m_gpuVertexTexHeight]; for (int v = 0; v < m_vertexCount; v++) { int x = v % m_gpuVertexTexWidth; int y = v / m_gpuVertexTexWidth; int offset = y * m_gpuVertexTexWidth + x; BoneWeight boneWeight = meshBoneWeights[v]; boneIndices[offset] = new Vector4(boneWeight.boneIndex0, boneWeight.boneIndex1, boneWeight.boneIndex2, boneWeight.boneIndex3); } m_gpuBoneIndices.SetPixels(boneIndices); m_gpuBoneIndices.Apply(); // base vertex textures m_gpuBaseVertices = new Texture2D[m_weightCount]; for (int w = 0; w < m_weightCount; w++) { m_gpuBaseVertices[w] = new Texture2D(m_gpuVertexTexWidth, m_gpuVertexTexHeight, TextureFormat.RGBAFloat, false, true); m_gpuBaseVertices[w].filterMode = FilterMode.Point; } List <Color[]> baseVertices = new List <Color[]>(m_weightCount); for (int w = 0; w < m_weightCount; w++) { baseVertices.Add(new Color[m_gpuVertexTexWidth * m_gpuVertexTexHeight]); } for (int v = 0; v < m_vertexCount; v++) { int x = v % m_gpuVertexTexWidth; int y = v / m_gpuVertexTexWidth; int offset = y * m_gpuVertexTexWidth + x; for (int w = 0; w < m_weightCount; w++) { baseVertices[w][offset] = m_baseVertices[v * m_weightCount + w]; } } for (int w = 0; w < m_weightCount; w++) { m_gpuBaseVertices[w].SetPixels(baseVertices[w]); m_gpuBaseVertices[w].Apply(); } // create output/target vertex render textures m_gpuPrevVertices = new RenderTexture(m_gpuVertexTexWidth, m_gpuVertexTexHeight, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); m_gpuPrevVertices.filterMode = FilterMode.Point; m_gpuPrevVertices.wrapMode = TextureWrapMode.Clamp; m_gpuPrevVertices.Create(); m_gpuCurrVertices = new RenderTexture(m_gpuVertexTexWidth, m_gpuVertexTexHeight, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); m_gpuCurrVertices.filterMode = FilterMode.Point; m_gpuCurrVertices.wrapMode = TextureWrapMode.Clamp; m_gpuCurrVertices.Create(); // assign local material constants m_gpuSkinDeformMat.SetTexture("_AM_BONE_TEX", m_gpuBones); m_gpuSkinDeformMat.SetTexture("_AM_BONE_INDEX_TEX", m_gpuBoneIndices); for (int w = 0; w < m_weightCount; w++) { m_gpuSkinDeformMat.SetTexture("_AM_BASE_VERTEX" + w + "_TEX", m_gpuBaseVertices[w]); } // assign global shader constants Vector4 boneTexelSize = new Vector4(1.0f / m_gpuBoneTexWidth, 1.0f / m_gpuBoneTexHeight, m_gpuBoneTexWidth, m_gpuBoneTexHeight); Vector4 vertexTexelSize = new Vector4(1.0f / m_gpuVertexTexWidth, 1.0f / m_gpuVertexTexHeight, m_gpuVertexTexWidth, m_gpuVertexTexHeight); m_gpuSkinDeformMat.SetVector("_AM_BONE_TEXEL_SIZE", boneTexelSize); m_gpuSkinDeformMat.SetVector("_AM_BONE_TEXEL_HALFSIZE", boneTexelSize * 0.5f); m_gpuSkinDeformMat.SetVector("_AM_VERTEX_TEXEL_SIZE", vertexTexelSize); m_gpuSkinDeformMat.SetVector("_AM_VERTEX_TEXEL_HALFSIZE", vertexTexelSize * 0.5f); // assign vertex x/y offsets packed into second uv channel Vector2[] indexCoords = new Vector2[m_vertexCount]; for (int v = 0; v < m_vertexCount; v++) { int x = v % m_gpuVertexTexWidth; int y = v / m_gpuVertexTexWidth; float x_norm = (x / ( float )m_gpuVertexTexWidth) + vertexTexelSize.x * 0.5f; float y_norm = (y / ( float )m_gpuVertexTexHeight) + vertexTexelSize.y * 0.5f; indexCoords[v] = new Vector2(x_norm, y_norm); } m_clonedMesh.uv2 = indexCoords; } catch (Exception) { succeeded = false; } return(succeeded); }
// multiple submMesh is not sharing a VertexBuffer. // each subMesh use a independent VertexBuffer. private static MeshContext _ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { //Debug.LogWarning("_ImportMeshIndependentVertexBuffer"); var targets = gltfMesh.primitives[0].targets; for (int i = 1; i < gltfMesh.primitives.Count; ++i) { if (!gltfMesh.primitives[i].targets.SequenceEqual(targets)) { throw new NotImplementedException(string.Format("diffirent targets: {0} with {1}", gltfMesh.primitives[i], targets)); } } var positions = new List <Vector3>(); var normals = new List <Vector3>(); var tangents = new List <Vector4>(); var uv = new List <Vector2>(); var colors = new List <Color>(); var meshContext = new MeshContext(); foreach (var prim in gltfMesh.primitives) { var indexOffset = positions.Count; var indexBuffer = prim.indices; var positionCount = positions.Count; positions.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).Select(x => x.ReverseZ())); positionCount = positions.Count - positionCount; // normal if (prim.attributes.NORMAL != -1) { normals.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).Select(x => x.ReverseZ())); } if (prim.attributes.TANGENT != -1) { tangents.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).Select(x => x.ReverseZ())); } // uv if (prim.attributes.TEXCOORD_0 != -1) { uv.AddRange(ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).Select(x => x.ReverseY())); } else { // for inconsistent attributes in primitives uv.AddRange(new Vector2[positionCount]); } // color if (prim.attributes.COLOR_0 != -1) { colors.AddRange(ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0)); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray(); for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; meshContext.boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = new BlendShape(!string.IsNullOrEmpty(prim.extras.targetNames[i]) ? prim.extras.targetNames[i] : i.ToString()) ; if (primTarget.POSITION != -1) { blendShape.Positions.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.NORMAL != -1) { blendShape.Normals.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL).Select(x => x.ReverseZ()).ToArray()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.AddRange( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT).Select(x => x.ReverseZ()).ToArray()); } meshContext.blendShapes.Add(blendShape); } } var indices = (indexBuffer >= 0) ? ctx.GLTF.GetIndices(indexBuffer) : TriangleUtil.FlipTriangle(Enumerable.Range(0, meshContext.positions.Length)).ToArray() // without index array ; for (int i = 0; i < indices.Length; ++i) { indices[i] += indexOffset; } meshContext.subMeshes.Add(indices); // material meshContext.materialIndices.Add(prim.material); } meshContext.positions = positions.ToArray(); meshContext.normals = normals.ToArray(); meshContext.tangents = tangents.ToArray(); meshContext.uv = uv.ToArray(); return(meshContext); }
public void OnSceneGUI(SceneView sceneView) { if (skin != null && isPainting) { HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive)); Mesh m = skin.sharedMesh.Clone(); m.colors = CalculateVertexColors(skin.bones, m, skin.bones[boneIndex].GetComponent <Bone>()); List <BoneWeight> weights = m.boneWeights.ToList(); Event current = Event.current; Graphics.DrawMeshNow(m, skin.transform.position, skin.transform.rotation); Bone bn = skin.bones[boneIndex].GetComponent <Bone>(); foreach (Bone b in skin.GetComponentsInChildren <Bone>()) { if (bn == b) { Handles.color = Color.yellow; } else { Handles.color = Color.gray; } Handles.DrawLine(b.transform.position, b.Head); } Handles.color = Color.red; Vector3 mpos = HandleUtility.GUIPointToWorldRay(current.mousePosition).origin; mpos = new Vector3(mpos.x, mpos.y); Handles.DrawWireDisc(mpos, Vector3.forward, brushSize); if (isPainting) { if (current.type == EventType.scrollWheel && current.modifiers == EventModifiers.Control) { brushSize = Mathf.Clamp(brushSize + (float)System.Math.Round(current.delta.y / 30, 2), 0, float.MaxValue); Repaint(); current.Use(); } else if (current.type == EventType.mouseDown && current.button == 0) { isDrawing = true; } else if (current.type == EventType.mouseUp && current.button == 0) { isDrawing = false; } else if (current.type == EventType.mouseDrag && isDrawing && current.button == 0) { float w = weight * ((mode == PaintingMode.Subtract) ? -1 : 1); for (int i = 0; i < m.vertices.Length; i++) { Vector3 v = m.vertices[i]; float d = (v - skin.gameObject.transform.InverseTransformPoint(mpos)).magnitude; if (d <= brushSize) { BoneWeight bw = weights[i]; float vw = bw.GetWeight(boneIndex); vw = Mathf.Clamp(vw + (1 - d / brushSize) * w, 0, 1); bw = bw.SetWeight(boneIndex, vw); weights[i] = bw.Clone(); } } skin.sharedMesh.boneWeights = weights.ToArray(); EditorUtility.SetDirty(skin.gameObject); if (PrefabUtility.GetPrefabType(skin.gameObject) != PrefabType.None) { AssetDatabase.SaveAssets(); } } } sceneView.Repaint(); } }
public Mesh LoadFromStream(EndianBinaryReader reader) { MeshVertexAttributeHolder vertexData = null; SceneNode rootNode = new SceneNode(); List <Texture2D> textureList = new List <Texture2D>(); List <WEditor.Common.Nintendo.J3D.Material> materialList = null; List <SkeletonBone> joints = new List <SkeletonBone>(); DrawInfo drawInfo = null; Envelopes envelopes = null; Mesh j3dMesh = new Mesh(); // Read the Header int magic = reader.ReadInt32(); // J3D1, J3D2, etc if (magic != 1244873778) { WLog.Warning(LogCategory.ModelLoading, null, "Attempted to load model with invalid magic, ignoring!"); return(null); } int j3dType = reader.ReadInt32(); // BMD3 (models) BDL4 (models), jpa1 (particles), bck1 (animations), etc. int totalFileSize = reader.ReadInt32(); int chunkCount = reader.ReadInt32(); // Skip over an unused tag (consistent in all files) and some padding. reader.ReadBytes(16); for (int i = 0; i < chunkCount; i++) { long chunkStart = reader.BaseStream.Position; string tagName = reader.ReadString(4); int chunkSize = reader.ReadInt32(); switch (tagName) { // INFO - Vertex Count, Scene Hierarchy case "INF1": rootNode = LoadINF1FromFile(rootNode, reader, chunkStart); break; // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc. Contains VertexAttributes which describe // how this data is stored/laid out. case "VTX1": vertexData = LoadVTX1FromFile(reader, chunkStart, chunkSize); break; // ENVELOPES - Defines vertex weights for skinning. case "EVP1": envelopes = LoadEVP1FromStream(reader, chunkStart); break; // DRAW (Skeletal Animation Data) - Stores which matrices are weighted, and which are used directly. case "DRW1": drawInfo = LoadDRW1FromStream(reader, chunkStart); break; // JOINTS - Stores the skeletal joints (position, rotation, scale, etc.) case "JNT1": joints = LoadJNT1SectionFromStream(reader, chunkStart); break; // SHAPE - Face/Triangle information for model. case "SHP1": LoadSHP1SectionFromFile(vertexData, j3dMesh, reader, chunkStart); break; // MATERIAL - Stores materials (which describes how textures, etc. are drawn) case "MAT3": materialList = LoadMAT3SectionFromStream(reader, chunkStart, chunkSize); break; // TEXTURES - Stores binary texture images. case "TEX1": textureList = LoadTEX1FromFile(reader, chunkStart); break; // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly. case "MDL3": break; } reader.BaseStream.Position = chunkStart + chunkSize; } // Resolve the texture indexes into actual textures now that we've loaded the TEX1 section. foreach (Material mat in materialList) { for (int i = 0; i < mat.TextureIndexes.Length; i++) { short index = mat.TextureIndexes[i]; if (index < 0) { continue; } mat.Textures[i] = textureList[index]; } } // loltests for (int i = 0; i < materialList.Count; i++) { materialList[i].VtxDesc = j3dMesh.SubMeshes[0].GetVertexDescription(); Shader shader = TEVShaderGenerator.GenerateShader(materialList[i]); materialList[i].Shader = shader; } // We're going to do something a little crazy - we're going to read the scene view and apply textures to meshes (for now) Material curMat = null; AssignMaterialsToMeshRecursive(rootNode, j3dMesh, ref curMat, materialList); List <SkeletonBone> skeleton = new List <SkeletonBone>(); BuildSkeletonRecursive(rootNode, skeleton, joints, 0); j3dMesh.Skeleton = skeleton; j3dMesh.BindPoses = envelopes.inverseBindPose; // Let's do some ugly post-processing here to see if we can't resolve all of the cross-references and turn it into // a normal computer-readable format that we can digest in our RenderSytem. { for (int i = 0; i < j3dMesh.SubMeshes.Count; i++) { MeshBatch batch = j3dMesh.SubMeshes[i]; batch.BoneWeights = new BoneWeight[batch.Vertices.Length]; for (int j = 0; j < batch.PositionMatrixIndexs.Count; j++) { // Okay so this is where it gets more complicated. The PMI gives us an index into the MatrixTable for the packet, which we // resolve and call "drawIndexes" - however we have to divide the number they give us by three for some reason, so that is // already done and now our drawIndexes array should be one-index-for-every-vertex-in-batch and it should be the index into // the draw section we need. ushort drw1Index = batch.drawIndexes[j]; // The drw1Index can be set as 0xFFFF - if so, this means that you need to use the dr1Index of the previous one. // until it is no longer 0xFFFF. int counter = 0; while (drw1Index == 0xFFFF) { drw1Index = batch.drawIndexes[j - counter]; counter++; } bool isWeighted = drawInfo.IsWeighted[drw1Index]; BoneWeight weight = new BoneWeight(); if (isWeighted) { // Something on this doesn't work for models that actually specify a PositionMatrixIndex. // So... some math is off somewhere and I don't know where for the moment. ushort numBonesAffecting = envelopes.numBonesAffecting[drw1Index]; weight.BoneIndexes = new ushort[numBonesAffecting]; weight.BoneWeights = new float[numBonesAffecting]; // "Much WTFs" ushort offset = 0; for (ushort e = 0; e < envelopes.indexRemap[drw1Index]; e++) { offset += envelopes.numBonesAffecting[e]; } offset *= 2; Matrix4 finalTransform = Matrix4.Identity; for (ushort k = 0; k < numBonesAffecting; k++) { ushort boneIndex = envelopes.indexRemap[offset + (k * 0x2)]; float boneWeight = envelopes.weights[(offset / 2) + k]; weight.BoneIndexes[k] = boneIndex; weight.BoneWeights[k] = boneWeight; // This was apaprently a partial thought I never finished or got working in the old one? :S } } else { // If the vertex isn't weighted, we just use the position from the bone matrix. SkeletonBone joint = skeleton[drawInfo.Indexes[drw1Index]]; Matrix4 translation = Matrix4.CreateTranslation(joint.Translation); Matrix4 rotation = Matrix4.CreateFromQuaternion(joint.Rotation); Matrix4 finalMatrix = rotation * translation; // Move the mesh by transforming the position by this much. // I think we can just assign full weight to the first bone index and call it good. weight.BoneIndexes = new[] { drawInfo.Indexes[drw1Index] }; weight.BoneWeights = new[] { 1f }; } batch.BoneWeights[j] = weight; } } } return(j3dMesh); }
static void ShowSpriteMesh(TextureFrame frame, Material mat, DragonBoneData.SkinSlotDisplayData displayData, Transform slot, ArmatureEditor armatureEditor, DragonBoneData.SlotData slotData) { armatureEditor.spriteMeshUsedMatKV[mat] = true; GameObject go = new GameObject(displayData.textureName); SpriteMesh sm = go.AddComponent <SpriteMesh>(); sm.atlasMat = mat; sm.vertices = displayData.vertices; sm.frame = frame; sm.uvs = displayData.uvs; sm.triangles = displayData.triangles; sm.colors = new Color[sm.vertices.Length]; for (int i = 0; i < sm.colors.Length; ++i) { sm.colors[i] = Color.white; } if (displayData.weights != null && displayData.weights.Length > 0) { sm.CreateMesh(true); if (armatureEditor.ffdKV.ContainsKey(displayData.textureName)) { //Vertex controller sm.vertControlTrans = new Transform[sm.vertices.Length]; for (int i = 0; i < sm.vertices.Length; ++i) { GameObject gov = new GameObject(go.name + "_v" + i); gov.transform.parent = go.transform; gov.transform.localPosition = sm.vertices[i]; gov.transform.localScale = Vector3.zero; sm.vertControlTrans[i] = gov.transform; } } } else { sm.CreateMesh(false); if (displayData.bonePose == null) { //Vertex controller sm.vertControlTrans = new Transform[sm.vertices.Length]; for (int i = 0; i < sm.vertices.Length; ++i) { GameObject gov = new GameObject(go.name + "_v" + i); gov.transform.parent = go.transform; gov.transform.localPosition = sm.vertices[i]; gov.transform.localScale = Vector3.zero; sm.vertControlTrans[i] = gov.transform; } } } sm.transform.parent = slot; if (displayData.bonePose != null) { SkinnedMeshRenderer skinnedMesh = sm.GetComponent <SkinnedMeshRenderer>(); if (skinnedMesh) { skinnedMesh.quality = SkinQuality.Bone4; if (displayData.weights != null && displayData.weights.Length > 0) { Transform[] bones = new Transform[displayData.bonePose.Length / 7]; for (int i = 0; i < displayData.bonePose.Length; i += 7) { int index = i / 7; int boneIndex = (int)displayData.bonePose[i]; bones[index] = armatureEditor.bones[boneIndex]; } List <BoneWeight> boneWeights = new List <BoneWeight>(); for (int i = 0; i < displayData.weights.Length; ++i) { int boneCount = (int)displayData.weights[i]; //骨骼数量 List <KeyValuePair <int, float> > boneWeightList = new List <KeyValuePair <int, float> >(); for (int j = 0; j < boneCount * 2; j += 2) { int boneIdx = (int)displayData.weights[i + j + 1]; float weight = displayData.weights[i + j + 2]; boneWeightList.Add(new KeyValuePair <int, float>(boneIdx, weight)); } //sort boneWeightList,desc boneWeightList.Sort(delegate(KeyValuePair <int, float> x, KeyValuePair <int, float> y) { if (x.Value == y.Value) { return(0); } return(x.Value < y.Value? 1: -1); }); BoneWeight bw = new BoneWeight(); for (int j = 0; j < boneWeightList.Count; ++j) { if (j == 0) { bw.boneIndex0 = GlobalBoneIndexToLocalBoneIndex(armatureEditor, boneWeightList[j].Key, bones); bw.weight0 = boneWeightList[j].Value; } else if (j == 1) { bw.boneIndex1 = GlobalBoneIndexToLocalBoneIndex(armatureEditor, boneWeightList[j].Key, bones); bw.weight1 = boneWeightList[j].Value; } else if (j == 2) { bw.boneIndex2 = GlobalBoneIndexToLocalBoneIndex(armatureEditor, boneWeightList[j].Key, bones); bw.weight2 = boneWeightList[j].Value; } else if (j == 3) { bw.boneIndex3 = GlobalBoneIndexToLocalBoneIndex(armatureEditor, boneWeightList[j].Key, bones); bw.weight3 = boneWeightList[j].Value; } } boneWeights.Add(bw); i += boneCount * 2; } Matrix4x4[] matrixArray = new Matrix4x4[bones.Length]; for (int i = 0; i < matrixArray.Length; ++i) { Transform bone = bones[i]; Vector3 bonePos = bone.localPosition; Quaternion boneRotate = bone.localRotation; Matrix2D m2d = armatureEditor.bonePoseKV[displayData.textureName + bone.name]; bone.position = new Vector3(m2d.tx * 0.01f, -m2d.ty * 0.01f, bone.position.z); bone.rotation = Quaternion.Euler(0f, 0f, -m2d.GetAngle()); matrixArray[i] = bone.worldToLocalMatrix * armatureEditor.armature.localToWorldMatrix; matrixArray[i] *= Matrix4x4.TRS(slot.localPosition, slot.localRotation, slot.localScale); bone.localPosition = bonePos; bone.localRotation = boneRotate; } skinnedMesh.bones = bones; skinnedMesh.sharedMesh.boneWeights = boneWeights.ToArray(); skinnedMesh.sharedMesh.bindposes = matrixArray; skinnedMesh.rootBone = slot; sm.bindposes = matrixArray; SpriteMesh.BoneWeightClass[] bwcs = new SpriteMesh.BoneWeightClass[boneWeights.Count]; for (int i = 0; i < boneWeights.Count; ++i) { SpriteMesh.BoneWeightClass bwc = new SpriteMesh.BoneWeightClass(); BoneWeight bw = boneWeights[i]; bwc.boneIndex0 = bw.boneIndex0; bwc.boneIndex1 = bw.boneIndex1; bwc.boneIndex2 = bw.boneIndex2; bwc.boneIndex3 = bw.boneIndex3; bwc.weight0 = bw.weight0; bwc.weight1 = bw.weight1; bwc.weight2 = bw.weight2; bwc.weight3 = bw.weight3; bwcs[i] = bwc; } sm.weights = bwcs; } } } DragonBoneData.TransformData tranform = displayData.transform; Vector3 localPos = Vector3.zero; if (!float.IsNaN(tranform.x)) { localPos.x = tranform.x; } if (!float.IsNaN(tranform.y)) { localPos.y = tranform.y; } sm.transform.localPosition = localPos; Vector3 localSc = Vector3.one; if (!float.IsNaN(tranform.scx)) { localSc.x = tranform.scx; } if (!float.IsNaN(tranform.scy)) { localSc.y = tranform.scy; } sm.transform.localScale = localSc; sm.color = slot.GetComponent <Slot>().color; sm.transform.localRotation = Quaternion.Euler(0, 0, tranform.rotate); }
BoneWeight CreateBoneWeightFromWeights(List<float> weights) { BoneWeight boneWeight = new BoneWeight(); float weight = 0f; int index = -1; weight = weights.Max(); if(weight < 0.01f) weight = 0f; index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight0 = weight; boneWeight.boneIndex0 = index; if(index >= 0) weights[index] = 0f; weight = weights.Max(); if(weight < 0.01f) weight = 0f; index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight1 = weight; boneWeight.boneIndex1 = index; if(index >= 0) weights[index] = 0f; weight = weights.Max(); if(weight < 0.01f) weight = 0f; index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight2 = weight; boneWeight.boneIndex2 = index; if(index >= 0) weights[index] = 0f; weight = weights.Max(); if(weight < 0.01f) weight = 0f; index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight3 = weight; boneWeight.boneIndex3 = index; float sum = boneWeight.weight0 + boneWeight.weight1 + boneWeight.weight2 + boneWeight.weight3; if(sum > 0f) { boneWeight.weight0 /= sum; boneWeight.weight1 /= sum; boneWeight.weight2 /= sum; boneWeight.weight3 /= sum; } return boneWeight; }
Dictionary <Point, Rigidbody> UpdateRigidbodys(SkinnedMeshRenderer skineedRenderer, TriangleNet.Mesh triMesh, bool isForward) { var vertexLookup = new Dictionary <Point, Rigidbody> ( ); var skinnedRoot = skineedRenderer.transform; ///------------------------------------------------------------------------- /// int boneIndex0 = 0; var bindposes = new List <Matrix4x4>(); var bones = new List <Transform>(); var fBoneWeights = new List <BoneWeight>(); var voronoi = new StandardVoronoi(triMesh); var triAreas = triMesh.Triangles.Sum(t => t.Area()); Debug.Log("Tri Areas : " + triAreas); foreach (var face in voronoi.Faces) { var origins = face.GetAllVertices(); if (origins.Count( ) > 0) { var center = face.generator; var obj = GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Sphere);//new GameObject(); obj.name = "V_" + center.Label + "_" + center.ID; obj.transform.localScale = Vector3.one * 0.005F; var renderer = obj.GetComponent <MeshRenderer> ( ); if (renderer) { renderer.enabled = false; } var worldPosition = skinnedRoot.transform.TransformPoint(new Vector3(( float )center.x, ( float )center.y, 0)); obj.transform.position = worldPosition; obj.transform.parent = skinnedRoot;// Root.transform; bones.Add(obj.transform); bindposes.Add(obj.transform.worldToLocalMatrix * skinnedRoot.localToWorldMatrix); var weight = new BoneWeight(); weight.boneIndex0 = boneIndex0; weight.weight0 = 1.0F; fBoneWeights.Add(weight); var rigidbody = obj.AddComponent <Rigidbody>(); rigidbody.useGravity = false; rigidbody.interpolation = RigidbodyInterpolation.Interpolate; rigidbody.mass = origins.Area( ) * KGSM; rigidbody.drag = 4; rigidbody.angularDrag = 2; // if ( center.Label == 0 ) rigidbody.constraints ^= RigidbodyConstraints.FreezeRotation; vertexLookup.Add(center, rigidbody); boneIndex0++; } } foreach (var edge in triMesh.Edges) { var v0 = triMesh.Vertices.ElementAt(edge.P0); var v1 = triMesh.Vertices.ElementAt(edge.P1); bool isBounds = v0.Label != 0 && v1.Label != 0; var pt_0 = new Vector2((float)v0.x, (float)v0.y); var pt_1 = new Vector2((float)v1.x, (float)v1.y); var distance = Vector2.Distance(pt_0, pt_1); var rigid_0 = vertexLookup[v0]; var rigid_1 = vertexLookup[v1]; var spring = rigid_0.gameObject.AddComponent <SpringJoint>(); spring.connectedBody = rigid_1; spring.minDistance = distance * .96F; spring.maxDistance = distance * 1.00F; spring.spring = isBounds ? 4F : 8F; spring.damper = 0F; spring.autoConfigureConnectedAnchor = false; spring.enableCollision = false; spring.connectedAnchor = spring.anchor = Vector3.zero; spring.axis = Vector3.back; spring.tolerance = 0.01F; spring.enablePreprocessing = false; } var vertices = triMesh.Vertices.Select(v => new Vector3((float)v.x, (float)v.y, 0)).ToArray(); var triangles = isForward ? triMesh.Triangles.SelectMany(t => t.vertices.Reverse().Select(v => v.id)).ToArray() : triMesh.Triangles.SelectMany(t => t.vertices.Select(v => v.id)).ToArray();//.Reverse() var normals = triMesh.Vertices.Select(v => isForward ? Vector3.back : Vector3.forward); var bounds = triMesh.bounds; var l = bounds.Left; var b = bounds.Bottom; var w = bounds.Width; var h = bounds.Height; float dir = isForward ? 1F : -1F; var uvs = triMesh.Vertices.Select(v => new Vector2(dir * (float)((v.x)), (float)((v.y))) * 0.2F).ToArray(); var uniMesh = new Mesh(); uniMesh.vertices = vertices; uniMesh.triangles = triangles; uniMesh.uv = uvs; uniMesh.normals = normals.ToArray( ); uniMesh.boneWeights = fBoneWeights.ToArray( ); uniMesh.bindposes = bindposes.ToArray( ); skineedRenderer.sharedMesh = uniMesh; skineedRenderer.bones = bones.ToArray( ); skineedRenderer.rootBone = skinnedRoot; return(vertexLookup); }
private Mesh CreateNewMesh(Mesh mesh, string meshName) { Vector3[] normals = mesh.normals; Vector4[] tangents = mesh.tangents; Color[] colors = mesh.colors; Vector2[] uv = mesh.uv; Mesh newMesh = new Mesh(); newMesh.name = meshName; newMesh.vertices = mesh.vertices; if (normals != null && normals.Length > 0) { newMesh.normals = normals; } if (tangents != null && tangents.Length > 0) { newMesh.tangents = tangents; } if (colors != null && colors.Length > 0) { newMesh.colors = colors; } if (uv != null && uv.Length > 0) { newMesh.uv = uv; } int numVertices = mesh.vertexCount; BoneWeight[] boneWeights = mesh.boneWeights; Vector4[] uv2 = new Vector4[numVertices]; Vector4[] uv3 = new Vector4[numVertices]; Transform[] smrBones = smr.bones; for (int i = 0; i < numVertices; ++i) { BoneWeight boneWeight = boneWeights[i]; BoneWeightSortData[] weights = new BoneWeightSortData[4]; weights[0] = new BoneWeightSortData() { index = boneWeight.boneIndex0, weight = boneWeight.weight0 }; weights[1] = new BoneWeightSortData() { index = boneWeight.boneIndex1, weight = boneWeight.weight1 }; weights[2] = new BoneWeightSortData() { index = boneWeight.boneIndex2, weight = boneWeight.weight2 }; weights[3] = new BoneWeightSortData() { index = boneWeight.boneIndex3, weight = boneWeight.weight3 }; System.Array.Sort(weights); GPUSkinningBone bone0 = GetBoneByTransform(smrBones[weights[0].index]); GPUSkinningBone bone1 = GetBoneByTransform(smrBones[weights[1].index]); GPUSkinningBone bone2 = GetBoneByTransform(smrBones[weights[2].index]); GPUSkinningBone bone3 = GetBoneByTransform(smrBones[weights[3].index]); Vector4 skinData_01 = new Vector4(); skinData_01.x = GetBoneIndex(bone0); skinData_01.y = weights[0].weight; skinData_01.z = GetBoneIndex(bone1); skinData_01.w = weights[1].weight; uv2[i] = skinData_01; Vector4 skinData_23 = new Vector4(); skinData_23.x = GetBoneIndex(bone2); skinData_23.y = weights[2].weight; skinData_23.z = GetBoneIndex(bone3); skinData_23.w = weights[3].weight; uv3[i] = skinData_23; } newMesh.SetUVs(1, new List <Vector4>(uv2)); newMesh.SetUVs(2, new List <Vector4>(uv3)); newMesh.triangles = mesh.triangles; return(newMesh); }
public static void UpdateAssets(SpriteMesh spriteMesh, SpriteMeshData spriteMeshData) { if(spriteMesh && spriteMeshData) { string spriteMeshPath = AssetDatabase.GetAssetPath(spriteMesh); SerializedObject spriteMeshSO = new SerializedObject(spriteMesh); SerializedProperty sharedMeshProp = spriteMeshSO.FindProperty("m_SharedMesh"); SerializedProperty sharedMaterialsProp = spriteMeshSO.FindProperty("m_SharedMaterials"); if(!spriteMesh.sharedMesh) { Mesh mesh = new Mesh(); mesh.hideFlags = HideFlags.HideInHierarchy; AssetDatabase.AddObjectToAsset(mesh,spriteMeshPath); spriteMeshSO.Update(); sharedMeshProp.objectReferenceValue = mesh; spriteMeshSO.ApplyModifiedProperties(); EditorUtility.SetDirty(mesh); } spriteMesh.sharedMesh.name = spriteMesh.name; if(spriteMesh.sharedMaterials.Length == 0) { Material material = new Material(Shader.Find("Sprites/Default")); material.mainTexture = SpriteUtility.GetSpriteTexture(spriteMesh.sprite,false); AssetDatabase.AddObjectToAsset(material,spriteMeshPath); spriteMeshSO.Update(); sharedMaterialsProp.arraySize = 1; sharedMaterialsProp.GetArrayElementAtIndex(0).objectReferenceValue = material; spriteMeshSO.ApplyModifiedProperties(); } for (int i = 0; i < spriteMesh.sharedMaterials.Length; i++) { Material material = spriteMesh.sharedMaterials [i]; if(material) { if(spriteMesh.sprite) { material.mainTexture = SpriteUtility.GetSpriteTexture(spriteMesh.sprite,false); } material.name = spriteMesh.name + "_" + i; material.hideFlags = HideFlags.HideInHierarchy; EditorUtility.SetDirty(material); } } spriteMeshData.hideFlags = HideFlags.HideInHierarchy; EditorUtility.SetDirty(spriteMeshData); int width = 0; int height = 0; GetSpriteTextureSize(spriteMesh.sprite,ref width,ref height); float pixelsPerUnit = GetSpritePixelsPerUnit(spriteMesh.sprite); Vector2 textureWidthHeightInv = new Vector2(1f/width,1f/height); Vector3[] vertices = (new List<Vector2>(spriteMeshData.vertices)).ConvertAll( v => TexCoordToVertex(spriteMeshData.pivotPoint,v,pixelsPerUnit)).ToArray(); Vector2[] uvs = (new List<Vector2>(spriteMeshData.vertices)).ConvertAll( v => Vector2.Scale(v,textureWidthHeightInv)).ToArray(); Vector3[] normals = (new List<Vector3>(vertices)).ConvertAll( v => Vector3.back ).ToArray(); BoneWeight[] boneWeightsData = spriteMeshData.boneWeights; if(boneWeightsData.Length != spriteMeshData.vertices.Length) { boneWeightsData = new BoneWeight[spriteMeshData.vertices.Length]; } List<UnityEngine.BoneWeight> boneWeights = new List<UnityEngine.BoneWeight>(boneWeightsData.Length); List<float> verticesOrder = new List<float>(spriteMeshData.vertices.Length); for (int i = 0; i < boneWeightsData.Length; i++) { BoneWeight boneWeight = boneWeightsData[i]; List< KeyValuePair<int,float> > pairs = new List<KeyValuePair<int, float>>(); pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex0,boneWeight.weight0)); pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex1,boneWeight.weight1)); pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex2,boneWeight.weight2)); pairs.Add(new KeyValuePair<int, float>(boneWeight.boneIndex3,boneWeight.weight3)); pairs = pairs.OrderByDescending(s=>s.Value).ToList(); UnityEngine.BoneWeight boneWeight2 = new UnityEngine.BoneWeight(); boneWeight2.boneIndex0 = Mathf.Max(0,pairs[0].Key); boneWeight2.boneIndex1 = Mathf.Max(0,pairs[1].Key); boneWeight2.boneIndex2 = Mathf.Max(0,pairs[2].Key); boneWeight2.boneIndex3 = Mathf.Max(0,pairs[3].Key); boneWeight2.weight0 = pairs[0].Value; boneWeight2.weight1 = pairs[1].Value; boneWeight2.weight2 = pairs[2].Value; boneWeight2.weight3 = pairs[3].Value; boneWeights.Add(boneWeight2); float vertexOrder = i; if(spriteMeshData.bindPoses.Length > 0) { vertexOrder = spriteMeshData.bindPoses[boneWeight2.boneIndex0].zOrder * boneWeight2.weight0 + spriteMeshData.bindPoses[boneWeight2.boneIndex1].zOrder * boneWeight2.weight1 + spriteMeshData.bindPoses[boneWeight2.boneIndex2].zOrder * boneWeight2.weight2 + spriteMeshData.bindPoses[boneWeight2.boneIndex3].zOrder * boneWeight2.weight3; } verticesOrder.Add(vertexOrder); } List<WeightedTriangle> weightedTriangles = new List<WeightedTriangle>(spriteMeshData.indices.Length / 3); for(int i = 0; i < spriteMeshData.indices.Length; i+=3) { int p1 = spriteMeshData.indices[i]; int p2 = spriteMeshData.indices[i+1]; int p3 = spriteMeshData.indices[i+2]; weightedTriangles.Add(new WeightedTriangle(p1,p2,p3, verticesOrder[p1], verticesOrder[p2], verticesOrder[p3])); } weightedTriangles = weightedTriangles.OrderBy( t => t.weight ).ToList(); List<int> indices = new List<int>(spriteMeshData.indices.Length); for(int i = 0; i < weightedTriangles.Count; ++i) { WeightedTriangle t = weightedTriangles[i]; indices.Add(t.p1); indices.Add(t.p2); indices.Add(t.p3); } spriteMesh.sharedMesh.Clear(); spriteMesh.sharedMesh.vertices = vertices; spriteMesh.sharedMesh.uv = uvs; spriteMesh.sharedMesh.triangles = indices.ToArray(); spriteMesh.sharedMesh.normals = normals; spriteMesh.sharedMesh.boneWeights = boneWeights.ToArray(); spriteMesh.sharedMesh.bindposes = (new List<BindInfo>(spriteMeshData.bindPoses)).ConvertAll( p => p.bindPose ).ToArray(); spriteMesh.sharedMesh.RecalculateBounds(); } }
void DrawPie(Vector3 position, BoneWeight boneWeight, float pieSize) { Handles.color = Color.black; DrawVertex(position,22.5f); int boneIndex = boneWeight.boneIndex0; float angleStart = 0f; float angle = 0f; if(boneIndex >= 0) { angleStart = 0f; angle = Mathf.Lerp(0f,360f,boneWeight.weight0); Handles.color = m_BindPoseColors[boneWeight.boneIndex0]; Handles.DrawSolidArc(position, Vector3.forward,Vector3.up,angle, pieSize); } boneIndex = boneWeight.boneIndex1; if(boneIndex >= 0) { angleStart += angle; angle = Mathf.Lerp(0f,360f,boneWeight.weight1); Handles.color = m_BindPoseColors[boneWeight.boneIndex1]; Handles.DrawSolidArc(position, Vector3.forward,Quaternion.AngleAxis(angleStart,Vector3.forward) * Vector3.up,angle, pieSize); } boneIndex = boneWeight.boneIndex2; if(boneIndex >= 0) { angleStart += angle; angle = Mathf.Lerp(0f,360f,boneWeight.weight2); Handles.color = m_BindPoseColors[boneWeight.boneIndex2]; Handles.DrawSolidArc(position, Vector3.forward,Quaternion.AngleAxis(angleStart,Vector3.forward) * Vector3.up,angle, pieSize); } boneIndex = boneWeight.boneIndex3; if(boneIndex >= 0) { angleStart += angle; angle = Mathf.Lerp(0f,360f,boneWeight.weight3); Handles.color = m_BindPoseColors[boneWeight.boneIndex3]; Handles.DrawSolidArc(position, Vector3.forward,Quaternion.AngleAxis(angleStart,Vector3.forward) * Vector3.up,angle, pieSize); } }
public Mesh LoadFromStream(EndianBinaryReader reader) { MeshVertexAttributeHolder vertexData = null; SceneNode rootNode = new SceneNode(); List<Texture2D> textureList = new List<Texture2D>(); List<WEditor.Common.Nintendo.J3D.Material> materialList = null; List<SkeletonBone> joints = new List<SkeletonBone>(); DrawInfo drawInfo = null; Envelopes envelopes = null; Mesh j3dMesh = new Mesh(); // Read the Header int magic = reader.ReadInt32(); // J3D1, J3D2, etc if (magic != 1244873778) { WLog.Warning(LogCategory.ModelLoading, null, "Attempted to load model with invalid magic, ignoring!"); return null; } int j3dType = reader.ReadInt32(); // BMD3 (models) BDL4 (models), jpa1 (particles), bck1 (animations), etc. int totalFileSize = reader.ReadInt32(); int chunkCount = reader.ReadInt32(); // Skip over an unused tag (consistent in all files) and some padding. reader.ReadBytes(16); for (int i = 0; i < chunkCount; i++) { long chunkStart = reader.BaseStream.Position; string tagName = reader.ReadString(4); int chunkSize = reader.ReadInt32(); switch (tagName) { // INFO - Vertex Count, Scene Hierarchy case "INF1": rootNode = LoadINF1FromFile(rootNode, reader, chunkStart); break; // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc. Contains VertexAttributes which describe // how this data is stored/laid out. case "VTX1": vertexData = LoadVTX1FromFile(reader, chunkStart, chunkSize); break; // ENVELOPES - Defines vertex weights for skinning. case "EVP1": envelopes = LoadEVP1FromStream(reader, chunkStart); break; // DRAW (Skeletal Animation Data) - Stores which matrices are weighted, and which are used directly. case "DRW1": drawInfo = LoadDRW1FromStream(reader, chunkStart); break; // JOINTS - Stores the skeletal joints (position, rotation, scale, etc.) case "JNT1": joints = LoadJNT1SectionFromStream(reader, chunkStart); break; // SHAPE - Face/Triangle information for model. case "SHP1": LoadSHP1SectionFromFile(vertexData, j3dMesh, reader, chunkStart); break; // MATERIAL - Stores materials (which describes how textures, etc. are drawn) case "MAT3": materialList = LoadMAT3SectionFromStream(reader, chunkStart, chunkSize); break; // TEXTURES - Stores binary texture images. case "TEX1": textureList = LoadTEX1FromFile(reader, chunkStart); break; // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly. case "MDL3": break; } reader.BaseStream.Position = chunkStart + chunkSize; } // Resolve the texture indexes into actual textures now that we've loaded the TEX1 section. foreach (Material mat in materialList) { for (int i = 0; i < mat.TextureIndexes.Length; i++) { short index = mat.TextureIndexes[i]; if (index < 0) continue; mat.Textures[i] = textureList[index]; } } // loltests for (int i = 0; i < materialList.Count; i++) { materialList[i].VtxDesc = j3dMesh.SubMeshes[0].GetVertexDescription(); Shader shader = TEVShaderGenerator.GenerateShader(materialList[i]); materialList[i].Shader = shader; } // We're going to do something a little crazy - we're going to read the scene view and apply textures to meshes (for now) Material curMat = null; AssignMaterialsToMeshRecursive(rootNode, j3dMesh, ref curMat, materialList); List<SkeletonBone> skeleton = new List<SkeletonBone>(); BuildSkeletonRecursive(rootNode, skeleton, joints, 0); j3dMesh.Skeleton = skeleton; j3dMesh.BindPoses = envelopes.inverseBindPose; // Let's do some ugly post-processing here to see if we can't resolve all of the cross-references and turn it into // a normal computer-readable format that we can digest in our RenderSytem. { for (int i = 0; i < j3dMesh.SubMeshes.Count; i++) { MeshBatch batch = j3dMesh.SubMeshes[i]; batch.BoneWeights = new BoneWeight[batch.Vertices.Length]; for (int j = 0; j < batch.PositionMatrixIndexs.Count; j++) { // Okay so this is where it gets more complicated. The PMI gives us an index into the MatrixTable for the packet, which we // resolve and call "drawIndexes" - however we have to divide the number they give us by three for some reason, so that is // already done and now our drawIndexes array should be one-index-for-every-vertex-in-batch and it should be the index into // the draw section we need. ushort drw1Index = batch.drawIndexes[j]; // The drw1Index can be set as 0xFFFF - if so, this means that you need to use the dr1Index of the previous one. // until it is no longer 0xFFFF. int counter = 0; while (drw1Index == 0xFFFF) { drw1Index = batch.drawIndexes[j - counter]; counter++; } bool isWeighted = drawInfo.IsWeighted[drw1Index]; BoneWeight weight = new BoneWeight(); if (isWeighted) { // Something on this doesn't work for models that actually specify a PositionMatrixIndex. // So... some math is off somewhere and I don't know where for the moment. ushort numBonesAffecting = envelopes.numBonesAffecting[drw1Index]; weight.BoneIndexes = new ushort[numBonesAffecting]; weight.BoneWeights = new float[numBonesAffecting]; // "Much WTFs" ushort offset = 0; for (ushort e = 0; e < envelopes.indexRemap[drw1Index]; e++) { offset += envelopes.numBonesAffecting[e]; } offset *= 2; Matrix4 finalTransform = Matrix4.Identity; for (ushort k = 0; k < numBonesAffecting; k++) { ushort boneIndex = envelopes.indexRemap[offset + (k * 0x2)]; float boneWeight = envelopes.weights[(offset / 2) + k]; weight.BoneIndexes[k] = boneIndex; weight.BoneWeights[k] = boneWeight; // This was apaprently a partial thought I never finished or got working in the old one? :S } } else { // If the vertex isn't weighted, we just use the position from the bone matrix. SkeletonBone joint = skeleton[drawInfo.Indexes[drw1Index]]; Matrix4 translation = Matrix4.CreateTranslation(joint.Translation); Matrix4 rotation = Matrix4.CreateFromQuaternion(joint.Rotation); Matrix4 finalMatrix = rotation * translation; // Move the mesh by transforming the position by this much. // I think we can just assign full weight to the first bone index and call it good. weight.BoneIndexes = new[] { drawInfo.Indexes[drw1Index] }; weight.BoneWeights = new[] { 1f }; } batch.BoneWeights[j] = weight; } } } return j3dMesh; }
static public void ImportFlver(FLVER flver, FLVERAssetLink assetLink, DarkSoulsTools.GameType gameType, string assetName, string texturePath = null, bool mapflver = false) { Material[] materials = new Material[flver.Materials.Count]; string gamePath = DarkSoulsTools.GameFolder(gameType); if (!AssetDatabase.IsValidFolder(assetName)) { AssetDatabase.CreateFolder(Path.GetDirectoryName(assetName + ".blah"), Path.GetFileNameWithoutExtension(assetName + ".blah")); } Shader shader = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/FLVERShader.shadergraph"); Shader shaderObj = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/ObjFLVERShader.shadergraph"); Shader shaderDiff = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/FLVERShaderDiffuse.shadergraph"); var t = 0; foreach (var m in flver.Materials) { //string name = m.Name; //if (name == null || name == "") //{ string name = Path.GetFileNameWithoutExtension(assetName) + $@"_{t}"; //} //bool normalquery = (m.Textures.Where(x => ((x.Type.ToUpper() == "G_BUMPMAPTEXTURE") || (x.Type.ToUpper() == "G_BUMPMAP"))).Count() >= 1); bool normalquery = false; Texture2D albedo = null; Texture2D specular = null; Texture2D normal = null; bool IsMapTexture = mapflver; var MTD = AssetDatabase.LoadAssetAtPath <MTDAssetLink>($@"Assets/{gamePath}/MTD/{Path.GetFileNameWithoutExtension(m.MTD)}.asset"); if (texturePath != null) { foreach (var matParam in m.Textures) { var paramNameCheck = matParam.Type.ToUpper(); if (paramNameCheck == "G_DIFFUSETEXTURE" || paramNameCheck == "G_DIFFUSE" || paramNameCheck.Contains("ALBEDO")) { var texPath = matParam.Path; if (texPath == "") { texPath = MTD.Textures.Find(x => (x.Name == matParam.Type)).TexturePath; if (texPath == "") { continue; } } if (albedo == null) { albedo = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(texPath)}.dds"); if (albedo == null) { albedo = FindTexture(texPath, gameType); } } } if (paramNameCheck == "G_SPECULARTEXTURE" || paramNameCheck == "G_SPECULAR") { specular = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(matParam.Path)}.dds"); if (specular == null) { specular = FindTexture(matParam.Path, gameType); } } if (paramNameCheck == "G_BUMPMAPTEXTURE" || paramNameCheck == "G_BUMPMAP" || paramNameCheck.Contains("NORMAL")) { var texPath = matParam.Path; if (texPath == "") { texPath = MTD.Textures.Find(x => (x.Name == matParam.Type)).TexturePath; if (texPath == "") { continue; } } if (normal == null) { normal = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(texPath)}.dds"); if (normal == null) { normal = FindTexture(texPath, gameType); } } normalquery = true; } } } Material mat; /*if (IsMapTexture && specular != null) * { * mat = new Material(shader); * mat.SetTexture("_Albedo", albedo); * mat.SetTexture("_Specular", specular); * mat.SetTexture("_Normal", normal); * } * else */ if (!normalquery) { mat = new Material(shaderDiff); mat.SetTexture("_MainTex", albedo); } else { mat = new Material(shaderObj); mat.SetTexture("_MainTex", albedo); mat.SetTexture("_Specular", specular); mat.SetTexture("_BumpMap", normal); } mat.name = name; materials[t] = mat; t++; AssetDatabase.CreateAsset(mat, assetName + "/" + name + ".mat"); } GameObject root = new GameObject(Path.GetFileNameWithoutExtension(assetName)); GameObject meshesObj = new GameObject("Meshes"); GameObject bonesObj = new GameObject("Bones"); meshesObj.transform.parent = root.transform; bonesObj.transform.parent = root.transform; // import the skeleton Transform[] bones = new Transform[flver.Bones.Count]; Matrix4x4[] bindPoses = new Matrix4x4[flver.Bones.Count]; for (int i = 0; i < flver.Bones.Count; i++) { var fbone = flver.Bones[i]; bones[i] = new GameObject(fbone.Name).transform; EulerToTransform(new Vector3(fbone.Rotation.X, fbone.Rotation.Y, fbone.Rotation.Z), bones[i]); bones[i].localPosition = new Vector3(fbone.Translation.X, fbone.Translation.Y, fbone.Translation.Z); bones[i].localScale = new Vector3(fbone.Scale.X, fbone.Scale.Y, fbone.Scale.Z); //SetBoneWorldTransform(bones[i], flver.Bones.ToArray(), i); //bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix; } // Skeleton parenting for (int i = 0; i < flver.Bones.Count; i++) { var fbone = flver.Bones[i]; if (fbone.ParentIndex == -1) { //bones[i].parent = root.transform; bones[i].SetParent(bonesObj.transform, false); bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix; } else { //bones[i].parent = bones[fbone.ParentIndex]; bones[i].SetParent(bones[fbone.ParentIndex], false); bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix; } } // Import the meshes int index = 0; foreach (var m in flver.Meshes) { var mesh = new Mesh(); var verts = new List <Vector3>(); var normals = new List <Vector3>(); var tangents = new List <Vector4>(); var boneweights = new List <BoneWeight>(); var smcount = 0; bool usestangents = false; int uvcount = m.Vertices[0].UVs.Count; List <Vector2>[] uvs = new List <Vector2> [uvcount]; List <Material> matList = new List <Material>(); // Add the mesh to the asset link FLVERAssetLink.SubmeshInfo info = new FLVERAssetLink.SubmeshInfo(); info.Name = flver.Materials[m.MaterialIndex].Name; var MTD = AssetDatabase.LoadAssetAtPath <MTDAssetLink>($@"Assets/{gamePath}/MTD/{Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)}.asset"); info.Mtd = MTD; assetLink.Submeshes.Add(info); int lightmapUVIndex = 1; // Use MTD to get lightmap uv index if (gameType != DarkSoulsTools.GameType.Sekiro) { if (MTD != null) { lightmapUVIndex = (MTD.LightmapUVIndex != -1) ? MTD.LightmapUVIndex : 1; if (lightmapUVIndex >= uvs.Length) { lightmapUVIndex = 1; } } else { // Do a hardcoded lookup of a material's lightmap UV index from a shitty table :fatcat: if (MaterialLightmapUVIndex.ContainsKey(Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD))) { lightmapUVIndex = MaterialLightmapUVIndex[Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)]; } } } for (int i = 0; i < uvs.Length; i++) { uvs[i] = new List <Vector2>(); } bool isSkinned = false; foreach (var v in m.Vertices) { verts.Add(new Vector3(v.Positions[0].X, v.Positions[0].Y, v.Positions[0].Z)); normals.Add(new Vector3(v.Normals[0].X, v.Normals[0].Y, v.Normals[0].Z)); if (v.Tangents.Count > 0) { tangents.Add(new Vector4(v.Tangents[0].X, v.Tangents[0].Y, v.Tangents[0].Z, v.Tangents[0].W)); usestangents = true; } else { tangents.Add(new Vector4(0, 0, 0, 1)); } for (int i = 0; i < uvs.Length; i++) { // Swap lightmap uvs with uv index 1 because lmao unity if (i == 1) { uvs[i].Add(new Vector2(v.UVs[lightmapUVIndex].X, 1.0f - v.UVs[lightmapUVIndex].Y)); } else if (i == lightmapUVIndex) { uvs[i].Add(new Vector2(v.UVs[1].X, 1.0f - v.UVs[1].Y)); } else { uvs[i].Add(new Vector2(v.UVs[i].X, 1.0f - v.UVs[i].Y)); } } if (v.BoneWeights != null && v.BoneWeights.Count() > 0) { isSkinned = true; var weight = new BoneWeight(); if (m.Unk1 == 0) { weight.boneIndex0 = v.BoneIndices[0]; weight.boneIndex1 = v.BoneIndices[1]; weight.boneIndex2 = v.BoneIndices[2]; weight.boneIndex3 = v.BoneIndices[3]; } else { weight.boneIndex0 = m.BoneIndices[v.BoneIndices[0]]; weight.boneIndex1 = m.BoneIndices[v.BoneIndices[1]]; weight.boneIndex2 = m.BoneIndices[v.BoneIndices[2]]; weight.boneIndex3 = m.BoneIndices[v.BoneIndices[3]]; } if (v.BoneWeights[0] < 0.0) { weight.weight0 = 1.0f; } else { weight.weight0 = v.BoneWeights[0]; } weight.weight1 = v.BoneWeights[1]; weight.weight2 = v.BoneWeights[2]; weight.weight3 = v.BoneWeights[3]; boneweights.Add(weight); } else { boneweights.Add(new BoneWeight()); } } foreach (var fs in m.FaceSets) { if (fs.Vertices.Count() > 0 && fs.Flags == FLVER.FaceSet.FSFlags.None) { matList.Add(materials[m.MaterialIndex]); smcount++; } } mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; mesh.subMeshCount = smcount; mesh.SetVertices(verts); mesh.SetNormals(normals); if (usestangents) { mesh.SetTangents(tangents); } if (isSkinned) { mesh.boneWeights = boneweights.ToArray(); mesh.bindposes = bindPoses; } for (int i = 0; i < uvs.Length; i++) { mesh.SetUVs(i, uvs[i]); } var submesh = 0; foreach (var fs in m.FaceSets) { if (fs.Vertices.Count() == 0) { continue; } if (fs.Flags != FLVER.FaceSet.FSFlags.None) { continue; } mesh.SetTriangles(fs.GetFacesArray(), submesh, true, 0); submesh++; } mesh.RecalculateBounds(); // Setup a game object asset GameObject obj = new GameObject(Path.GetFileNameWithoutExtension(assetName) + $@"_{index}"); if (isSkinned) { obj.AddComponent <SkinnedMeshRenderer>(); obj.GetComponent <SkinnedMeshRenderer>().materials = matList.ToArray(); obj.GetComponent <SkinnedMeshRenderer>().bones = bones; obj.GetComponent <SkinnedMeshRenderer>().sharedMesh = mesh; } else { obj.AddComponent <MeshRenderer>(); obj.GetComponent <MeshRenderer>().materials = matList.ToArray(); obj.AddComponent <MeshFilter>(); obj.GetComponent <MeshFilter>().mesh = mesh; } obj.AddComponent <FlverSubmesh>(); obj.GetComponent <FlverSubmesh>().Link = assetLink; obj.GetComponent <FlverSubmesh>().SubmeshIdx = index; obj.transform.parent = meshesObj.transform; AssetDatabase.CreateAsset(mesh, assetName + $@"/{Path.GetFileNameWithoutExtension(assetName)}_{index}.mesh"); index++; } // If there's no meshes, create an empty one to bind the skeleton to so that Maya works // when you export the skeleton (like with c0000). if (flver.Meshes.Count == 0) { var mesh = new Mesh(); var verts = new List <Vector3>(); var normals = new List <Vector3>(); var tangents = new List <Vector4>(); var boneweights = new List <BoneWeight>(); for (var i = 0; i < 3; i++) { verts.Add(new Vector3(0.0f, 0.0f, 0.0f)); normals.Add(new Vector3(0.0f, 1.0f, 0.0f)); tangents.Add(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); var weight = new BoneWeight(); weight.boneIndex0 = 0; weight.weight0 = 1.0f; boneweights.Add(weight); } mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; mesh.subMeshCount = 1; mesh.SetVertices(verts); mesh.SetNormals(normals); mesh.SetTangents(tangents); mesh.boneWeights = boneweights.ToArray(); mesh.bindposes = bindPoses; mesh.SetTriangles(new int [] { 0, 1, 2 }, 0); GameObject obj = new GameObject(Path.GetFileNameWithoutExtension(assetName) + $@"_{index}"); obj.AddComponent <SkinnedMeshRenderer>(); obj.GetComponent <SkinnedMeshRenderer>().bones = bones; obj.GetComponent <SkinnedMeshRenderer>().sharedMesh = mesh; obj.transform.parent = meshesObj.transform; AssetDatabase.CreateAsset(mesh, assetName + $@"/{Path.GetFileNameWithoutExtension(assetName)}_{index}.mesh"); } root.AddComponent <FlverMesh>(); root.GetComponent <FlverMesh>().Link = assetLink; AssetDatabase.CreateAsset(assetLink, assetName + ".asset"); AssetDatabase.SaveAssets(); PrefabUtility.SaveAsPrefabAsset(root, assetName + ".prefab"); Object.DestroyImmediate(root); }
bool InitSkin() { if (target) { SkinnedMeshRenderer skin = target.GetComponent <SkinnedMeshRenderer>(); if (skin) { Quaternion rot = transform.rotation; attachrot = Quaternion.identity; skinned = true; Mesh ms = skin.sharedMesh; Vector3 pt = transform.position; CalcSkinVerts(); Vector3 objSpacePt = pt; Vector3[] verts = calcskinverts; int[] tris = ms.triangles; int index = -1; MegaNearestPointTest.NearestPointOnMesh1(objSpacePt, verts, tris, ref index, ref BaryCoord); //ref tribary); if (index >= 0) { BaryVerts[0] = tris[index]; BaryVerts[1] = tris[index + 1]; BaryVerts[2] = tris[index + 2]; } MegaNearestPointTest.NearestPointOnMesh1(objSpacePt + attachforward, verts, tris, ref index, ref BaryCoord1); if (index >= 0) { BaryVerts1[0] = tris[index]; BaryVerts1[1] = tris[index + 1]; BaryVerts1[2] = tris[index + 2]; } skinverts = new MegaSkinVert[6]; for (int i = 0; i < 3; i++) { int vert = BaryVerts[i]; BoneWeight bw = ms.boneWeights[vert]; skinverts[i] = new MegaSkinVert(); skinverts[i].vert = vert; skinverts[i].weights[0] = bw.weight0; skinverts[i].weights[1] = bw.weight1; skinverts[i].weights[2] = bw.weight2; skinverts[i].weights[3] = bw.weight3; skinverts[i].bones[0] = skin.bones[bw.boneIndex0]; skinverts[i].bones[1] = skin.bones[bw.boneIndex1]; skinverts[i].bones[2] = skin.bones[bw.boneIndex2]; skinverts[i].bones[3] = skin.bones[bw.boneIndex3]; skinverts[i].bindposes[0] = ms.bindposes[bw.boneIndex0]; skinverts[i].bindposes[1] = ms.bindposes[bw.boneIndex1]; skinverts[i].bindposes[2] = ms.bindposes[bw.boneIndex2]; skinverts[i].bindposes[3] = ms.bindposes[bw.boneIndex3]; } for (int i = 3; i < 6; i++) { int vert = BaryVerts1[i - 3]; BoneWeight bw = ms.boneWeights[vert]; skinverts[i] = new MegaSkinVert(); skinverts[i].vert = vert; skinverts[i].weights[0] = bw.weight0; skinverts[i].weights[1] = bw.weight1; skinverts[i].weights[2] = bw.weight2; skinverts[i].weights[3] = bw.weight3; skinverts[i].bones[0] = skin.bones[bw.boneIndex0]; skinverts[i].bones[1] = skin.bones[bw.boneIndex1]; skinverts[i].bones[2] = skin.bones[bw.boneIndex2]; skinverts[i].bones[3] = skin.bones[bw.boneIndex3]; skinverts[i].bindposes[0] = ms.bindposes[bw.boneIndex0]; skinverts[i].bindposes[1] = ms.bindposes[bw.boneIndex1]; skinverts[i].bindposes[2] = ms.bindposes[bw.boneIndex2]; skinverts[i].bindposes[3] = ms.bindposes[bw.boneIndex3]; } GetSkinPos1(); attachrot = Quaternion.Inverse(transform.rotation) * rot; return(true); } else { skinned = false; } } return(false); }
//---------------------------------------------------------------------------- void Start () { // if not specified, go find meshes if(meshFilters.Length == 0) { // find all the mesh filters Component[] comps = GetComponentsInChildren(typeof(MeshFilter)); meshFilters = new MeshFilter[comps.Length]; int mfi = 0; foreach(Component comp in comps) meshFilters[mfi++] = (MeshFilter) comp; } // figure out array sizes int vertCount = 0; int normCount = 0; int triCount = 0; int uvCount = 0; foreach(MeshFilter mf in meshFilters) { vertCount += mf.mesh.vertices.Length; normCount += mf.mesh.normals.Length; triCount += mf.mesh.triangles.Length; uvCount += mf.mesh.uv.Length; if(material == null) material = mf.gameObject.renderer.material; } // allocate arrays Vector3[] verts = new Vector3[vertCount]; Vector3[] norms = new Vector3[normCount]; Transform[] aBones = new Transform[meshFilters.Length]; Matrix4x4[] bindPoses = new Matrix4x4[meshFilters.Length]; BoneWeight[] weights = new BoneWeight[vertCount]; int[] tris = new int[triCount]; Vector2[] uvs = new Vector2[uvCount]; int vertOffset = 0; int normOffset = 0; int triOffset = 0; int uvOffset = 0; int meshOffset = 0; // merge the meshes and set up bones foreach(MeshFilter mf in meshFilters) { foreach(int i in mf.mesh.triangles) tris[triOffset++] = i + vertOffset; aBones[meshOffset] = mf.transform; bindPoses[meshOffset] = Matrix4x4.identity; foreach(Vector3 v in mf.mesh.vertices) { weights[vertOffset].weight0 = 1.0f; weights[vertOffset].boneIndex0 = meshOffset; verts[vertOffset++] = v; } foreach(Vector3 n in mf.mesh.normals) norms[normOffset++] = n; foreach(Vector2 uv in mf.mesh.uv) uvs[uvOffset++] = uv; meshOffset++; MeshRenderer mr = mf.gameObject.GetComponent(typeof(MeshRenderer)) as MeshRenderer; if(mr) mr.enabled = false; } // hook up the mesh Mesh me = new Mesh(); me.name = gameObject.name; me.vertices = verts; me.normals = norms; me.boneWeights = weights; me.uv = uvs; me.triangles = tris; me.bindposes = bindPoses; // hook up the mesh renderer SkinnedMeshRenderer smr = gameObject.AddComponent(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer; smr.sharedMesh = me; smr.bones = aBones; renderer.material = material; }
public void SetBoneWeight(Node node, BoneWeight boneWeight) { boneWeights[node.index] = boneWeight; isDirty = true; }
static bool PostProcessSpriteMeshData(ISpriteEditorDataProvider spriteDataProvider, Sprite[] sprites) { var spriteMeshDataProvider = spriteDataProvider.GetDataProvider <ISpriteMeshDataProvider>(); var boneDataProvider = spriteDataProvider.GetDataProvider <ISpriteBoneDataProvider>(); var textureDataProvider = spriteDataProvider.GetDataProvider <ITextureDataProvider>(); if (sprites == null || sprites.Length == 0 || spriteMeshDataProvider == null || textureDataProvider == null) { return(false); } bool dataChanged = false; float definitionScale = CalculateDefinitionScale(textureDataProvider); foreach (var sprite in sprites) { var guid = sprite.GetSpriteID(); var spriteRect = spriteDataProvider.GetSpriteRects().First(s => { return(s.spriteID == guid); }); var spriteBone = boneDataProvider.GetBones(guid); var hasBones = spriteBone != null && spriteBone.Count > 0; var hasInvalidWeights = false; var vertices = spriteMeshDataProvider.GetVertices(guid); var indices = spriteMeshDataProvider.GetIndices(guid); if (vertices.Length > 2 && indices.Length > 2) { var vertexArray = new NativeArray <Vector3>(vertices.Length, Allocator.Temp); var boneWeightArray = new NativeArray <BoneWeight>(vertices.Length, Allocator.Temp); for (int i = 0; i < vertices.Length; ++i) { var boneWeight = vertices[i].boneWeight; vertexArray[i] = (Vector3)(vertices[i].position - Vector2.Scale(spriteRect.rect.size, spriteRect.pivot)) * definitionScale / sprite.pixelsPerUnit; boneWeightArray[i] = boneWeight; if (hasBones && !hasInvalidWeights) { var sum = boneWeight.weight0 + boneWeight.weight1 + boneWeight.weight2 + boneWeight.weight3; hasInvalidWeights = sum < 0.999f; } } var indicesArray = new NativeArray <ushort>(indices.Length, Allocator.Temp); for (int i = 0; i < indices.Length; ++i) { indicesArray[i] = (ushort)indices[i]; } sprite.SetVertexCount(vertices.Length); sprite.SetVertexAttribute <Vector3>(VertexAttribute.Position, vertexArray); sprite.SetIndices(indicesArray); sprite.SetVertexAttribute <BoneWeight>(VertexAttribute.BlendWeight, boneWeightArray); vertexArray.Dispose(); boneWeightArray.Dispose(); indicesArray.Dispose(); dataChanged = true; if (hasBones && hasInvalidWeights) { Debug.LogWarning("Sprite \"" + spriteRect.name + "\" contains bone weights which sum zero or are not normalized. To avoid visual artifacts please consider fixing them."); } } else { var boneWeightArray = new NativeArray <BoneWeight>(sprite.GetVertexCount(), Allocator.Temp); var defaultBoneWeight = new BoneWeight() { weight0 = 1f }; for (var i = 0; i < boneWeightArray.Length; ++i) { boneWeightArray[i] = defaultBoneWeight; } sprite.SetVertexAttribute <BoneWeight>(VertexAttribute.BlendWeight, boneWeightArray); } } return(dataChanged); }
private void OnSceneGUI() { if (!_active) { return; } if (Event.current.type == EventType.Repaint && _idx >= 0) { Handles.color = Color.red; Handles.matrix = Matrix4x4.identity; Handles.CubeHandleCap(0, _pos, Quaternion.identity, 0.01f, EventType.Repaint); Handles.Label(_pos + new Vector3(0, 0.02f, 0), string.Format("Vertex ID {0}, World Position {1} Model Position {2}", _idx, _pos.ToString("F"), _vtx.ToString("F"))); Handles.Label(_pos + new Vector3(0, 0.01f, 0), string.Format("BoneWeights ({0}:{1}),({2}:{3}),({4}:{5}),({6}:{7})", _bws.boneIndex0, _bws.weight0, _bws.boneIndex1, _bws.weight1, _bws.boneIndex2, _bws.weight2, _bws.boneIndex3, _bws.weight3)); } Selection.activeTransform = _selectedTransform; if (Event.current != null && Event.current.type == EventType.MouseDown && Tools.current == Tool.Move) { Transform trans = Selection.activeTransform; if (trans != null) { SkinnedMeshRenderer smr; MeshRenderer mr; if (null != (smr = trans.GetComponent <SkinnedMeshRenderer>())) { float minIntersectDistance = float.MaxValue; int minIntersectVertexIndex = -1; Vector3 minIntersectPosition = Vector3.zero; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); Bounds bb = smr.bounds; if (bb.IntersectRay(ray)) { Mesh mesh = smr.sharedMesh; Vector3[] vertices = mesh.vertices; for (int s = 0, smax = mesh.subMeshCount; s < smax; s++) { int[] triangles = mesh.GetTriangles(s); for (int t = 0, tmax = triangles.Length / 3; t < tmax; t++) { int i0 = triangles[t * 3]; int i1 = triangles[t * 3 + 1]; int i2 = triangles[t * 3 + 2]; Vector3 v0 = smr.GetSkinnedVertexWS(i0); Vector3 v1 = smr.GetSkinnedVertexWS(i1); Vector3 v2 = smr.GetSkinnedVertexWS(i2); Vector3 ip; if (!ray.CheckIntersect(v0, v1, v2, out ip, ref minIntersectDistance)) { continue; } switch (GetNearestPoint(v0, v1, v2, ip)) { case 0: minIntersectVertexIndex = i0; minIntersectPosition = v0; break; case 1: minIntersectVertexIndex = i1; minIntersectPosition = v1; break; case 2: default: minIntersectVertexIndex = i2; minIntersectPosition = v2; break; } } } if (minIntersectVertexIndex >= 0) { _pos = minIntersectPosition; _idx = minIntersectVertexIndex; _vtx = vertices[minIntersectVertexIndex]; _bws = mesh.boneWeights[minIntersectVertexIndex]; } } } else if (null != (mr = trans.GetComponent <MeshRenderer>())) { float minIntersectDistance = float.MaxValue; int minIntersectVertexIndex = -1; Vector3 minIntersectPosition = Vector3.zero; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); Bounds bb = mr.bounds; if (bb.IntersectRay(ray)) { Matrix4x4 w2m = mr.worldToLocalMatrix; Matrix4x4 m2w = mr.localToWorldMatrix; Ray localRay = new Ray(w2m.MultiplyPoint3x4(ray.origin), w2m.MultiplyVector(ray.direction)); MeshFilter mf = mr.GetComponent <MeshFilter>(); Mesh mesh = mf.sharedMesh; Vector3[] vertices = mesh.vertices; for (int s = 0, smax = mesh.subMeshCount; s < smax; s++) { int[] triangles = mesh.GetTriangles(s); for (int t = 0, tmax = triangles.Length / 3; t < tmax; t++) { int i0 = triangles[t * 3]; int i1 = triangles[t * 3 + 1]; int i2 = triangles[t * 3 + 2]; Vector3 v0 = vertices[i0]; Vector3 v1 = vertices[i1]; Vector3 v2 = vertices[i2]; Vector3 ip; if (!localRay.CheckIntersect(v0, v1, v2, out ip, ref minIntersectDistance)) { continue; } switch (GetNearestPoint(v0, v1, v2, ip)) { case 0: minIntersectVertexIndex = i0; minIntersectPosition = v0; break; case 1: minIntersectVertexIndex = i1; minIntersectPosition = v1; break; case 2: default: minIntersectVertexIndex = i2; minIntersectPosition = v2; break; } } } if (minIntersectVertexIndex >= 0) { _pos = m2w.MultiplyPoint3x4(minIntersectPosition); _idx = minIntersectVertexIndex; _vtx = vertices[minIntersectVertexIndex]; } } } } } #if DEBUG_VERTEX_SELECTOR if (_idx >= 0) { Shader.SetGlobalColor("SelectedColor", Color.red); Shader.SetGlobalInt("SelectedVid", _idx); } #endif }
/// <summary> /// Generate new index in triangle list that resides in plane /// </summary> public int GetIndexFor(int from, int to) { var oldDir = new IndexVector(from, to); int result; if (_chashedOuterLines.TryGetValue(oldDir, out result)) { return(result); } result = _meshData.Vertices.Count; _chashedOuterLines.Add(oldDir, result); float ratioIn = CalcGetRatio(from, to); { // Vertex Vector3 vFrom = _meshData.Vertices[from]; Vector3 vTo = _meshData.Vertices[to]; Vector3 vNew = Vector3.Lerp(vFrom, vTo, ratioIn); _meshData.Vertices.Add(vNew); } if (_meshData.NormalsExists) { Vector3 nFrom = _meshData.Normals[from]; Vector3 nTo = _meshData.Normals[to]; Vector3 nNew = Vector3.Slerp(nFrom, nTo, ratioIn); _meshData.Normals.Add(nNew); } if (_meshData.ColorsExists) { Color colorFrom = _meshData.Colors[from]; Color colorTo = _meshData.Colors[to]; Color colorNew = Color.Lerp(colorFrom, colorTo, ratioIn); _meshData.Colors.Add(colorNew); } if (_meshData.Colors32Exists) { Color32 colorFrom = _meshData.Colors32[from]; Color32 colorTo = _meshData.Colors32[to]; Color32 colorNew = Color32.Lerp(colorFrom, colorTo, ratioIn); _meshData.Colors32.Add(colorNew); } if (_meshData.UVExists) { AddValue(_meshData.UV, from, to, ratioIn); } if (_meshData.UV2Exists) { AddValue(_meshData.UV2, from, to, ratioIn); } if (_meshData.UV3Exists) { AddValue(_meshData.UV3, from, to, ratioIn); } if (_meshData.UV4Exists) { AddValue(_meshData.UV4, from, to, ratioIn); } if (_meshData.TangentsExists) { Vector4 vFrom = _meshData.Tangents[from]; Vector4 vTo = _meshData.Tangents[to]; Vector4 vNew = Vector4.Lerp(vFrom, vTo, ratioIn); _meshData.Tangents.Add(vNew); } if (_meshData.BoneWeightsExists) { var w1 = _meshData.BoneWeights[from]; var w2 = _meshData.BoneWeights[to]; var ws = new Dictionary <int, float>(); float ratioOut = 1 - ratioIn; if (w1.weight0 != 0) { ws.Add(w1.boneIndex0, w1.weight0 * ratioIn); } if (w1.weight1 != 0) { ws.Add(w1.boneIndex1, w1.weight1 * ratioIn); } if (w1.weight2 != 0) { ws.Add(w1.boneIndex2, w1.weight2 * ratioIn); } if (w1.weight3 != 0) { ws.Add(w1.boneIndex3, w1.weight3 * ratioIn); } if (w2.weight0 != 0) { float fA; ws.TryGetValue(w2.boneIndex0, out fA); ws[w2.boneIndex0] = fA + w2.weight0 * ratioOut; } if (w2.weight1 != 0) { float fA; ws.TryGetValue(w2.boneIndex1, out fA); ws[w2.boneIndex1] = fA + w2.weight1 * ratioOut; } if (w2.weight2 != 0) { float fA; ws.TryGetValue(w2.boneIndex2, out fA); ws[w2.boneIndex2] = fA + w2.weight2 * ratioOut; } if (w2.weight3 != 0) { float fA; ws.TryGetValue(w2.boneIndex3, out fA); ws[w2.boneIndex3] = fA + w2.weight3 * ratioOut; } var newBoneWeight = new BoneWeight(); var wsArr = ws .Where(v => v.Value != 0) .Take(4) .OrderByDescending(v => v.Value) .ToArray(); KeyValuePair <int, float>[] wsArr4 = new KeyValuePair <int, float> [4]; Array.Copy(wsArr, wsArr4, wsArr.Length); float weightSum = 0; weightSum += wsArr4[0].Value; weightSum += wsArr4[1].Value; weightSum += wsArr4[2].Value; weightSum += wsArr4[3].Value; float weightRatio = 1 / weightSum; if (wsArr.Length > 0) { newBoneWeight.boneIndex0 = wsArr[0].Key; newBoneWeight.weight0 = wsArr[0].Value * weightRatio; } if (wsArr.Length > 1) { newBoneWeight.boneIndex1 = wsArr[1].Key; newBoneWeight.weight1 = wsArr[1].Value * weightRatio; } if (wsArr.Length > 2) { newBoneWeight.boneIndex2 = wsArr[2].Key; newBoneWeight.weight2 = wsArr[2].Value * weightRatio; } if (wsArr.Length > 3) { newBoneWeight.boneIndex3 = wsArr[3].Key; newBoneWeight.weight3 = wsArr[3].Value * weightRatio; } _meshData.BoneWeights.Add(newBoneWeight); } return(result); }
/** */ public static Mesh Merge(Mesh m1, Mesh m2, List <Transform> bones, Transform[] bones2) { Mesh newMesh = new Mesh(); List <Vector3> vertices = new List <Vector3>(); vertices.AddRange(m1.vertices); vertices.AddRange(m2.vertices); newMesh.vertices = vertices.ToArray(); List <Vector2> uvs = new List <Vector2>(); uvs.AddRange(m1.uv); uvs.AddRange(m2.uv); newMesh.uv = uvs.ToArray(); List <BoneWeight> bw = new List <BoneWeight>(); bw.AddRange(m1.boneWeights); //Remap bones as necessary List <Matrix4x4> bindposes = new List <Matrix4x4>(); bindposes.AddRange(m1.bindposes); int[] remap = new int[bones2.Length]; for (int i = 0; i < remap.Length; i++) { remap[i] = bones.IndexOf(bones2[i]); if (remap[i] == -1) { remap[i] = bones.Count; bones.Add(bones2[i]); } } for (int i = 0; i < m2.boneWeights.Length; i++) { BoneWeight bwtemp = m2.boneWeights[i]; bwtemp.boneIndex0 = remap[bwtemp.boneIndex0]; if (bwtemp.boneIndex1 >= 0) { bwtemp.boneIndex1 = remap[bwtemp.boneIndex1]; } if (bwtemp.boneIndex2 >= 0) { bwtemp.boneIndex2 = remap[bwtemp.boneIndex2]; } if (bwtemp.boneIndex3 >= 0) { bwtemp.boneIndex3 = remap[bwtemp.boneIndex3]; } bw.Add(bwtemp); } newMesh.boneWeights = bw.ToArray(); newMesh.bindposes = m1.bindposes; newMesh.subMeshCount = m1.subMeshCount + m2.subMeshCount; for (int i = 0; i < m1.subMeshCount; i++) { int[] tris = m1.GetTriangles(i); newMesh.SetTriangles(tris, i); } int offset = m1.vertexCount; for (int i = 0; i < m2.subMeshCount; i++) { int[] tris = m2.GetTriangles(i); //tris.ForEach(index => index+offset); for (int t = 0; t < tris.Length; t++) { tris[t] += offset; } newMesh.SetTriangles(tris, m1.subMeshCount + i); } newMesh.RecalculateBounds(); newMesh.RecalculateNormals(); return(newMesh); }
public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx) { //Load file contents M2 file = new M2(); file.LoadFile(ctx.assetPath); //Prepare blank asset GameObject model = new GameObject(); model.AddComponent <Animator>(); model.AddComponent <SkinnedMeshRenderer>(); SkinnedMeshRenderer renderer = model.GetComponent <SkinnedMeshRenderer>(); Mesh mesh = new Mesh(); mesh.name = file.Name + "_mesh"; //Fill vertex data Vector3[] vertices = new Vector3[file.Vertices.Length]; Vector3[] normals = new Vector3[file.Vertices.Length]; BoneWeight[] weights = new BoneWeight[file.Vertices.Length]; Vector2[] uv = new Vector2[file.Vertices.Length]; Vector2[] uv2 = new Vector2[file.Vertices.Length]; for (int i = 0; i < file.Vertices.Length; i++) { vertices[i] = new Vector3(-file.Vertices[i].Position.X / 2, file.Vertices[i].Position.Z / 2, -file.Vertices[i].Position.Y / 2); normals[i] = new Vector3(-file.Vertices[i].Normal.X, file.Vertices[i].Normal.Z, -file.Vertices[i].Normal.Y); BoneWeight weight = new BoneWeight { boneIndex0 = file.Vertices[i].Bones[0], boneIndex1 = file.Vertices[i].Bones[1], boneIndex2 = file.Vertices[i].Bones[2], boneIndex3 = file.Vertices[i].Bones[3], weight0 = file.Vertices[i].Weights[0] / 255f, weight1 = file.Vertices[i].Weights[1] / 255f, weight2 = file.Vertices[i].Weights[2] / 255f, weight3 = file.Vertices[i].Weights[3] / 255f }; weights[i] = weight; uv[i] = new Vector2(file.Vertices[i].UV[0].X, 1 - file.Vertices[i].UV[0].Y); uv2[i] = new Vector2(file.Vertices[i].UV[1].X, 1 - file.Vertices[i].UV[1].Y); } mesh.vertices = vertices; mesh.normals = normals; mesh.boneWeights = weights; mesh.uv = uv; mesh.uv2 = uv2; //Fill Submesh data mesh.subMeshCount = file.Skin.Submeshes.Length; for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = new int[file.Skin.Submeshes[i].Count]; for (int j = 0; j < triangles.Length; j++) { triangles[j] = file.Skin.Indices[file.Skin.Submeshes[i].Start + j]; } mesh.SetTriangles(triangles, i); } //Generate bones Transform[] bones = new Transform[file.Skeleton.Bones.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = new GameObject("Bone" + i).transform; bones[i].position = new Vector3(-file.Skeleton.Bones[i].Pivot.X / 2, file.Skeleton.Bones[i].Pivot.Z / 2, -file.Skeleton.Bones[i].Pivot.Y / 2); } GameObject skeleton = new GameObject("Skeleton"); for (int i = 0; i < bones.Length; i++) { if (file.Skeleton.Bones[i].Parent == -1) { bones[i].parent = skeleton.transform; } else { bones[i].parent = bones[file.Skeleton.Bones[i].Parent]; } } Matrix4x4[] bind = new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; i++) { bind[i] = bones[i].worldToLocalMatrix * model.transform.localToWorldMatrix; } skeleton.transform.parent = model.transform; renderer.materials = new Material[mesh.subMeshCount]; renderer.sharedMesh = mesh; renderer.bones = bones; renderer.rootBone = bones[0]; mesh.bindposes = bind; //Seralize data in json so they can be accessible at runtime TextAsset json = new TextAsset(JsonConvert.SerializeObject(file)); json.name = file.Name + "_data"; model.AddComponent <M2Model>(); model.GetComponent <M2Model>().json = json; //Fill particle effect data if (file.Particles.Length > 0) { GameObject[] particles = new GameObject[file.Particles.Length]; for (int i = 0; i < particles.Length; i++) { particles[i] = ParticleEffect(file.Particles[i]); particles[i].transform.parent = bones[file.Particles[i].Bone]; particles[i].transform.localPosition = Vector3.zero; particles[i].name = "Particle" + i; ctx.AddObjectToAsset(particles[i].name, particles[i]); } } //Populate the asset ctx.AddObjectToAsset(file.Name, model); ctx.AddObjectToAsset(mesh.name, mesh); ctx.AddObjectToAsset(skeleton.name, skeleton); ctx.AddObjectToAsset(json.name, json); }
void GenerateSkinning() { SkinTools t = target as SkinTools; SkinToolsData data = t.Data; bool referenceExist = data.ReferenceSMR != null; Vector3[] rVertices = data.SourceGeometryMF.sharedMesh.vertices; Vector3[] rNormals = data.SourceGeometryMF.sharedMesh.normals; Vector3[] rWorldVertices = new Vector3[rVertices.Length]; Vector2[] rMapVertices = data.SourceGeometryMF.sharedMesh.uv; Matrix4x4 smLTW = data.SourceGeometryMF.transform.localToWorldMatrix; Matrix4x4 tWTL = t.transform.worldToLocalMatrix; for (int v = 0; v < rVertices.Length; v++) { rWorldVertices[v] = smLTW.MultiplyPoint3x4(rVertices[v]); rVertices[v] = tWTL.MultiplyPoint3x4(rWorldVertices[v]); rNormals[v] = smLTW.MultiplyVector(rNormals[v]); rNormals[v] = tWTL.MultiplyVector(rNormals[v]); } data.ResultMesh = Instantiate(data.SourceGeometryMF.sharedMesh) as Mesh; string[] splittedPath = data.OutputMeshPath.Split("/.".ToCharArray()); string meshName = splittedPath[splittedPath.Length - 2]; data.ResultMesh.name = meshName; data.ResultMesh.vertices = rVertices; data.ResultMesh.normals = rNormals; data.ResultMesh.RecalculateBounds(); data.resultSMR.localBounds = new Bounds(data.ResultMesh.bounds.center, data.ResultMesh.bounds.size * 2); SourceSMRCollider _collider = null; SourceSMRCollider _icollider = null; BoneWeight[] existingWeights = null; Transform[] sourceBones = null; int[] sourceSMRTris = null; Ray[] frays = null; bool[] excludedTriangles = null; if (referenceExist) { _collider = new SourceSMRCollider(data.ReferenceSMR, false); _icollider = new SourceSMRCollider(data.ReferenceSMR, true); existingWeights = data.ReferenceSMR.sharedMesh.boneWeights; sourceBones = data.ReferenceSMR.bones; sourceSMRTris = data.ReferenceSMR.sharedMesh.triangles; excludedTriangles = new bool[data.ReferenceSMR.sharedMesh.triangles.Length / 3]; if (data.ReferenceSMRGeometry != null && data.ReferenceSMRGeometry.IsValid) { excludedTriangles = data.ReferenceSMRGeometry.ExcludedTris; } if (data.BakingQuality == 0) { frays = new Ray[ResourceHolder.Rays362.Length]; for (int i = 0; i < frays.Length; i++) { frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays362[i]); } } else if (data.BakingQuality == 1) { frays = new Ray[ResourceHolder.Rays642.Length]; for (int i = 0; i < frays.Length; i++) { frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays642[i]); } } else if (data.BakingQuality == 2) { frays = new Ray[ResourceHolder.Rays1002.Length]; for (int i = 0; i < frays.Length; i++) { frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays1002[i]); } } } ExtBoneWeight[] ebws = new ExtBoneWeight[rWorldVertices.Length]; List <Transform> newBonesList = new List <Transform>(); for (int b = 0; b < data.MapBones.Count; b++) { newBonesList.Add(data.MapBones[b].Tr); } EditorUtility.DisplayProgressBar("Bake", "Baking vertices", 0); int progressPercent = 0; for (int v = 0; v < rWorldVertices.Length; v++) { ebws[v] = new ExtBoneWeight( ); if (data.SourceGeometry.HasUV0) { Vector2 uv = rMapVertices[v]; for (int b = 0; b < data.MapBones.Count; b++) { float val = data.MapBones[b].Map.GetPixelBilinear(uv.x, uv.y).grayscale; ebws[v].AddMask(data.MapBones[b].Tr, val); } } if (referenceExist) { RaycastHit hit = GetNearestHit(frays, _collider._Collider, _icollider._Collider, rWorldVertices[v], excludedTriangles); BoneWeight bwA = existingWeights [sourceSMRTris[hit.triangleIndex * 3]]; BoneWeight bwB = existingWeights [sourceSMRTris[hit.triangleIndex * 3 + 1]]; BoneWeight bwC = existingWeights [sourceSMRTris[hit.triangleIndex * 3 + 2]]; for (int i = 0; i < 4; i++) { Transform nbA = sourceBones[bwA.GetBoneIdx(i)]; Transform nbB = sourceBones[bwB.GetBoneIdx(i)]; Transform nbC = sourceBones[bwC.GetBoneIdx(i)]; if (!data.ReferenceSMRBones[nbA].Excluded) { if (!newBonesList.Contains(nbA)) { newBonesList.Add(nbA); } ebws[v].Add(nbA, bwA.GetWeight(i) * hit.barycentricCoordinate.x, 0); } if (!data.ReferenceSMRBones[nbB].Excluded) { if (!newBonesList.Contains(nbB)) { newBonesList.Add(nbB); } ebws[v].Add(nbB, bwB.GetWeight(i) * hit.barycentricCoordinate.y, 0); } if (!data.ReferenceSMRBones[nbC].Excluded) { if (!newBonesList.Contains(nbC)) { newBonesList.Add(nbC); } ebws[v].Add(nbC, bwC.GetWeight(i) * hit.barycentricCoordinate.z, 0); } } } float progress = v / (float)rWorldVertices.Length; int percent = Mathf.FloorToInt(progress * 100); if (progressPercent != percent) { progressPercent = percent; string progressBarName = string.Format("Bake {0}", data.ResultMesh.name); string progressInfo = string.Format("baking vertices {0} of {1} with {2} quality ", v, rWorldVertices.Length, data.BakingQualityNames[data.BakingQuality]); EditorUtility.DisplayProgressBar(progressBarName, progressInfo, progress); } } EditorUtility.ClearProgressBar(); BoneWeight[] newweights = new BoneWeight[rWorldVertices.Length]; Transform[] newBonesArray = newBonesList.ToArray(); for (int w = 0; w < ebws.Length; w++) { ebws[w].FillIndeces(newBonesArray); newweights[w] = ebws[w].GetClampedBW(); } data.resultSMR.bones = newBonesArray; Matrix4x4[] bindBones = new Matrix4x4[newBonesArray.Length]; for (int b = 0; b < newBonesArray.Length; b++) { bindBones[b] = newBonesArray[b].worldToLocalMatrix * t.transform.localToWorldMatrix; } data.ResultMesh.bindposes = bindBones; data.ResultMesh.boneWeights = newweights; if (referenceExist) { _collider.Destroy(); _icollider.Destroy(); } AssetDatabase.DeleteAsset(data.OutputMeshPath); AssetDatabase.CreateAsset(data.ResultMesh, data.OutputMeshPath); AssetDatabase.SaveAssets(); data.ResultMesh = AssetDatabase.LoadAssetAtPath(data.OutputMeshPath, typeof(Mesh)) as Mesh; data.resultSMR.sharedMesh = data.ResultMesh; data.UpdateResultInfo(); data.ApplyResultVisual(); }
public static Mesh ExtractSubmesh(Mesh mesh, int submeshIndex) { MeshTopology topology = mesh.GetTopology(submeshIndex); if (topology != MeshTopology.Triangles) { Debug.LogWarningFormat("Extract Submesh method could handle triangle topology only. Current topology is {0}. Mesh name {1} submeshIndex {2}", topology, mesh, submeshIndex); return(mesh); } int[] triangles = mesh.GetTriangles(submeshIndex); int[] newTriangles = new int[triangles.Length]; Dictionary <int, int> remapping = new Dictionary <int, int>(); int newIndex = 0; for (int i = 0; i < triangles.Length; ++i) { int index = triangles[i]; if (!remapping.ContainsKey(index)) { newTriangles[i] = newIndex; remapping.Add(index, newIndex); newIndex++; } else { newTriangles[i] = remapping[index]; } } Vector3[] vertices = mesh.vertices; Vector3[] newVertices = new Vector3[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newVertices[kvp.Value] = vertices[kvp.Key]; } Mesh result = new Mesh(); result.indexFormat = mesh.indexFormat; result.vertices = newVertices; Color[] colors = mesh.colors; if (colors.Length == vertices.Length) { Color[] newColors = new Color[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newColors[kvp.Value] = colors[kvp.Key]; } result.colors = newColors; } else { if (colors.Length != 0) { Debug.LogWarning("colors.Length != vertices.Length"); } } Color32[] colors32 = mesh.colors32; if (colors32.Length == vertices.Length) { Color32[] newColors32 = new Color32[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newColors32[kvp.Value] = colors32[kvp.Key]; } result.colors32 = newColors32; } else { if (colors32.Length != 0) { Debug.LogWarning("colors32.Length != vertices.Length"); } } BoneWeight[] boneWeights = mesh.boneWeights; if (boneWeights.Length == vertices.Length) { BoneWeight[] newBoneWeights = new BoneWeight[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newBoneWeights[kvp.Value] = boneWeights[kvp.Key]; } result.boneWeights = newBoneWeights; } else { if (boneWeights.Length != 0) { Debug.LogWarning("boneWeights.Length != vertices.Length"); } } Vector3[] normals = mesh.normals; if (normals.Length == vertices.Length) { Vector3[] newNormals = new Vector3[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newNormals[kvp.Value] = normals[kvp.Key]; } result.normals = newNormals; } else { if (normals.Length != 0) { Debug.LogWarning("normals.Length != vertices.Length"); } } Vector4[] tangents = mesh.tangents; if (tangents.Length == vertices.Length) { Vector4[] newTangents = new Vector4[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newTangents[kvp.Value] = tangents[kvp.Key]; } result.tangents = newTangents; } else { if (tangents.Length != 0) { Debug.LogWarning("tangents.Length != vertices.Length"); } } Vector2[] uv = mesh.uv; if (uv.Length == vertices.Length) { Vector2[] newUv = new Vector2[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newUv[kvp.Value] = uv[kvp.Key]; } result.uv = newUv; } else { if (uv.Length != 0) { Debug.LogWarning("uv.Length != vertices.Length"); } } Vector2[] uv2 = mesh.uv2; if (uv2.Length == vertices.Length) { Vector2[] newUv2 = new Vector2[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newUv2[kvp.Value] = uv2[kvp.Key]; } result.uv2 = newUv2; } else { if (uv2.Length != 0) { Debug.LogWarning("uv2.Length != vertices.Length"); } } Vector2[] uv3 = mesh.uv3; if (uv3.Length == vertices.Length) { Vector2[] newUv3 = new Vector2[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newUv3[kvp.Value] = uv3[kvp.Key]; } result.uv3 = newUv3; } else { if (uv3.Length != 0) { Debug.LogWarning("uv3.Length != vertices.Length"); } } Vector2[] uv4 = mesh.uv4; if (uv4.Length == vertices.Length) { Vector2[] newUv4 = new Vector2[newIndex]; foreach (KeyValuePair <int, int> kvp in remapping) { newUv4[kvp.Value] = uv4[kvp.Key]; } result.uv4 = newUv4; } else { if (uv4.Length != 0) { Debug.LogWarning("uv4.Length != vertices.Length"); } } result.triangles = newTriangles; return(result); }
public OvrAvatarAssetMesh(UInt64 _assetId, IntPtr asset) { assetID = _assetId; ovrAvatarMeshAssetData meshAssetData = CAPI.ovrAvatarAsset_GetMeshData(asset); mesh = new Mesh(); mesh.name = "Procedural Geometry for asset " + _assetId; long vertexCount = (long)meshAssetData.vertexCount; Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; Vector2[] uv = new Vector2[vertexCount]; Color[] colors = new Color[vertexCount]; BoneWeight[] boneWeights = new BoneWeight[vertexCount]; long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertex)); long vertexBufferStart = meshAssetData.vertexBuffer.ToInt64(); for (long i = 0; i < vertexCount; i++) { long offset = vertexSize * i; ovrAvatarMeshVertex vertex = (ovrAvatarMeshVertex)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertex)); vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); uv[i] = new Vector2(vertex.u, vertex.v); colors[i] = new Color(0, 0, 0, 1); boneWeights[i].boneIndex0 = vertex.blendIndices[0]; boneWeights[i].boneIndex1 = vertex.blendIndices[1]; boneWeights[i].boneIndex2 = vertex.blendIndices[2]; boneWeights[i].boneIndex3 = vertex.blendIndices[3]; boneWeights[i].weight0 = vertex.blendWeights[0]; boneWeights[i].weight1 = vertex.blendWeights[1]; boneWeights[i].weight2 = vertex.blendWeights[2]; boneWeights[i].weight3 = vertex.blendWeights[3]; } mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.tangents = tangents; mesh.boneWeights = boneWeights; mesh.colors = colors; skinnedBindPose = meshAssetData.skinnedBindPose; ulong indexCount = meshAssetData.indexCount; Int16[] indices = new Int16[indexCount]; IntPtr indexBufferPtr = meshAssetData.indexBuffer; Marshal.Copy(indexBufferPtr, indices, 0, (int)indexCount); Int32[] triangles = new Int32[indexCount]; for (ulong i = 0; i < indexCount; i += 3) { triangles[i + 2] = (Int32)indices[i]; triangles[i + 1] = (Int32)indices[i + 1]; triangles[i] = (Int32)indices[i + 2]; } mesh.triangles = triangles; UInt32 jointCount = skinnedBindPose.jointCount; jointNames = new string[jointCount]; for (UInt32 i = 0; i < jointCount; i++) { jointNames[i] = Marshal.PtrToStringAnsi(skinnedBindPose.jointNames[i]); } }
public static void CalculateBarycentric(Mesh mesh) { int[] tris = mesh.triangles; List <int> err; Color32[] barycentric = GetBarycentricCoordinates(mesh.vertexCount, tris, out err); List <Color32> colors = new List <Color32>(barycentric); if (err.Count > 0) { List <Vector3> vertices = new List <Vector3>(mesh.vertices); List <Vector3> normals = new List <Vector3>(mesh.normals); List <Vector4> tangents = new List <Vector4>(mesh.tangents); List <Vector2> uv = new List <Vector2>(mesh.uv); List <Vector2> uv2 = new List <Vector2>(mesh.uv2); List <Vector2> uv3 = new List <Vector2>(mesh.uv3); List <Vector2> uv4 = new List <Vector2>(mesh.uv4); List <BoneWeight> boneWeights = new List <BoneWeight>(mesh.boneWeights); int[] triangles = tris; for (int i = 0; i < err.Count; ++i) { int t = err[i]; int i0 = triangles[t]; int i1 = triangles[t + 1]; int i2 = triangles[t + 2]; Vector3 v0 = vertices[i0]; Vector3 v1 = vertices[i1]; Vector3 v2 = vertices[i2]; triangles[t] = vertices.Count; vertices.Add(v0); triangles[t + 1] = vertices.Count; vertices.Add(v1); triangles[t + 2] = vertices.Count; vertices.Add(v2); colors.Add(palette[0]); colors.Add(palette[1]); colors.Add(palette[2]); if (normals.Count > 0) { Vector3 n0 = normals[i0]; Vector3 n1 = normals[i1]; Vector3 n2 = normals[i2]; normals.Add(n0); normals.Add(n1); normals.Add(n2); } if (tangents.Count > 0) { Vector4 t0 = tangents[i0]; Vector4 t1 = tangents[i1]; Vector4 t2 = tangents[i2]; tangents.Add(t0); tangents.Add(t1); tangents.Add(t2); } if (uv.Count > 0) { Vector2 u0 = uv[i0]; Vector2 u1 = uv[i1]; Vector2 u2 = uv[i2]; uv.Add(u0); uv.Add(u1); uv.Add(u2); } if (uv2.Count > 0) { Vector2 u0 = uv2[i0]; Vector2 u1 = uv2[i1]; Vector2 u2 = uv2[i2]; uv2.Add(u0); uv2.Add(u1); uv2.Add(u2); } if (uv3.Count > 0) { Vector2 u0 = uv3[i0]; Vector2 u1 = uv3[i1]; Vector2 u2 = uv3[i2]; uv3.Add(u0); uv3.Add(u1); uv3.Add(u2); } if (uv4.Count > 0) { Vector2 u0 = uv4[i0]; Vector2 u1 = uv4[i1]; Vector2 u2 = uv4[i2]; uv4.Add(u0); uv4.Add(u1); uv4.Add(u2); } if (boneWeights.Count > 0) { BoneWeight b0 = boneWeights[i0]; BoneWeight b1 = boneWeights[i1]; BoneWeight b2 = boneWeights[i2]; boneWeights.Add(b0); boneWeights.Add(b1); boneWeights.Add(b2); } } mesh.SetVertices(vertices); int offset = 0; for (int s = 0; s < mesh.subMeshCount; ++s) { int[] stris = mesh.GetTriangles(s); System.Array.Copy(tris, offset, stris, 0, stris.Length); offset += stris.Length; mesh.SetTriangles(stris, s); } mesh.SetColors(colors); mesh.SetNormals(normals); mesh.SetTangents(tangents); mesh.SetUVs(0, uv); mesh.SetUVs(1, uv2); mesh.SetUVs(2, uv3); mesh.SetUVs(3, uv4); mesh.boneWeights = boneWeights.ToArray(); } else { mesh.SetColors(colors); } }
public Base BaseFromGameObject(GameObject target) { Matrix4x4 world = target.transform.localToWorldMatrix; Vector3 lastPos = target.transform.position; PdxAnimationPlayer player = target.GetComponent <PdxAnimationPlayer>(); if (player != null) { player.SetTpose(); } target.transform.position = Vector3.zero; List <Transform> shapes = new List <Transform>(); FindTagInChildren(shapes, target.transform, "Shape", target.transform); Base _base = new Base("PdxData", "object"); Base _pdxasset = new Base("pdxasset", "int", _base); _pdxasset.value = new List <Base.Data>() { Base.Data.Int(1), Base.Data.Int(0) }; Base _object = new Base("object", "object", _base); foreach (Transform sh in shapes) { MeshFilter mf = sh.GetComponent <MeshFilter>(); MeshRenderer mr = sh.GetComponent <MeshRenderer>(); SkinnedMeshRenderer smr = sh.GetComponent <SkinnedMeshRenderer>(); PdxShape shapeData = sh.GetComponent <PdxShape>(); bool isCollider = sh.gameObject.tag == "Collider"; bool skinned = smr != null; Mesh mesh; Material mat; if (isCollider) { mesh = mf.mesh; mat = null; } else if (skinned) { mesh = smr.sharedMesh; mat = smr.material; } else { mesh = mf.mesh; mat = mr.material; } Base _shape = _object.subNodes.ContainsKey(sh.name) ? _object.subNodes[sh.name] : new Base(sh.name.Replace(" Instance", ""), "object", _object); Base _mesh = new Base("mesh", "object", _shape); Base _p = new Base("p", "float", _mesh); foreach (Vector3 p in mesh.vertices) { Vector3 pW = world.MultiplyPoint3x4(p); _p.value.Add(Base.Data.Float(pW.x)); _p.value.Add(Base.Data.Float(pW.y)); _p.value.Add(Base.Data.Float(pW.z)); } if (!isCollider) { Base _n = new Base("n", "float", _mesh); foreach (Vector3 n in mesh.normals) { Vector3 nW = world.MultiplyPoint3x4(n); _n.value.Add(Base.Data.Float(nW.x)); _n.value.Add(Base.Data.Float(nW.y)); _n.value.Add(Base.Data.Float(nW.z)); } Base _ta = new Base("ta", "float", _mesh); foreach (Vector4 ta in mesh.tangents) { Vector4 taW = world * ta; _ta.value.Add(Base.Data.Float(taW.x)); _ta.value.Add(Base.Data.Float(taW.y)); _ta.value.Add(Base.Data.Float(taW.z)); _ta.value.Add(Base.Data.Float(taW.w)); } Base _uv = new Base("u0", "float", _mesh); foreach (Vector2 uv in mesh.uv) { _uv.value.Add(Base.Data.Float(uv.x)); _uv.value.Add(Base.Data.Float(uv.y)); } if (mesh.uv2 != null && mesh.uv2.Length > 0) { Base _uv1 = new Base("u1", "float", _mesh); foreach (Vector2 uv2 in mesh.uv2) { _uv1.value.Add(Base.Data.Float(uv2.x)); _uv1.value.Add(Base.Data.Float(uv2.y)); } } } Base _tri = new Base("tri", "int", _mesh); foreach (int tri in mesh.triangles) { _tri.value.Add(Base.Data.Int(tri)); } Base _aabb = new Base("aabb", "object", _mesh); Base _min = new Base("min", "float", _aabb); _min.value.Add(Base.Data.Float(mesh.bounds.min.x)); _min.value.Add(Base.Data.Float(mesh.bounds.min.y)); _min.value.Add(Base.Data.Float(mesh.bounds.min.z)); Base _max = new Base("max", "float", _aabb); _max.value.Add(Base.Data.Float(mesh.bounds.max.x)); _max.value.Add(Base.Data.Float(mesh.bounds.max.y)); _max.value.Add(Base.Data.Float(mesh.bounds.max.z)); Base _material = new Base("material", "object", _mesh); Base _shader = new Base("shader", "string", _material); _shader.nullByteString = true; if (!isCollider) { _shader.value.Add(Base.Data.String(shapeData.shader)); if (!string.IsNullOrEmpty(shapeData.diffuse)) { Base _diff = new Base("diff", "string", _material); _diff.nullByteString = true; _diff.value.Add(Base.Data.String(Path.GetFileName(shapeData.diffuse))); } if (!string.IsNullOrEmpty(shapeData.normal)) { Base _normal = new Base("n", "string", _material); _normal.nullByteString = true; _normal.value.Add(Base.Data.String(Path.GetFileName(shapeData.normal))); } if (!string.IsNullOrEmpty(shapeData.specular)) { Base _spec = new Base("spec", "string", _material); _spec.nullByteString = true; _spec.value.Add(Base.Data.String(Path.GetFileName(shapeData.specular))); } } else { _shader.value.Add(Base.Data.String("Collision")); } if (skinned) { Dictionary <Transform, int> newBoneIndices = new Dictionary <Transform, int>(); Dictionary <int, Transform> oldBoneIndices = new Dictionary <int, Transform>(); if (!_shape.subNodes.ContainsKey("skeleton")) { Transform root = null; Base _skeleton = new Base("skeleton", "object", _shape); Dictionary <string, Base> nameBones = new Dictionary <string, Base>(); foreach (Transform b in smr.bones) { oldBoneIndices.Add(Array.IndexOf(smr.bones, b), b); if (b.name.ToLower().Equals("root")) { root = b; } Base _bone = new Base(b.name, "object"); Base _btx = new Base("tx", "float", _bone); Matrix4x4 m = b.localToWorldMatrix.inverse; _btx.value = new List <Base.Data>() { new Base.Data() { f = m.m00 }, new Base.Data() { f = m.m10 }, new Base.Data() { f = m.m20 }, //new Base.Data() { f = m.m03 }, new Base.Data() { f = m.m01 }, new Base.Data() { f = m.m11 }, new Base.Data() { f = m.m21 }, //new Base.Data() { f = m.m13 }, new Base.Data() { f = m.m02 }, new Base.Data() { f = m.m12 }, new Base.Data() { f = m.m22 }, //new Base.Data() { f = m.m23 }, new Base.Data() { f = m.m03 }, new Base.Data() { f = m.m13 }, new Base.Data() { f = m.m23 }, //new Base.Data() { f = m.m33 }, }; nameBones.Add(b.name, _bone); } List <Transform> hierBones = new List <Transform>(); ObjectHierarchy(hierBones, root); foreach (var hb in hierBones) { newBoneIndices.Add(hb, hierBones.IndexOf(hb)); Base _bone = nameBones[hb.name]; Base _bix = new Base("ix", "int", _bone); _bix.value.Add(Base.Data.Int(hierBones.IndexOf(hb))); _skeleton.Add(_bone); if (hb != smr.rootBone) { Base _bpa = new Base("pa", "int", _bone); _bpa.value.Add(Base.Data.Int(hierBones.IndexOf(hb.parent))); } } } Base _skin = new Base("skin", "object", _mesh); Base _bonesPerVert = new Base("bones", "int", _skin); int num = 1; foreach (BoneWeight bw in mesh.boneWeights) { if (num < 2 && bw.weight1 > 0) { num = 2; } if (num < 3 && bw.weight2 > 0) { num = 3; } if (num < 4 && bw.weight3 > 0) { num = 4; break; } } _bonesPerVert.value.Add(Base.Data.Int(num)); int ixCount = mesh.vertexCount; Base _ix = new Base("ix", "int", _skin); Base _w = new Base("w", "float", _skin); for (int i = 0; i < ixCount; i++) { BoneWeight w = mesh.boneWeights[i]; int bi0 = newBoneIndices[oldBoneIndices[w.boneIndex0]]; int bi1 = newBoneIndices[oldBoneIndices[w.boneIndex1]]; int bi2 = newBoneIndices[oldBoneIndices[w.boneIndex2]]; int bi3 = newBoneIndices[oldBoneIndices[w.boneIndex3]]; _ix.value.Add(Base.Data.Int((bi0 == 0 && w.weight0 == 0) ? -1 : bi0)); _ix.value.Add(Base.Data.Int((bi1 == 0 && w.weight1 == 0) ? -1 : bi1)); _ix.value.Add(Base.Data.Int((bi2 == 0 && w.weight2 == 0) ? -1 : bi2)); _ix.value.Add(Base.Data.Int((bi3 == 0 && w.weight3 == 0) ? -1 : bi3)); _w.value.Add(Base.Data.Float(w.weight0)); _w.value.Add(Base.Data.Float(w.weight1)); _w.value.Add(Base.Data.Float(w.weight2)); _w.value.Add(Base.Data.Float(w.weight3)); } } } Base _locator = new Base("locator", "object", _base); List <Transform> locators = new List <Transform>(); FindTagInChildren(locators, target.transform, "Locator", target.transform); foreach (Transform loc in locators) { Base _loc = new Base(loc.name, "object", _locator); Base _p = new Base("p", "float", _loc); Base _q = new Base("q", "float", _loc); Base _pa = new Base("pa", "string", _loc); _pa.nullByteString = true; Vector3 pos = loc.transform.localPosition; Quaternion rot = loc.transform.localRotation; _p.value.Add(Base.Data.Float(pos.x)); _p.value.Add(Base.Data.Float(pos.y)); _p.value.Add(Base.Data.Float(pos.z)); _q.value.Add(Base.Data.Float(rot.x)); _q.value.Add(Base.Data.Float(rot.y)); _q.value.Add(Base.Data.Float(rot.z)); _q.value.Add(Base.Data.Float(rot.w)); _pa.value.Add(Base.Data.String(loc.transform.parent.name)); } target.transform.position = lastPos; return(_base); }
// multiple submesh sharing same VertexBuffer private static MeshContext _ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) { var context = new MeshContext(); { var prim = gltfMesh.primitives.First(); context.positions = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ()); // normal if (prim.attributes.NORMAL != -1) { context.normals = ctx.GLTF.GetArrayFromAccessor <Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ()); } // tangent if (prim.attributes.TANGENT != -1) { context.tangents = ctx.GLTF.GetArrayFromAccessor <Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ()); } // uv if (prim.attributes.TEXCOORD_0 != -1) { context.uv = ctx.GLTF.GetArrayFromAccessor <Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()); } else { // for inconsistent attributes in primitives context.uv = new Vector2[context.positions.Length]; } // color if (prim.attributes.COLOR_0 != -1) { context.colors = ctx.GLTF.GetArrayFromAccessor <Color>(prim.attributes.COLOR_0); } // skin if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1) { var joints0 = ctx.GLTF.GetArrayFromAccessor <UShort4>(prim.attributes.JOINTS_0); // uint4 var weights0 = ctx.GLTF.GetArrayFromAccessor <Float4>(prim.attributes.WEIGHTS_0); for (int i = 0; i < weights0.Length; ++i) { weights0[i] = weights0[i].One(); } for (int j = 0; j < joints0.Length; ++j) { var bw = new BoneWeight(); bw.boneIndex0 = joints0[j].x; bw.weight0 = weights0[j].x; bw.boneIndex1 = joints0[j].y; bw.weight1 = weights0[j].y; bw.boneIndex2 = joints0[j].z; bw.weight2 = weights0[j].z; bw.boneIndex3 = joints0[j].w; bw.weight3 = weights0[j].w; context.boneWeights.Add(bw); } } // blendshape if (prim.targets != null && prim.targets.Count > 0) { context.blendShapes.AddRange(prim.targets.Select((x, i) => new BlendShape( i < prim.extras.targetNames.Count && !string.IsNullOrEmpty(prim.extras.targetNames[i]) ? prim.extras.targetNames[i] : i.ToString()))); for (int i = 0; i < prim.targets.Count; ++i) { //var name = string.Format("target{0}", i++); var primTarget = prim.targets[i]; var blendShape = context.blendShapes[i]; if (primTarget.POSITION != -1) { blendShape.Positions.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.POSITION), x => x.ReverseZ()); } if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.NORMAL), x => x.ReverseZ()); } if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( ctx.GLTF.GetArrayFromAccessor <Vector3>(primTarget.TANGENT), x => x.ReverseZ()); } } } } foreach (var prim in gltfMesh.primitives) { if (prim.indices == -1) { context.subMeshes.Add(TriangleUtil.FlipTriangle(Enumerable.Range(0, context.positions.Length)).ToArray()); } else { var indices = ctx.GLTF.GetIndices(prim.indices); context.subMeshes.Add(indices); } // material context.materialIndices.Add(prim.material); } return(context); }
public static ReadOnlyBoneWeight AsReadOnly(this BoneWeight self) => new ReadOnlyBoneWeight(self);
public void CombineMeshes(ovrAvatarComponent component) { List <Transform> bones = new List <Transform>(); List <BoneWeight> boneWeights = new List <BoneWeight>(); List <CombineInstance> combineInstances = new List <CombineInstance>(); List <Matrix4x4> bindposes = new List <Matrix4x4>(); List <Color> colors = new List <Color>(); RootMeshComponent = gameObject.AddComponent <SkinnedMeshRenderer>(); RootMeshComponent.quality = SkinQuality.Bone4; RootMeshComponent.updateWhenOffscreen = true; int boneOffset = 0; for (UInt32 renderPartIndex = 0; renderPartIndex < RenderParts.Count; renderPartIndex++) { var renderPart = RenderParts[(int)renderPartIndex]; if (RootMeshComponent.sharedMaterial == null) { RootMeshComponent.sharedMaterial = renderPart.mesh.sharedMaterial; materialStates.Add(RootMeshComponent.sharedMaterial, new ovrAvatarMaterialState()); RootMeshComponent.sortingLayerID = renderPart.mesh.sortingLayerID; RootMeshComponent.gameObject.layer = renderPart.gameObject.layer; } colors.AddRange(ThreadData[renderPartIndex].MeshColors); foreach (BoneWeight bw in renderPart.mesh.sharedMesh.boneWeights) { BoneWeight bWeight = bw; bWeight.boneIndex0 += boneOffset; bWeight.boneIndex1 += boneOffset; bWeight.boneIndex2 += boneOffset; bWeight.boneIndex3 += boneOffset; boneWeights.Add(bWeight); } boneOffset += renderPart.mesh.bones.Length; foreach (Transform bone in renderPart.mesh.bones) { bones.Add(bone); } CombineInstance ci = new CombineInstance(); ci.mesh = renderPart.mesh.sharedMesh; ci.transform = renderPart.mesh.transform.localToWorldMatrix; combineInstances.Add(ci); for (int b = 0; b < renderPart.mesh.bones.Length; b++) { bindposes.Add(renderPart.mesh.sharedMesh.bindposes[b]); } Destroy(renderPart.mesh); renderPart.mesh = null; } RootMeshComponent.sharedMesh = new Mesh(); RootMeshComponent.sharedMesh.name = transform.name + "_combined_mesh"; RootMeshComponent.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, true); RootMeshComponent.bones = bones.ToArray(); RootMeshComponent.sharedMesh.boneWeights = boneWeights.ToArray(); RootMeshComponent.sharedMesh.bindposes = bindposes.ToArray(); RootMeshComponent.sharedMesh.colors = colors.ToArray(); RootMeshComponent.rootBone = bones[0]; RootMeshComponent.sharedMesh.RecalculateBounds(); }
internal static Mesh ExtractWeightedMeshAttachment (string name, MeshAttachment attachment, int slotIndex, SkeletonData skeletonData, List<Transform> boneList, Mesh mesh = null) { if (!attachment.IsWeighted()) throw new System.ArgumentException("Mesh is not weighted.", "attachment"); Skeleton skeleton = new Skeleton(skeletonData); skeleton.UpdateWorldTransform(); float[] floatVerts = new float[attachment.WorldVerticesLength]; attachment.ComputeWorldVertices(skeleton.Slots.Items[slotIndex], floatVerts); Vector2[] uvs = ExtractUV(attachment.UVs); Vector3[] verts = ExtractVerts(floatVerts); int[] triangles = attachment.Triangles; Color color = new Color(attachment.R, attachment.G, attachment.B, attachment.A); mesh = mesh ?? new Mesh(); mesh.triangles = new int[0]; mesh.vertices = verts; mesh.uv = uvs; mesh.triangles = triangles; Color[] colors = new Color[verts.Length]; for (int i = 0; i < verts.Length; i++) colors[i] = color; mesh.colors = colors; mesh.name = name; mesh.RecalculateNormals(); mesh.RecalculateBounds(); // Handle weights and binding var weightTable = new Dictionary<int, BoneWeightContainer>(); var warningBuilder = new System.Text.StringBuilder(); int[] bones = attachment.Bones; float[] weights = attachment.Vertices; for (int w = 0, v = 0, b = 0, n = bones.Length; v < n; w += 2) { int nn = bones[v++] + v; for (; v < nn; v++, b += 3) { Transform boneTransform = boneList[bones[v]]; int vIndex = w / 2; BoneWeightContainer container; if (weightTable.ContainsKey(vIndex)) container = weightTable[vIndex]; else { container = new BoneWeightContainer(); weightTable.Add(vIndex, container); } float weight = weights[b + 2]; container.Add(boneTransform, weight); } } BoneWeight[] boneWeights = new BoneWeight[weightTable.Count]; for (int i = 0; i < weightTable.Count; i++) { BoneWeight bw = new BoneWeight(); var container = weightTable[i]; var pairs = container.pairs.OrderByDescending(pair => pair.weight).ToList(); for (int b = 0; b < pairs.Count; b++) { if (b > 3) { if (warningBuilder.Length == 0) warningBuilder.Insert(0, "[Weighted Mesh: " + name + "]\r\nUnity only supports 4 weight influences per vertex! The 4 strongest influences will be used.\r\n"); warningBuilder.AppendFormat("{0} ignored on vertex {1}!\r\n", pairs[b].bone.name, i); continue; } int boneIndex = boneList.IndexOf(pairs[b].bone); float weight = pairs[b].weight; switch (b) { case 0: bw.boneIndex0 = boneIndex; bw.weight0 = weight; break; case 1: bw.boneIndex1 = boneIndex; bw.weight1 = weight; break; case 2: bw.boneIndex2 = boneIndex; bw.weight2 = weight; break; case 3: bw.boneIndex3 = boneIndex; bw.weight3 = weight; break; } } boneWeights[i] = bw; } Matrix4x4[] bindPoses = new Matrix4x4[boneList.Count]; for (int i = 0; i < boneList.Count; i++) { bindPoses[i] = boneList[i].worldToLocalMatrix; } mesh.boneWeights = boneWeights; mesh.bindposes = bindPoses; string warningString = warningBuilder.ToString(); if (warningString.Length > 0) Debug.LogWarning(warningString); return mesh; }
void Start() { Vector3 l_position = transform.position; Quaternion l_rotation = transform.rotation; Vector3 l_scale = transform.localScale; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; transform.localScale = Vector3.one; List <Transform> bones = new List <Transform>(); List <BoneWeight> boneWeights = new List <BoneWeight>(); List <CombineInstance> combineInstances = new List <CombineInstance>(); int numSubmeshes = 0; for (int i = 0; i < spriteMeshInstances.Length; i++) { SpriteMeshInstance spriteMeshInstance = spriteMeshInstances[i]; if (spriteMeshInstance.cachedSkinnedRenderer) { numSubmeshes += spriteMeshInstance.mesh.subMeshCount; } } int[] meshIndex = new int[numSubmeshes]; int boneOffset = 0; for (int i = 0; i < m_SpriteMeshInstances.Length; ++i) { SpriteMeshInstance spriteMeshInstance = spriteMeshInstances[i]; if (spriteMeshInstance.cachedSkinnedRenderer) { SkinnedMeshRenderer skinnedMeshRenderer = spriteMeshInstance.cachedSkinnedRenderer; BoneWeight[] meshBoneweight = spriteMeshInstance.sharedMesh.boneWeights; // May want to modify this if the renderer shares bones as unnecessary bones will get added. for (int j = 0; j < meshBoneweight.Length; ++j) { BoneWeight bw = meshBoneweight[j]; BoneWeight bWeight = bw; bWeight.boneIndex0 += boneOffset; bWeight.boneIndex1 += boneOffset; bWeight.boneIndex2 += boneOffset; bWeight.boneIndex3 += boneOffset; boneWeights.Add(bWeight); } boneOffset += spriteMeshInstance.bones.Count; Transform[] meshBones = skinnedMeshRenderer.bones; for (int j = 0; j < meshBones.Length; j++) { Transform bone = meshBones[j]; bones.Add(bone); } CombineInstance combineInstance = new CombineInstance(); Mesh mesh = new Mesh(); skinnedMeshRenderer.BakeMesh(mesh); mesh.uv = spriteMeshInstance.spriteMesh.sprite.uv; combineInstance.mesh = mesh; meshIndex[i] = combineInstance.mesh.vertexCount; combineInstance.transform = skinnedMeshRenderer.localToWorldMatrix; combineInstances.Add(combineInstance); skinnedMeshRenderer.gameObject.SetActive(false); } } List <Matrix4x4> bindposes = new List <Matrix4x4>(); for (int b = 0; b < bones.Count; b++) { bindposes.Add(bones[b].worldToLocalMatrix * transform.worldToLocalMatrix); } SkinnedMeshRenderer combinedSkinnedRenderer = gameObject.AddComponent <SkinnedMeshRenderer>(); Mesh combinedMesh = new Mesh(); combinedMesh.CombineMeshes(combineInstances.ToArray(), true, true); combinedSkinnedRenderer.sharedMesh = combinedMesh; combinedSkinnedRenderer.bones = bones.ToArray(); combinedSkinnedRenderer.sharedMesh.boneWeights = boneWeights.ToArray(); combinedSkinnedRenderer.sharedMesh.bindposes = bindposes.ToArray(); combinedSkinnedRenderer.sharedMesh.RecalculateBounds(); combinedSkinnedRenderer.materials = spriteMeshInstances[0].sharedMaterials; transform.position = l_position; transform.rotation = l_rotation; transform.localScale = l_scale; }
void parseSkin() { List <string> lines = new List <string> (File.ReadAllLines(skinPath)); List <Vector3> positions = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <int> triangles = new List <int>(); List <Matrix4x4> bindings = new List <Matrix4x4>(); List <BoneWeight> skinweights = new List <BoneWeight>(); string[] nameSplit; for (int i = 0; i < lines.Count; i = i + 1) { lines[i] = lines[i].Replace(" ", " "); lines[i] = lines[i].Replace(" ", " "); lines[i] = lines[i].Replace(" ", " "); lines[i] = lines[i].Replace(" ", " "); lines[i] = lines[i].Replace(" ", " "); if (lines[i][0] == ' ') { lines[i] = lines[i].Substring(1); } } for (int i = 0; i < lines.Count; i = i + 1) { if (lines[i].Contains("{")) { nameSplit = lines[i].Split(' '); string name = nameSplit[0]; i = i + 1; if (name == "positions") { while (!lines[i].Contains("{") && !lines[i].Contains("}")) { nameSplit = lines[i].Split(' '); positions.Add(new Vector3(float.Parse(nameSplit[0]), float.Parse(nameSplit[1]), float.Parse(nameSplit[2]))); i = i + 1; } } else if (name == "normals") { while (!lines[i].Contains("{") && !lines[i].Contains("}")) { nameSplit = lines[i].Split(' '); normals.Add(new Vector3(float.Parse(nameSplit[0]), float.Parse(nameSplit[1]), float.Parse(nameSplit[2]))); i = i + 1; } } else if (name == "triangles") { while (!lines[i].Contains("{") && !lines[i].Contains("}")) { nameSplit = lines[i].Split(' '); triangles.Add(int.Parse(nameSplit[0])); triangles.Add(int.Parse(nameSplit[1])); triangles.Add(int.Parse(nameSplit[2])); i = i + 1; } } else if (name == "bindings") { while (lines[i].Contains("matrix")) { Matrix4x4 matrix = new Matrix4x4(); matrix.m00 = float.Parse(lines[i + 1].Split(' ')[0]); matrix.m01 = float.Parse(lines[i + 2].Split(' ')[0]); matrix.m02 = float.Parse(lines[i + 3].Split(' ')[0]); matrix.m03 = float.Parse(lines[i + 4].Split(' ')[0]); matrix.m10 = float.Parse(lines[i + 1].Split(' ')[1]); matrix.m11 = float.Parse(lines[i + 2].Split(' ')[1]); matrix.m12 = float.Parse(lines[i + 3].Split(' ')[1]); matrix.m13 = float.Parse(lines[i + 4].Split(' ')[1]); matrix.m20 = float.Parse(lines[i + 1].Split(' ')[2]); matrix.m21 = float.Parse(lines[i + 2].Split(' ')[2]); matrix.m22 = float.Parse(lines[i + 3].Split(' ')[2]); matrix.m23 = float.Parse(lines[i + 4].Split(' ')[2]); matrix.m30 = 0; matrix.m31 = 0; matrix.m32 = 0; matrix.m33 = 1; bindings.Add(matrix.inverse); i = i + 6; } } else if (name == "skinweights") { while (!lines[i].Contains("{") && !lines[i].Contains("}")) { nameSplit = lines[i].Split(' '); int note = int.Parse(nameSplit[0]); BoneWeight bones = new BoneWeight(); switch (note) { case 1: bones.boneIndex0 = int.Parse(nameSplit[1]); bones.weight0 = float.Parse(nameSplit[2]); break; case 2: bones.boneIndex0 = int.Parse(nameSplit[1]); bones.weight0 = float.Parse(nameSplit[2]); bones.boneIndex1 = int.Parse(nameSplit[3]); bones.weight1 = float.Parse(nameSplit[4]); break; case 3: bones.boneIndex0 = int.Parse(nameSplit[1]); bones.weight0 = float.Parse(nameSplit[2]); bones.boneIndex1 = int.Parse(nameSplit[3]); bones.weight1 = float.Parse(nameSplit[4]); bones.boneIndex2 = int.Parse(nameSplit[5]); bones.weight2 = float.Parse(nameSplit[6]); break; case 4: bones.boneIndex0 = int.Parse(nameSplit[1]); bones.weight0 = float.Parse(nameSplit[2]); bones.boneIndex1 = int.Parse(nameSplit[3]); bones.weight1 = float.Parse(nameSplit[4]); bones.boneIndex2 = int.Parse(nameSplit[5]); bones.weight2 = float.Parse(nameSplit[6]); bones.boneIndex3 = int.Parse(nameSplit[7]); bones.weight3 = float.Parse(nameSplit[8]); break; default: break; } skinweights.Add(bones); i = i + 1; } } } } GameObject gameObject = rootobj; SkinnedMeshRenderer mr = gameObject.GetComponent <SkinnedMeshRenderer>(); mr.material = mat; Mesh m = new Mesh(); m.vertices = positions.ToArray(); m.triangles = triangles.ToArray(); m.normals = normals.ToArray(); m.boneWeights = skinweights.ToArray(); m.bindposes = bindings.ToArray(); mr.bones = gameObject.GetComponentsInChildren <Transform>(); mr.sharedMesh = m; }
/// <summary> /// Skinning mesh to new skinned mesh renderer with choosed weight markers settings /// </summary> public void SkinMesh(bool addTailAnimator = false) { CalculateVertexDatas(); Vector3 prePos = transform.position; Quaternion preRot = transform.rotation; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; GameObject newSkinObject = new GameObject(name + " [FSKINNED]"); newSkinObject.transform.localScale = transform.localScale; SkinnedMeshRenderer newSkinnedMesh = newSkinObject.AddComponent <SkinnedMeshRenderer>(); Mesh newMesh = Instantiate(GetBaseMesh()); newMesh.name = baseMesh.name + " [FSKINNED]"; newMesh.RecalculateNormals(); newMesh.RecalculateBounds(); newMesh.RecalculateTangents(); MeshRenderer meshRend = GetComponent <MeshRenderer>(); if (meshRend) { newSkinnedMesh.materials = meshRend.sharedMaterials; newSkinnedMesh.sharedMaterials = meshRend.sharedMaterials; } Transform[] bones = new Transform[ghostBones.Length]; Matrix4x4[] bindPoses = new Matrix4x4[ghostBones.Length]; string nameString = ""; if (baseMesh.name.Length < 6) { nameString = baseMesh.name; } else { nameString = baseMesh.name.Substring(0, 5); } for (int i = 0; i < ghostBones.Length; i++) { bones[i] = new GameObject("BoneF-" + nameString + "[" + i + "]").transform; if (i == 0) { bones[i].SetParent(newSkinObject.transform, true); } else { bones[i].SetParent(bones[i - 1], true); } bones[i].transform.position = ghostBones[i].position; bones[i].transform.rotation = ghostBones[i].rotation; bindPoses[i] = bones[i].worldToLocalMatrix * transform.localToWorldMatrix; } BoneWeight[] weights = new BoneWeight[newMesh.vertexCount]; for (int v = 0; v < weights.Length; v++) { weights[v] = new BoneWeight(); } // Calculating and applying weights for verices for (int i = 0; i < vertexDatas.Length; i++) { for (int w = 0; w < vertexDatas[i].weights.Length; w++) { weights[i] = SetWeightIndex(weights[i], w, vertexDatas[i].bonesIndexes[w]); weights[i] = SetWeightToBone(weights[i], w, vertexDatas[i].weights[w]); } } newMesh.bindposes = bindPoses; newMesh.boneWeights = weights; newSkinnedMesh.sharedMesh = newMesh;// (Mesh)AssetDatabase.LoadAssetAtPath(newMeshPath, typeof(Mesh)); newSkinnedMesh.rootBone = bones[0]; newSkinnedMesh.bones = bones; transform.position = prePos; transform.rotation = preRot; newSkinObject.transform.SetParent(transform.parent, true); newSkinObject.transform.position = prePos + Vector3.right; newSkinObject.transform.rotation = preRot; if (addTailAnimator) { FTail_Animator t = bones[0].gameObject.AddComponent <FTail_Animator>(); t.LookUpMethod = FTail_AnimatorBase.FELookUpMethod.Parental; } // Create asset for new model so it not disappear when we create prefab from this gameObject string newMeshPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(baseMesh)); AssetDatabase.CreateAsset(newMesh, newMeshPath + "/" + newMesh.name + ".mesh"); AssetDatabase.SaveAssets(); Debug.Log("New skinned mesh '" + newMesh.name + ".mesh" + "' saved under path: '" + newMeshPath + "'"); }
public GameObject GetGameObject(out GameObject[] boneGaos, GeometricObject morphObject = null, float morphProgress = 0f) { GameObject parentGao = new GameObject(Offset.ToString()); // Bones boneGaos = null; if (bones != null && bones.Length > 0) { GameObject rootBone = new GameObject("Root bone"); boneGaos = new GameObject[] { rootBone }; boneGaos[0].transform.SetParent(parentGao.transform); boneGaos[0].transform.localPosition = Vector3.zero; boneGaos[0].transform.localRotation = Quaternion.identity; boneGaos[0].transform.localScale = Vector3.one; boneGaos = boneGaos.Concat(bones.Select(b => b.GetGameObject(parentGao))).ToArray(); } // Morph Vector3[] mainVertices = vertices.Select(s => new Vector3(s.x, s.z, s.y) / R2PS1Loader.CoordinateFactor).ToArray(); Color[] mainColors = vertices.Select(s => new Color( s.r / (float)0x80, s.g / (float)0x80, s.b / (float)0x80, 1f)).ToArray(); if (morphProgress > 0f && morphObject != null && morphObject.vertices.Length == vertices.Length) { Vector3[] morphVertices = morphObject.vertices.Select(s => new Vector3(s.x, s.z, s.y) / R2PS1Loader.CoordinateFactor).ToArray(); Color[] morphColors = morphObject.vertices.Select(s => new Color( s.r / (float)0x80, s.g / (float)0x80, s.b / (float)0x80, 1f)).ToArray(); for (int i = 0; i < vertices.Length; i++) { mainVertices[i] = Vector3.Lerp(mainVertices[i], morphVertices[i], morphProgress); mainColors[i] = Color.Lerp(mainColors[i], morphColors[i], morphProgress); } } // First pass Dictionary <VisualMaterial, List <IPS1Polygon> > textured = new Dictionary <VisualMaterial, List <IPS1Polygon> >(); List <IPS1Polygon> untextured = new List <IPS1Polygon>(); for (int i = 0; i < triangleLists.Length; i++) { PolygonList polys = triangleLists[i]; if (polys.polygons != null) { foreach (IPS1Polygon p in polys.polygons) { if (p is QuadLOD && (p as QuadLOD).quads?.Length > 0) { Quad[] quads = (p as QuadLOD).quads; foreach (Quad q in quads) { VisualMaterial b = q.Material; if (b == null) { untextured.Add(q); } else { if (!textured.ContainsKey(b)) { textured[b] = new List <IPS1Polygon>(); } textured[b].Add(q); } } } else { VisualMaterial b = p.Material; if (b == null) { untextured.Add(p); } else { if (!textured.ContainsKey(b)) { textured[b] = new List <IPS1Polygon>(); } textured[b].Add(p); } } } } } // Second pass VisualMaterial[] textures = textured.Keys.ToArray(); for (int i = 0; i < textures.Length; i++) { VisualMaterial vm = textures[i]; TextureBounds b = vm.texture; float alpha = 1f; //if (!vm.IsLight) { /*switch (vm.BlendMode) { * case VisualMaterial.SemiTransparentMode.Point25: * alpha = 0.25f * 4f; * break; * case VisualMaterial.SemiTransparentMode.Point5: * alpha = 0.5f * 4f; * break; * }*/ //} IPS1Polygon pf = textured[vm].FirstOrDefault(); GameObject gao = new GameObject(Offset.ToString() + " - " + i + " - " + pf?.Offset + " - " + pf?.GetType() + " - " + string.Format("{0:X2}", vm.materialFlags) + "|" + string.Format("{0:X2}", vm.scroll) + " - " + vm.BlendMode); gao.transform.SetParent(parentGao.transform); gao.layer = LayerMask.NameToLayer("Visual"); gao.transform.localPosition = Vector3.zero; List <int> vertIndices = new List <int>(); List <int> triIndices = new List <int>(); List <Vector2> uvs = new List <Vector2>(); foreach (IPS1Polygon p in textured[vm]) { int currentCount = vertIndices.Count; switch (p) { case Triangle t: vertIndices.Add(t.v0); vertIndices.Add(t.v1); vertIndices.Add(t.v2); uvs.Add(b.CalculateUV(t.x0, t.y0)); uvs.Add(b.CalculateUV(t.x1, t.y1)); uvs.Add(b.CalculateUV(t.x2, t.y2)); /*Vector2 uv0 = b.CalculateUV(t.x0, t.y0); * Vector2 uv1 = b.CalculateUV(t.x1, t.y1); * Vector2 uv2 = b.CalculateUV(t.x2, t.y2); * uvs.Add(uv0); * uvs.Add(uv1); * uvs.Add(uv2);*/ triIndices.Add(currentCount); triIndices.Add(currentCount + 1); triIndices.Add(currentCount + 2); break; case Quad q: vertIndices.Add(q.v0); vertIndices.Add(q.v1); vertIndices.Add(q.v2); vertIndices.Add(q.v3); uvs.Add(b.CalculateUV(q.x0, q.y0)); uvs.Add(b.CalculateUV(q.x1, q.y1)); uvs.Add(b.CalculateUV(q.x2, q.y2)); uvs.Add(b.CalculateUV(q.x3, q.y3)); triIndices.Add(currentCount); triIndices.Add(currentCount + 1); triIndices.Add(currentCount + 2); triIndices.Add(currentCount + 2); triIndices.Add(currentCount + 1); triIndices.Add(currentCount + 3); break; case Sprite s: GameObject spr_gao = new GameObject("Sprite"); spr_gao.transform.SetParent(gao.transform); spr_gao.transform.localPosition = mainVertices[s.v0]; BillboardBehaviour billboard = spr_gao.AddComponent <BillboardBehaviour>(); billboard.mode = BillboardBehaviour.LookAtMode.ViewRotation; MeshFilter sprites_mf = spr_gao.AddComponent <MeshFilter>(); MeshRenderer sprites_mr = spr_gao.AddComponent <MeshRenderer>(); spr_gao.layer = LayerMask.NameToLayer("Visual"); //Material unityMat = sprites[i].visualMaterial.MaterialBillboard; sprites_mr.receiveShadows = false; sprites_mr.material = vm.CreateMaterial(); var meshUnity = new Mesh(); Vector3[] vertices = new Vector3[4]; float scale_x = 1.0f; float scale_y = 1.0f; scale_x = ((float)s.height / R2PS1Loader.CoordinateFactor) / 2.0f; scale_y = ((float)s.width / R2PS1Loader.CoordinateFactor) / 2.0f; BoxCollider bc = spr_gao.AddComponent <BoxCollider>(); bc.size = new Vector3(0, scale_y * 2, scale_x * 2); vertices[0] = new Vector3(0, -scale_y, -scale_x); vertices[1] = new Vector3(0, -scale_y, scale_x); vertices[2] = new Vector3(0, scale_y, -scale_x); vertices[3] = new Vector3(0, scale_y, scale_x); Vector3[] normals = new Vector3[4]; normals[0] = Vector3.forward; normals[1] = Vector3.forward; normals[2] = Vector3.forward; normals[3] = Vector3.forward; Vector3[] sprite_uvs = new Vector3[4]; bool mirrorX = false; bool mirrorY = false; sprite_uvs[0] = new Vector3(0, 0 - (mirrorY ? 1 : 0), alpha); sprite_uvs[1] = new Vector3(1 + (mirrorX ? 1 : 0), 0 - (mirrorY ? 1 : 0), alpha); sprite_uvs[2] = new Vector3(0, 1, alpha); sprite_uvs[3] = new Vector3(1 + (mirrorX ? 1 : 0), 1, alpha); int[] triangles = new int[] { 0, 2, 1, 1, 2, 3 }; meshUnity.vertices = vertices; meshUnity.normals = normals; meshUnity.triangles = triangles; meshUnity.SetUVs(0, sprite_uvs.ToList()); sprites_mf.sharedMesh = meshUnity; break; } } //Vertex[] v = vertIndices.Select(vi => vertices[vi]).ToArray(); BoneWeight[] w = null; if (bones != null && bones.Length > 0 && boneWeights != null) { w = new BoneWeight[vertIndices.Count]; for (int vi = 0; vi < w.Length; vi++) { DeformVertexWeights dvw = boneWeights.FirstOrDefault(bw => bw.ind_vertex == vertIndices[vi]); if (dvw != null) { w[vi] = dvw.UnityWeight; } else { w[vi] = new BoneWeight() { boneIndex0 = 0, weight0 = 1f }; } } } if (vertIndices.Any()) { MeshFilter mf = gao.AddComponent <MeshFilter>(); gao.AddComponent <ExportableModel>(); MeshRenderer mr = null; SkinnedMeshRenderer smr = null; Matrix4x4[] bindPoses = null; if (bones == null || bones.Length <= 0) { mr = gao.AddComponent <MeshRenderer>(); } else { smr = gao.AddComponent <SkinnedMeshRenderer>(); //smr = (SkinnedMeshRenderer)mr; smr.bones = boneGaos.Select(bo => bo.transform).ToArray(); bindPoses = new Matrix4x4[smr.bones.Length]; for (int bi = 0; bi < smr.bones.Length; bi++) { bindPoses[bi] = smr.bones[bi].worldToLocalMatrix * parentGao.transform.localToWorldMatrix; } smr.rootBone = smr.bones[0]; } Mesh m = new Mesh(); m.vertices = vertIndices.Select(vi => mainVertices[vi]).ToArray(); m.colors = vertIndices.Select(vi => mainColors[vi]).ToArray(); m.SetUVs(0, uvs.Select(s => new Vector4(s.x, s.y, alpha, 0f)).ToList()); m.triangles = triIndices.ToArray(); m.RecalculateNormals(); if (w != null) { m.boneWeights = w; m.bindposes = bindPoses; } mf.mesh = m; if (mr != null) { mr.material = vm.CreateMaterial(); } else if (smr != null) { smr.material = vm.CreateMaterial(); smr.sharedMesh = m; } try { MeshCollider mc = gao.AddComponent <MeshCollider>(); mc.isTrigger = false; //mc.cookingOptions = MeshColliderCookingOptions.None; //mc.sharedMesh = mesh; } catch (Exception) { } } } // Untextured (some skyboxes, etc) if (untextured.Count > 0) { GameObject gao = new GameObject(Offset.ToString() + " - Untextured"); gao.transform.SetParent(parentGao.transform); gao.layer = LayerMask.NameToLayer("Visual"); gao.transform.localPosition = Vector3.zero; MeshFilter mf = gao.AddComponent <MeshFilter>(); gao.AddComponent <ExportableModel>(); MeshRenderer mr = gao.AddComponent <MeshRenderer>(); List <int> vertIndices = new List <int>(); List <int> triIndices = new List <int>(); foreach (IPS1Polygon p in untextured) { int currentCount = vertIndices.Count; switch (p) { case TriangleNoTexture t: vertIndices.Add(t.v0); vertIndices.Add(t.v1); vertIndices.Add(t.v2); triIndices.Add(currentCount); triIndices.Add(currentCount + 1); triIndices.Add(currentCount + 2); break; case QuadNoTexture q: vertIndices.Add(q.v0); vertIndices.Add(q.v1); vertIndices.Add(q.v2); vertIndices.Add(q.v3); triIndices.Add(currentCount); triIndices.Add(currentCount + 1); triIndices.Add(currentCount + 2); triIndices.Add(currentCount + 2); triIndices.Add(currentCount + 1); triIndices.Add(currentCount + 3); break; default: Debug.LogWarning(p.GetType()); break; } } //Vertex[] v = vertIndices.Select(vi => vertices[vi]).ToArray(); Mesh m = new Mesh(); m.vertices = vertIndices.Select(vi => mainVertices[vi]).ToArray(); m.colors = vertIndices.Select(vi => mainColors[vi]).ToArray(); m.SetUVs(0, vertIndices.Select(s => new Vector4(0.5f, 0.5f, 1f, 1f)).ToList()); m.triangles = triIndices.ToArray(); m.RecalculateNormals(); mf.mesh = m; Material baseMaterial; /*if (m.colors.Any(c => c.a != 1f)) { * baseMaterial = Load.baseTransparentMaterial; * } else {*/ baseMaterial = Load.baseMaterial; //} Material mat = new Material(baseMaterial); mat.SetInt("_NumTextures", 1); string textureName = "_Tex0"; Texture2D tex = Util.GrayTexture(); mat.SetTexture(textureName, tex); mat.SetVector("_AmbientCoef", Vector4.one); mat.SetFloat("_Prelit", 1f); mr.material = mat; try { MeshCollider mc = gao.AddComponent <MeshCollider>(); mc.isTrigger = false; //mc.cookingOptions = MeshColliderCookingOptions.None; //mc.sharedMesh = mesh; } catch (Exception) { } } return(parentGao); }