Exemplo n.º 1
0
        private void ApplyMorphToMeshLod(int lodIndex, MeshAsset mesh)
        {
            List <Vector> LodVertices = GetVerticesForLod(lodIndex, mesh);
            MeshLOD       lod         = mesh.lods[lodIndex];
            int           offset      = 0;

            foreach (MeshLodSection section in lod.sections)
            {
                if (section.vertices != null)
                {
                    for (int i = 0; i < section.vertices.Count; i++)
                    {
                        section.vertices[i].position.members[0] = LodVertices[offset].members[0];
                        section.vertices[i].position.members[1] = LodVertices[offset].members[1];
                        section.vertices[i].position.members[2] = LodVertices[offset].members[2];
                        offset++;
                    }
                }
                else
                {
                    // if the lod is not completely loaded, we abort
                    break;
                }
            }
        }
Exemplo n.º 2
0
 public void LoadVertexData(Stream s, MeshLOD lod)
 {
     s.Seek(vertOffset, 0);
     vertices = new List <Vertex>();
     for (int i = 0; i < vertCount; i++)
     {
         vertices.Add(new Vertex(s, vertDesc, (int)vertexStride));
     }
     s.Seek(lod.vertexDataSize + indStart * 2, 0);
     indicies = new List <ushort>();
     for (int i = 0; i < triCount * 3; i++)
     {
         indicies.Add(Helpers.ReadUShort(s));
     }
 }
Exemplo n.º 3
0
        ///
        private byte[] ExportAsObj(MeshAsset mesh, MeshLOD lod)
        {
            string[]   subMeshNames = new string[lod.sections.Count];
            float[][]  verts        = new float[lod.sections.Count][];
            float[][]  uvcords      = new float[lod.sections.Count][];
            ushort[][] indices      = new ushort[lod.sections.Count][];

            for (int i = 0; i < lod.sections.Count; i++)
            {
                subMeshNames[i] = lod.sections[i].matName;
                verts[i]        = GetVerticesPositionsArray(lod.sections[i].vertices);
                uvcords[i]      = GetUVCoordsArray(lod.sections[i].vertices);
                indices[i]      = lod.sections[i].indicies.ToArray();
            }

            return(convertToOBJ(mesh.header.shortName, subMeshNames, verts, uvcords, indices));
        }
Exemplo n.º 4
0
        private void CreateMeshSkinning(SkeletonAsset Skeleton, MeshLOD lod, FBXNode pFbxMesh, FBXNode pSkeletonRoot, FBXScene pScene)
        {
            Dictionary <string, List <VertexGroup.VertexWeight> > vg = VertexGroup.GetVertexGroups(Skeleton, lod);

            CreateMeshSkinning(vg, pFbxMesh, pSkeletonRoot, pScene);
        }
