コード例 #1
0
ファイル: ObjModelCooker.cs プロジェクト: Pursche/PurEngine
        UInt32 CombineVertex(CapnpGen.CapVector3 position, CapnpGen.CapVector3 normal, CapnpGen.CapVector2 texCoord, ref Dictionary <CapnpGen.CapVertex, UInt32> combinedVertices)
        {
            CapnpGen.CapVertex combinedVertex = new CapnpGen.CapVertex();
            combinedVertex.Position = position;
            combinedVertex.Normal   = normal;
            combinedVertex.TexCoord = texCoord;

            // If our dict of combined vertices contains a vertex identical to this already
            if (combinedVertices.ContainsKey(combinedVertex))
            {
                // Just return its index
                return(combinedVertices[combinedVertex]);
            }

            // Otherwise, we add the vertex to the dict and return its index
            UInt32 index = (UInt32)combinedVertices.Count;

            combinedVertices.Add(combinedVertex, index);
            return(index);
        }
コード例 #2
0
ファイル: ObjModelCooker.cs プロジェクト: Pursche/PurEngine
        public override bool Cook(string luaPath, LuaGlobal environment, string outputDirectory, string intermediateDirectory, out string producedFile, out string error)
        {
            error        = "";
            producedFile = "";
            string assetPath = GetAssetPath(luaPath);

            materialStreamProvider.SetAssetPath(assetPath);

            using (FileStream assetStream = new FileStream(assetPath, FileMode.Open))
            {
                LoadResult result = objLoader.Load(assetStream);

                CapnpGen.CapModel model = new CapnpGen.CapModel();

                // Get all vertex positions
                List <CapnpGen.CapVector3> vertexPositions = new List <CapnpGen.CapVector3>();
                foreach (Vertex vertex in result.Vertices)
                {
                    CapnpGen.CapVector3 pos = new CapnpGen.CapVector3();
                    pos.X = vertex.X;
                    pos.Y = vertex.Y;
                    pos.Z = vertex.Z;

                    vertexPositions.Add(pos);
                }
                //model.VertexPositions = vertexPositions;

                // Get all vertex texCoords
                List <CapnpGen.CapVector2> vertexTexCoords = new List <CapnpGen.CapVector2>();
                foreach (Texture texture in result.Textures)
                {
                    CapnpGen.CapVector2 texCoord = new CapnpGen.CapVector2();
                    texCoord.X = texture.X;
                    texCoord.Y = texture.Y;

                    vertexTexCoords.Add(texCoord);
                }

                // Get all vertex normals
                List <CapnpGen.CapVector3> vertexNormals = new List <CapnpGen.CapVector3>();
                foreach (Normal normal in result.Normals)
                {
                    CapnpGen.CapVector3 vertexNormal = new CapnpGen.CapVector3();
                    vertexNormal.X = normal.X;
                    vertexNormal.Y = normal.Y;
                    vertexNormal.Z = normal.Z;

                    vertexNormals.Add(vertexNormal);
                }

                // Because .obj stores vertex positions, vertex texcoords and vertex normals separately and without duplication we need to "unpack" combined vertices from this data
                // Each .obj model has a list of "groups" which represent submeshes
                // Each group has a list of faces which represent quads, they have 3-4 "indices" that point to vertex positions, vertex texcoords and vertex normals separately
                // We need to iterate over these, and then build one combined vertex for each unique combination of position, texcoord and normal

                // Convert indices

                // This dictionary will hold unique vertices as keys, and it's corresponding index as value, this makes it easy for us to look up indices of duplicated vertices
                Dictionary <CapnpGen.CapVertex, UInt32> combinedVertices = new Dictionary <CapnpGen.CapVertex, uint>();

                List <UInt32> indices = new List <UInt32>();
                foreach (ObjLoader.Loader.Data.Elements.Group group in result.Groups) // A group represents a "submesh"
                {
                    foreach (Face face in group.Faces)
                    {
                        UInt32[] combinedIndices = new UInt32[face.Count];

                        for (int i = 0; i < face.Count; i++)
                        {
                            CapnpGen.CapVector3 position = vertexPositions[face[i].VertexIndex - 1];

                            int normalIndex            = face[i].NormalIndex;
                            CapnpGen.CapVector3 normal = new CapnpGen.CapVector3();
                            normal.Y = 1;
                            if (normalIndex > 0)
                            {
                                normal = vertexNormals[normalIndex - 1];
                            }

                            int texCoordIndex = face[i].TextureIndex;

                            CapnpGen.CapVector2 texCoord = new CapnpGen.CapVector2();

                            if (texCoordIndex > 0)
                            {
                                texCoord = vertexTexCoords[texCoordIndex - 1];
                            }

                            combinedIndices[i] = CombineVertex(position, normal, texCoord, ref combinedVertices);
                        }

                        if (face.Count == 4)
                        {
                            // We split the face (quad) into two triangles, the first one with index 0 1 and 2
                            indices.Add(combinedIndices[0]);
                            indices.Add(combinedIndices[1]);
                            indices.Add(combinedIndices[2]);

                            // The second one with index 2 3 and 0
                            indices.Add(combinedIndices[2]);
                            indices.Add(combinedIndices[3]);
                            indices.Add(combinedIndices[0]);
                        }
                        else if (face.Count == 3)
                        {
                            // This kind of face only has one triangle, so it's simple
                            indices.Add(combinedIndices[0]);
                            indices.Add(combinedIndices[1]);
                            indices.Add(combinedIndices[2]);
                        }
                        else
                        {
                            Debug.Assert(false); // I haven't seen a model where faces don't have 4 or 3 indices yet
                        }
                    }
                }

                CapnpGen.CapVertex[] vertices = new CapnpGen.CapVertex[combinedVertices.Count];
                combinedVertices.Keys.CopyTo(vertices, 0);
                model.Vertices = vertices;
                model.Indices  = indices;

                // Create output file
                string outputFileName = Path.ChangeExtension(Path.GetFileName(assetPath), ".model");
                producedFile = Path.Combine(outputDirectory, "models", outputFileName);
                Directory.CreateDirectory(Path.GetDirectoryName(producedFile));
                using (FileStream outStream = new FileStream(producedFile, FileMode.Create))
                {
                    MessageBuilder message = MessageBuilder.Create();
                    var            root    = message.BuildRoot <CapnpGen.CapModel.WRITER>();
                    model.serialize(root);

                    var pump = new FramePump(outStream);
                    pump.Send(message.Frame);
                }
            }

            return(true);
        }