Exemple #1
0
		public static BoneWeight Create()
		{
			BoneWeight boneWeight = new BoneWeight();
			boneWeight.boneIndex0 = -1;
			boneWeight.boneIndex1 = -1;
			boneWeight.boneIndex2 = -1;
			boneWeight.boneIndex3 = -1;
			return boneWeight;
		}
Exemple #2
0
 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;
 }
Exemple #3
0
		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;
		}
Exemple #4
0
        // 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);
    }
Exemple #6
0
        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);
        }
Exemple #7
0
        // 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);
        }
Exemple #8
0
    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();
        }
    }
Exemple #9
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
		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);
    }
Exemple #14
0
		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);
			}
		}
Exemple #16
0
        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;
        }
Exemple #17
0
    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;

  }
Exemple #20
0
		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
    }
Exemple #23
0
        /// <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);
    }
Exemple #25
0
    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();
        }
Exemple #27
0
        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]);
        }
    }
Exemple #29
0
        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);
            }
        }
Exemple #30
0
    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);
    }
Exemple #31
0
        // 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 + "'");
        }
Exemple #38
0
        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);
        }