Exemplo n.º 5
0
        private FBXNode CreateFbxMesh(MeshLOD lod, FBXScene pScene)
        {
            FBXMesh fbxMesh   = FBXMesh.Create(pScene, lod.shortName);
            FBXNode lMeshNode = FBXNode.Create(pScene, lod.shortName);

            lMeshNode.SetNodeAttribute(fbxMesh);
            FBXGeometryElementNormal lGeometryElementNormal = fbxMesh.CreateElementNormal();

            lGeometryElementNormal.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
            FBXGeometryElementBinormal lGeometryElementBiNormal = fbxMesh.CreateElementBinormal();

            lGeometryElementBiNormal.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
            FBXGeometryElementTangent lGeometryElementTangent = fbxMesh.CreateElementTangent();

            lGeometryElementTangent.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
            FBXGeometryElementMaterial lMaterialElement = fbxMesh.CreateElementMaterial();

            lMaterialElement.SetMappingMode(FBXWrapper.MappingMode.eByPolygon);
            lMaterialElement.SetReferenceMode(FBXWrapper.ReferenceMode.eIndexToDirect);
            int verticesCount = lod.GetLODTotalVertCount();

            fbxMesh.InitControlPoints(verticesCount);
            List <FBXGeometryElementUV[]> UVs = new List <FBXGeometryElementUV[]>();

            for (int i = 0; i < lod.sections.Count; i++)
            {
                UVs.Add(new FBXGeometryElementUV[Vertex.UV_SLOTS]);
            }
            int VertexOffset = 0;

            for (int i = 0; i < lod.sections.Count; i++)
            {
                MeshLodSection section = lod.sections[i];
                for (int j = 0; j < section.vertices.Count; j++)
                {
                    FBXVector4 position = new FBXVector4(section.vertices[j].position.members[0] * exportScale, section.vertices[j].position.members[1] * exportScale, section.vertices[j].position.members[2] * exportScale, 0);
                    FBXVector4 normal   = new FBXVector4(section.vertices[j].normals.members[0], section.vertices[j].normals.members[1], section.vertices[j].normals.members[2], section.vertices[j].normals.members[3]);
                    fbxMesh.SetControlPoint(VertexOffset + j, position);
                    lGeometryElementNormal.Add(normal);

                    // adding a check on bitangent and tangent as some meshes don't have them...
                    if (section.vertices[j].biTangents.members.Length == 4)
                    {
                        FBXVector4 bitangent = new FBXVector4(section.vertices[j].biTangents.members[0], section.vertices[j].biTangents.members[1], section.vertices[j].biTangents.members[2], section.vertices[j].biTangents.members[3]);
                        lGeometryElementBiNormal.Add(bitangent);
                    }
                    if (section.vertices[j].tangents.members.Length == 4)
                    {
                        FBXVector4 tangent = new FBXVector4(section.vertices[j].tangents.members[0], section.vertices[j].tangents.members[1], section.vertices[j].tangents.members[2], section.vertices[j].tangents.members[3]);
                        lGeometryElementTangent.Add(tangent);
                    }

                    // multiple UVs management
                    for (int uvInd = 0; uvInd < Vertex.UV_SLOTS; uvInd++)
                    {
                        if (section.vertices[j].texCoords[uvInd] != null)
                        {
                            FBXVector4 texCoords = new FBXVector4(section.vertices[j].texCoords[uvInd].members[0], (-section.vertices[j].texCoords[uvInd].members[1] + 1), 0, 0);
                            if (UVs[i][uvInd] == null)
                            {
                                // if the UV layer does not already exist, we create it...
                                UVs[i][uvInd] = fbxMesh.CreateElementUV(section.matName + "_" + uvInd);
                                UVs[i][uvInd].SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
                                UVs[i][uvInd].SetReferenceMode(FBXWrapper.ReferenceMode.eDirect);

                                // ... and fill it with empty vectors for all previous sections vertices.
                                for (int p = 0; p < VertexOffset + j; p++)
                                {
                                    UVs[i][uvInd].Add(new FBXVector4(0, 0, 0, 0));
                                }
                            }
                            // and now we can add the tex coord of the current vertex we're treating.
                            UVs[i][uvInd].Add(texCoords);
                        }
                    }

                    // since we use direct reference mode for UV, every vertices in the mesh must be present in every UV layer
                    // so for every UV layer created for previous section, we had an empty vector for this vertex.
                    UVs.Where((o, oi) => oi != i).ToList().ForEach(suv =>
                    {
                        for (int subuv = 0; subuv < Vertex.UV_SLOTS; subuv++)
                        {
                            if (suv[subuv] != null)
                            {
                                suv[subuv].Add(new FBXVector4(0, 0, 0, 0));
                            }
                        }
                    }
                                                                   );
                }
                for (int j = 0; j < section.indicies.Count; j++)
                {
                    if (j % 3 == 0)
                    {
                        fbxMesh.EndPolygon();
                        fbxMesh.BeginPolygon(i);
                    }
                    fbxMesh.AddPolygon(VertexOffset + section.indicies[j]);
                }
                fbxMesh.EndPolygon();
                VertexOffset = VertexOffset + section.vertices.Count;
                lMeshNode.AddMaterial(pScene, section.matName);
            }
            return(lMeshNode);
        }
Exemplo n.º 6
0
        public static Dictionary <string, List <VertexWeight> > GetVertexGroups(SkeletonAsset skeleton, MeshLOD lod)
        {
            var VertexGroupDict = new Dictionary <string, List <VertexWeight> >();
            int VertCount       = 0;

            foreach (var section in lod.sections)
            {
                VertCount = GetVertexGroups(skeleton, section, VertCount, ref VertexGroupDict);
            }
            return(VertexGroupDict);
        }
Exemplo n.º 7
0
        // export given LOD to psk
        private byte[] ExportSkinnedMeshToPsk(SkeletonAsset skeleton, MeshLOD LOD, float OverrideScale = 1.0f)
        {
            PSKFile Psk = new PSKFile();

            Psk.points    = new List <PSKFile.PSKPoint>();
            Psk.edges     = new List <PSKFile.PSKEdge>();
            Psk.materials = new List <PSKFile.PSKMaterial>();
            Psk.bones     = new List <PSKFile.PSKBone>();
            Psk.faces     = new List <PSKFile.PSKFace>();
            Psk.weights   = new List <PSKFile.PSKWeight>();

            /* No skeleton defined still */
            if (skeleton != null)
            {
                for (int i = 0; i < skeleton.Bones.Count; i++)
                {
                    PSKFile.PSKBone Bone = new PSKFile.PSKBone();
                    Bone.name     = skeleton.Bones[i].Name;
                    Bone.childs   = skeleton.Bones[i].Children.Count;
                    Bone.parent   = (skeleton.Bones[i].ParentIndex == -1) ? 0 : skeleton.Bones[i].ParentIndex;
                    Bone.index    = i;
                    Bone.location = new PSKFile.PSKPoint(ConvertVector3ToPsk(skeleton.Bones[i].Location) * OverrideScale);
                    Bone.rotation = new PSKFile.PSKQuad(0, 0, 0, 0);

                    float[][] RotMatrix = new float[4][];
                    RotMatrix[0] = new float[4];
                    RotMatrix[1] = new float[4];
                    RotMatrix[2] = new float[4];
                    RotMatrix[3] = new float[4];

                    RotMatrix[0][0] = skeleton.Bones[i].Right.members[0];   RotMatrix[0][1] = skeleton.Bones[i].Right.members[1];   RotMatrix[0][2] = skeleton.Bones[i].Right.members[2];   RotMatrix[0][3] = 0.0f;
                    RotMatrix[1][0] = skeleton.Bones[i].Up.members[0];      RotMatrix[1][1] = skeleton.Bones[i].Up.members[1];      RotMatrix[1][2] = skeleton.Bones[i].Up.members[2];      RotMatrix[1][3] = 0.0f;
                    RotMatrix[2][0] = skeleton.Bones[i].Forward.members[0]; RotMatrix[2][1] = skeleton.Bones[i].Forward.members[1]; RotMatrix[2][2] = skeleton.Bones[i].Forward.members[2]; RotMatrix[2][3] = 0.0f;
                    RotMatrix[3][0] = 0.0f;                                 RotMatrix[3][1] = 0.0f;                                 RotMatrix[3][2] = 0.0f;                                 RotMatrix[3][3] = 1.0f;

                    Vector Quat = new Vector(new float[4]);
                    float  tr   = RotMatrix[0][0] + RotMatrix[1][1] + RotMatrix[2][2];
                    float  s;

                    if (tr > 0.0f)
                    {
                        float InvS = 1.0f / (float)Math.Sqrt(tr + 1.0f);
                        Quat.members[3] = 0.5f * (1.0f / InvS);
                        s = 0.5f * InvS;

                        Quat.members[0] = (RotMatrix[1][2] - RotMatrix[2][1]) * s;
                        Quat.members[1] = (RotMatrix[2][0] - RotMatrix[0][2]) * s;
                        Quat.members[2] = (RotMatrix[0][1] - RotMatrix[1][0]) * s;
                    }
                    else
                    {
                        int m = 0;
                        if (RotMatrix[1][1] > RotMatrix[0][0])
                        {
                            m = 1;
                        }

                        if (RotMatrix[2][2] > RotMatrix[m][m])
                        {
                            m = 2;
                        }

                        int[] nxt = new int[] { 1, 2, 0 };
                        int   j   = nxt[m];
                        int   k   = nxt[j];

                        s = RotMatrix[m][m] - RotMatrix[j][j] - RotMatrix[k][k] + 1.0f;
                        float InvS = 1.0f / (float)Math.Sqrt(s);

                        float[] qt = new float[4];
                        qt[m] = 0.5f * (1.0f / InvS);
                        s     = 0.5f * InvS;

                        qt[3] = (RotMatrix[j][k] - RotMatrix[k][j]) * s;
                        qt[j] = (RotMatrix[m][j] + RotMatrix[j][m]) * s;
                        qt[k] = (RotMatrix[m][k] + RotMatrix[k][m]) * s;

                        Quat.members[0] = qt[0];
                        Quat.members[1] = qt[1];
                        Quat.members[2] = qt[2];
                        Quat.members[3] = qt[3];
                    }

                    Bone.rotation = new PSKFile.PSKQuad(ConvertVector4ToPsk(Quat));
                    Psk.bones.Add(Bone);
                }
            }
            int offset = 0;
            int matIdx = 0;

            for (int bufIdx = 0; bufIdx < LOD.sections.Count; bufIdx++)
            {
                MeshLodSection MeshBuffer = LOD.sections[bufIdx];
                for (int i = 0; i < MeshBuffer.vertices.Count; i++)
                {
                    if (MeshBuffer.vertices[i].position.members.Length != 3)
                    {
                        MeshBuffer.vertices[i].position.members = new float[3];
                    }
                    if (MeshBuffer.vertices[i].texCoords.members.Length != 2)
                    {
                        MeshBuffer.vertices[i].texCoords.members = new float[2];
                    }
                    Vector p = new Vector(MeshBuffer.vertices[i].position.members[0], MeshBuffer.vertices[i].position.members[1], MeshBuffer.vertices[i].position.members[2]);
                    Psk.points.Add(new PSKFile.PSKPoint(ConvertVector3ToPsk(p)));
                    Vector tc = new Vector(MeshBuffer.vertices[i].texCoords.members[0], MeshBuffer.vertices[i].texCoords.members[1]);
                    Psk.edges.Add(new PSKFile.PSKEdge((ushort)(offset + i), ConvertVector2ToPsk(tc), (byte)matIdx));
                    if (MeshBuffer.vertices[i].boneWeights != null)
                    {
                        for (int x = 0; x < 4; x++)
                        {
                            float Weight = MeshBuffer.vertices[i].boneWeights[x];

                            // only add meaningful weights
                            if (Weight != 0.0f)
                            {
                                int BoneIndex = MeshBuffer.vertices[i].boneIndices[x];

                                int SubObjectBoneIndex = MeshBuffer.boneIndices[BoneIndex];
                                Psk.weights.Add(new PSKFile.PSKWeight(
                                                    Weight,
                                                    (int)(offset + i),
                                                    SubObjectBoneIndex
                                                    ));
                            }
                        }
                    }
                }

                // reverse indices order before building faces: necessary for correct normal building since all points have been mirrored along z-axis.
                // if this is not done, all normals are flipped inside.
                if (Reverse)
                {
                    MeshBuffer.indicies.Reverse();
                }
                for (int fi = 0; fi < MeshBuffer.indicies.Count; fi++)
                {
                    if (fi % 3 == 0)
                    {
                        Psk.faces.Add(new PSKFile.PSKFace(
                                          (int)(offset + MeshBuffer.indicies[fi]),
                                          (int)(offset + MeshBuffer.indicies[fi + 1]),
                                          (int)(offset + MeshBuffer.indicies[fi + 2]),
                                          (byte)matIdx)
                                      );
                    }
                }
                Psk.materials.Add(new PSKFile.PSKMaterial(LOD.sections[bufIdx].matName, matIdx));

                offset += (int)LOD.sections[bufIdx].vertCount;
                matIdx++;
            }
            return(Psk.SaveToMemory().ToArray());
        }
Exemplo n.º 8
0
        // export given LOD to psk
        private byte[] ExportSkinnedMeshToPsk(SkeletonAsset skeleton, MeshLOD LOD, float OverrideScale = 1.0f)
        {
            PSKFile Psk = new PSKFile();

            Psk.points    = new List <PSKFile.PSKPoint>();
            Psk.edges     = new List <PSKFile.PSKEdge>();
            Psk.materials = new List <PSKFile.PSKMaterial>();
            Psk.bones     = new List <PSKFile.PSKBone>();
            Psk.faces     = new List <PSKFile.PSKFace>();
            Psk.weights   = new List <PSKFile.PSKWeight>();

            // create skeleton (only if mesh is skinned mesh)
            if (LOD.type == MeshType.MeshType_Skinned)
            {
                Psk.bones = CreatePskSkeleton(skeleton, OverrideScale);
            }

            // create mesh
            int offset = 0;
            int matIdx = 0;

            for (int bufIdx = 0; bufIdx < LOD.sections.Count; bufIdx++)
            {
                MeshLodSection MeshBuffer = LOD.sections[bufIdx];
                for (int i = 0; i < MeshBuffer.vertices.Count; i++)
                {
                    // vertex position
                    if (MeshBuffer.vertices[i].position.members.Length != 3)
                    {
                        MeshBuffer.vertices[i].position.members = new float[3];
                    }
                    Vector p = new Vector(MeshBuffer.vertices[i].position.members[0] * OverrideScale, MeshBuffer.vertices[i].position.members[1] * OverrideScale, MeshBuffer.vertices[i].position.members[2] * OverrideScale);
                    Psk.points.Add(new PSKFile.PSKPoint(ConvertVector3ToPsk(p)));

                    // vertex uv
                    // supports only first uv for the time being
                    // TODO support for multiple UVs
                    if (MeshBuffer.vertices[i].texCoords[0] == null)
                    {
                        MeshBuffer.vertices[i].texCoords[0] = new Vector(new float[2]);
                    }
                    if (MeshBuffer.vertices[i].texCoords[0].members.Length != 2)
                    {
                        MeshBuffer.vertices[i].texCoords[0].members = new float[2];
                    }
                    Vector tc = new Vector(MeshBuffer.vertices[i].texCoords[0].members[0], MeshBuffer.vertices[i].texCoords[0].members[1]);
                    Psk.edges.Add(new PSKFile.PSKEdge((ushort)(offset + i), ConvertVector2ToPsk(tc), (byte)matIdx));

                    // bones weights
                    if (MeshBuffer.vertices[i].boneWeights != null)
                    {
                        for (int x = 0; x < 4; x++)
                        {
                            float Weight = MeshBuffer.vertices[i].boneWeights[x];

                            // only add meaningful weights
                            if (Weight != 0.0f)
                            {
                                int BoneIndex = MeshBuffer.vertices[i].boneIndices[x];

                                int SubObjectBoneIndex = MeshBuffer.boneIndices[BoneIndex];
                                Psk.weights.Add(new PSKFile.PSKWeight(
                                                    Weight,
                                                    (int)(offset + i),
                                                    SubObjectBoneIndex
                                                    ));
                            }
                        }
                    }
                }

                // reverse indices order before building faces: necessary for correct normal building since all points have been mirrored along z-axis.
                // if this is not done, all normals are flipped inside.
                if (Reverse)
                {
                    MeshBuffer.indicies.Reverse();
                }
                for (int fi = 0; fi < MeshBuffer.indicies.Count; fi++)
                {
                    if (fi % 3 == 0)
                    {
                        Psk.faces.Add(new PSKFile.PSKFace(
                                          (int)(offset + MeshBuffer.indicies[fi]),
                                          (int)(offset + MeshBuffer.indicies[fi + 1]),
                                          (int)(offset + MeshBuffer.indicies[fi + 2]),
                                          (byte)matIdx)
                                      );
                    }
                }
                Psk.materials.Add(new PSKFile.PSKMaterial(LOD.sections[bufIdx].matName, matIdx));

                offset += (int)LOD.sections[bufIdx].vertCount;
                matIdx++;
            }
            return(Psk.SaveToMemory().ToArray());
        }
Exemplo n.º 9
0
        private FBXNode CreateFbxMesh(MeshLOD lod, FBXScene pScene)
        {
            FBXMesh fbxMesh   = FBXMesh.Create(pScene, lod.shortName);
            FBXNode lMeshNode = FBXNode.Create(pScene, lod.shortName);

            lMeshNode.SetNodeAttribute(fbxMesh);
            FBXGeometryElementNormal lGeometryElementNormal = fbxMesh.CreateElementNormal();

            lGeometryElementNormal.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
            FBXGeometryElementBinormal lGeometryElementBiNormal = fbxMesh.CreateElementBinormal();

            lGeometryElementBiNormal.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
            FBXGeometryElementTangent lGeometryElementTangent = fbxMesh.CreateElementTangent();

            lGeometryElementTangent.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
            FBXGeometryElementMaterial lMaterialElement = fbxMesh.CreateElementMaterial();

            lMaterialElement.SetMappingMode(FBXWrapper.MappingMode.eByPolygon);
            lMaterialElement.SetReferenceMode(FBXWrapper.ReferenceMode.eIndexToDirect);
            int verticesCount = lod.GetLODTotalVertCount();

            fbxMesh.InitControlPoints(verticesCount);
            List <FBXGeometryElementUV> UVs = new List <FBXGeometryElementUV>();

            for (int i = 0; i < lod.sections.Count; i++)
            {
                MeshLodSection       section           = lod.sections[i];
                FBXGeometryElementUV lUVDiffuseElement = fbxMesh.CreateElementUV(section.matName);
                lUVDiffuseElement.SetMappingMode(FBXWrapper.MappingMode.eByControlPoint);
                lUVDiffuseElement.SetReferenceMode(FBXWrapper.ReferenceMode.eDirect);
                UVs.Add(lUVDiffuseElement);
            }
            int VertexOffset = 0;

            for (int i = 0; i < lod.sections.Count; i++)
            {
                MeshLodSection section = lod.sections[i];
                for (int j = 0; j < section.vertices.Count; j++)
                {
                    FBXVector4 position   = new FBXVector4(section.vertices[j].position.members[0] * exportScale, section.vertices[j].position.members[1] * exportScale, section.vertices[j].position.members[2] * exportScale, 0);
                    FBXVector4 normal     = new FBXVector4(section.vertices[j].normals.members[0], section.vertices[j].normals.members[1], section.vertices[j].normals.members[2], section.vertices[j].normals.members[3]);
                    FBXVector4 textCoords = new FBXVector4(section.vertices[j].texCoords.members[0], (-section.vertices[j].texCoords.members[1] + 1), 0, 0);
                    FBXVector4 bitangent  = new FBXVector4(section.vertices[j].biTangents.members[0], section.vertices[j].biTangents.members[1], section.vertices[j].biTangents.members[2], section.vertices[j].biTangents.members[3]);
                    FBXVector4 tangent    = new FBXVector4(section.vertices[j].tangents.members[0], section.vertices[j].tangents.members[1], section.vertices[j].tangents.members[2], section.vertices[j].tangents.members[3]);
                    fbxMesh.SetControlPoint(VertexOffset + j, position);
                    lGeometryElementNormal.Add(normal);
                    lGeometryElementBiNormal.Add(bitangent);
                    lGeometryElementTangent.Add(tangent);
                    int uvI = 0;
                    foreach (FBXGeometryElementUV uv in UVs)
                    {
                        if (uvI == i)
                        {
                            uv.Add(textCoords);
                        }
                        else
                        {
                            uv.Add(new FBXVector4(0, 0, 0, 0));
                        }
                        uvI++;
                    }
                }
                for (int j = 0; j < section.indicies.Count; j++)
                {
                    if (j % 3 == 0)
                    {
                        fbxMesh.EndPolygon();
                        fbxMesh.BeginPolygon(i);
                    }
                    fbxMesh.AddPolygon(VertexOffset + section.indicies[j]);
                }
                fbxMesh.EndPolygon();
                VertexOffset = VertexOffset + section.vertices.Count;
                lMeshNode.AddMaterial(pScene, section.matName);
            }
            return(lMeshNode);
        }