Esempio n. 1
0
        public void ExportModelToDirectoryWithExportOptions(Model model, String directory, ExportOptions exportOptions)
        {
            //TODO: Figure out what to do with non-version 4 models.
            if (model != null && model.Version != 4)
            {
                return;
            }

            NumberFormatInfo format = new NumberFormatInfo();

            format.NumberDecimalSeparator = ".";

            if (exportOptions.Package)
            {
                try
                {
                    DirectoryInfo directoryInfo = Directory.CreateDirectory(directory + @"\" + Path.GetFileNameWithoutExtension(model.Name));
                    directory = directoryInfo.FullName;
                }
                catch (Exception) { }
            }

            if (exportOptions.Textures)
            {
                ImageImporter imageImporter = new ImageImporter();
                ImageExporter imageExporter = new ImageExporter();

                foreach (String textureString in model.TextureStrings)
                {
                    MemoryStream textureMemoryStream = AssetManager.Instance.CreateAssetMemoryStreamByName(textureString);

                    if (textureMemoryStream == null)
                    {
                        continue;
                    }

                    Image textureImage = imageImporter.LoadImageFromStream(textureMemoryStream);

                    if (textureImage == null)
                    {
                        continue;
                    }

                    imageExporter.SaveImage(textureImage, exportOptions.TextureFormat.ImageType, directory + @"\" + Path.GetFileNameWithoutExtension(textureString) + @"." + exportOptions.TextureFormat.Extension);
                }
            }

            String path = directory + @"\" + Path.GetFileNameWithoutExtension(model.Name) + ".obj";

            FileStream   fileStream   = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write);
            StreamWriter streamWriter = new StreamWriter(fileStream);

            for (Int32 i = 0; i < model.Meshes.Length; ++i)
            {
                Mesh mesh = model.Meshes[i];

                MaterialDefinition materialDefinition = MaterialDefinitionManager.Instance.MaterialDefinitions[model.Materials[(Int32)mesh.MaterialIndex].MaterialDefinitionHash];
                VertexLayout       vertexLayout       = MaterialDefinitionManager.Instance.VertexLayouts[materialDefinition.DrawStyles[0].VertexLayoutNameHash];

                //position
                VertexLayout.Entry.DataTypes positionDataType;
                Int32 positionOffset;
                Int32 positionStreamIndex;

                vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStreamIndex, out positionOffset);

                Mesh.VertexStream positionStream = mesh.VertexStreams[positionStreamIndex];

                for (Int32 j = 0; j < mesh.VertexCount; ++j)
                {
                    Vector3 position = readVector3(exportOptions, positionOffset, positionStream, j);

                    position.X *= exportOptions.Scale.X;
                    position.Y *= exportOptions.Scale.Y;
                    position.Z *= exportOptions.Scale.Z;

                    streamWriter.WriteLine("v " + position.X.ToString(format) + " " + position.Y.ToString(format) + " " + position.Z.ToString(format));
                }

                //texture coordinates
                if (exportOptions.TextureCoordinates)
                {
                    VertexLayout.Entry.DataTypes texCoord0DataType;
                    Int32 texCoord0Offset      = 0;
                    Int32 texCoord0StreamIndex = 0;

                    Boolean texCoord0Present = vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0StreamIndex, out texCoord0Offset);

                    if (texCoord0Present)
                    {
                        Mesh.VertexStream texCoord0Stream = mesh.VertexStreams[texCoord0StreamIndex];

                        for (Int32 j = 0; j < mesh.VertexCount; ++j)
                        {
                            Vector2 texCoord;

                            switch (texCoord0DataType)
                            {
                            case VertexLayout.Entry.DataTypes.Float2:
                                texCoord.X = BitConverter.ToSingle(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + 0);
                                texCoord.Y = 1.0f - BitConverter.ToSingle(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + 4);
                                break;

                            case VertexLayout.Entry.DataTypes.float16_2:
                                texCoord.X = Half.FromBytes(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 0).ToSingle();
                                texCoord.Y = 1.0f - Half.FromBytes(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 2).ToSingle();
                                break;

                            default:
                                texCoord.X = 0;
                                texCoord.Y = 0;
                                break;
                            }

                            streamWriter.WriteLine("vt " + texCoord.X.ToString(format) + " " + texCoord.Y.ToString(format));
                        }
                    }
                }
            }

            //faces
            UInt32 vertexCount = 0;

            for (Int32 i = 0; i < model.Meshes.Length; ++i)
            {
                Mesh mesh = model.Meshes[i];

                streamWriter.WriteLine("g Mesh" + i);

                for (Int32 j = 0; j < mesh.IndexCount; j += 3)
                {
                    UInt32 index0, index1, index2;

                    switch (mesh.IndexSize)
                    {
                    case 2:
                        index0 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 0) + 1;
                        index1 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 2) + 1;
                        index2 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 4) + 1;
                        break;

                    case 4:
                        index0 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 0) + 1;
                        index1 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 4) + 1;
                        index2 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 8) + 1;
                        break;

                    default:
                        index0 = 0;
                        index1 = 0;
                        index2 = 0;
                        break;
                    }

                    if (exportOptions.Normals && exportOptions.TextureCoordinates)
                    {
                        streamWriter.WriteLine("f " + index2 + "/" + index2 + "/" + index2 + " " + index1 + "/" + index1 + "/" + index1 + " " + index0 + "/" + index0 + "/" + index0);
                    }
                    else if (exportOptions.Normals)
                    {
                        streamWriter.WriteLine("f " + index2 + "//" + index2 + " " + index1 + "//" + index1 + " " + index0 + "//" + index0);
                    }
                    else if (exportOptions.TextureCoordinates)
                    {
                        streamWriter.WriteLine("f " + index2 + "/" + index2 + " " + index1 + "/" + index1 + " " + index0 + "/" + index0);
                    }
                    else
                    {
                        streamWriter.WriteLine("f " + index2 + " " + index1 + " " + index0);
                    }
                }

                vertexCount += (UInt32)mesh.VertexCount;
            }

            streamWriter.Close();
        }
Esempio n. 2
0
        private void render()
        {
            glControl1.MakeCurrent();

            GL.Viewport(0, 0, glControl1.ClientSize.Width, glControl1.ClientSize.Height);

            //clear
            GL.ClearColor(backgroundColorDialog.Color);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            //projection matrix
            Matrix4 projection = glControl1.Camera.Projection;

            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projection);

            //view matrix
            Matrix4 view = glControl1.Camera.View;

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref view);

            if (showAxesButton.Checked)
            {
                // debug axes
                GL.Begin(PrimitiveType.Lines);
                //x
                GL.Color3(Color.Red);
                GL.Vertex3(Vector3.Zero);
                GL.Vertex3(Vector3.UnitX);
                GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX + new Vector3(-0.125f, 0.125f, 0.0f));
                GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX + new Vector3(-0.125f, -0.125f, 0.0f));

                //y
                GL.Color3(Color.Green);
                GL.Vertex3(Vector3.Zero);
                GL.Vertex3(Vector3.UnitY);
                GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY + new Vector3(0.125f, -0.125f, 0.0f));
                GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY + new Vector3(-0.125f, -0.125f, 0.0f));

                //z
                GL.Color3(Color.Blue);
                GL.Vertex3(Vector3.Zero);
                GL.Vertex3(Vector3.UnitZ);
                GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ + new Vector3(0, -0.125f, -0.125f));
                GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ + new Vector3(0, 0.125f, -0.125f));

                GL.End();
            }

            //TODO: Decide what to do with non-version 4 models.
            if (model != null && model.Version == 4)
            {
                GL.PushMatrix();

                GL.PushAttrib(AttribMask.PolygonBit | AttribMask.EnableBit | AttribMask.LightingBit | AttribMask.CurrentBit);

                GL.UseProgram(currentShader);

                GL.Enable(EnableCap.DepthTest);
                GL.Enable(EnableCap.CullFace);
                GL.Enable(EnableCap.Texture2D);
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                GL.CullFace(CullFaceMode.Back);
                GL.FrontFace(FrontFaceDirection.Cw);



                for (Int32 i = 0; i < model.Meshes.Length; ++i)
                {
                    Mesh mesh = model.Meshes[i];

                    GL.ActiveTexture(TextureUnit.Texture0);
                    GL.BindTexture(TextureTarget.Texture2D, textures[i]);

                    if (currentShader == texturedShader)
                    {
                        int loc = GL.GetUniformLocation(currentShader, "colorMap");
                        GL.Uniform1(loc, 0);
                    }

                    //pin handles to stream data
                    GCHandle[] streamDataGCHandles = new GCHandle[mesh.VertexStreams.Length];

                    for (Int32 j = 0; j < streamDataGCHandles.Length; ++j)
                    {
                        streamDataGCHandles[j] = GCHandle.Alloc(mesh.VertexStreams[j].Data, GCHandleType.Pinned);
                    }

                    //fetch material definition and vertex layout
                    Int32 materialIndex                   = (Int32)mesh.MaterialIndex;
                    uint  materialDefinitionHash          = model.Materials[materialIndex].MaterialDefinitionHash;
                    MaterialDefinition materialDefinition = null;
                    VertexLayout       vertexLayout       = null;

                    if (MaterialDefinitionManager.Instance.MaterialDefinitions.ContainsKey(materialDefinitionHash))
                    {
                        materialDefinition = MaterialDefinitionManager.Instance.MaterialDefinitions[materialDefinitionHash];
                        vertexLayout       = MaterialDefinitionManager.Instance.VertexLayouts[materialDefinition.DrawStyles[0].VertexLayoutNameHash];
                    }

                    GL.Color3(meshColors[i % meshColors.Length]);

                    if (renderModeWireframeButton.Checked)
                    {
                        GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
                    }
                    else
                    {
                        GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                    }

                    //position
                    VertexLayout.Entry.DataTypes positionDataType = VertexLayout.Entry.DataTypes.None;
                    Int32 positionStream = 0;
                    Int32 positionOffset = 0;
                    bool  positionExists = (vertexLayout != null ? vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStream, out positionOffset) : false);

                    if (positionExists)
                    {
                        IntPtr positionData = streamDataGCHandles[positionStream].AddrOfPinnedObject();

                        GL.EnableClientState(ArrayCap.VertexArray);
                        GL.VertexPointer(3, VertexPointerType.Float, mesh.VertexStreams[positionStream].BytesPerVertex, positionData + positionOffset);
                    }

                    //normal
                    VertexLayout.Entry.DataTypes normalDataType = VertexLayout.Entry.DataTypes.None;
                    Int32 normalStream = 0;
                    Int32 normalOffset = 0;
                    bool  normalExists = (vertexLayout != null ? vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Normal, 0, out normalDataType, out normalStream, out normalOffset) : false);

                    if (normalExists)
                    {
                        IntPtr normalData = streamDataGCHandles[normalStream].AddrOfPinnedObject();

                        GL.EnableClientState(ArrayCap.NormalArray);
                        GL.NormalPointer(NormalPointerType.Float, mesh.VertexStreams[normalStream].BytesPerVertex, normalData + normalOffset);
                    }


                    //texture coordiantes
                    VertexLayout.Entry.DataTypes texCoord0DataType = VertexLayout.Entry.DataTypes.None;
                    Int32 texCoord0Stream = 0;
                    Int32 texCoord0Offset = 0;
                    bool  texCoord0Exists = (vertexLayout != null ? vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0Stream, out texCoord0Offset) : false);

                    if (texCoord0Exists)
                    {
                        IntPtr texCoord0Data = streamDataGCHandles[texCoord0Stream].AddrOfPinnedObject();

                        GL.EnableClientState(ArrayCap.TextureCoordArray);

                        TexCoordPointerType texCoord0PointerType = TexCoordPointerType.Float;

                        switch (texCoord0DataType)
                        {
                        case VertexLayout.Entry.DataTypes.Float2:
                            texCoord0PointerType = TexCoordPointerType.Float;
                            break;

                        case VertexLayout.Entry.DataTypes.float16_2:
                            texCoord0PointerType = TexCoordPointerType.HalfFloat;
                            break;

                        default:
                            break;
                        }

                        GL.TexCoordPointer(2, texCoord0PointerType, mesh.VertexStreams[texCoord0Stream].BytesPerVertex, texCoord0Data + texCoord0Offset);
                    }



                    //indices
                    GCHandle indexDataHandle = GCHandle.Alloc(mesh.IndexData, GCHandleType.Pinned);
                    IntPtr   indexData       = indexDataHandle.AddrOfPinnedObject();

                    GL.DrawElements(PrimitiveType.Triangles, (Int32)mesh.IndexCount, DrawElementsType.UnsignedShort, indexData);

                    indexDataHandle.Free();

                    GL.DisableClientState(ArrayCap.VertexArray);
                    GL.DisableClientState(ArrayCap.NormalArray);
                    GL.DisableClientState(ArrayCap.TextureCoordArray);

                    //free stream data handles
                    for (Int32 j = 0; j < streamDataGCHandles.Length; ++j)
                    {
                        streamDataGCHandles[j].Free();
                    }
                }

                GL.UseProgram(0);

                GL.PopAttrib();

                ////bounding box
                //if (showBoundingBoxButton.Checked)
                //{
                //    GL.PushAttrib(AttribMask.CurrentBit | AttribMask.EnableBit);

                //    GL.Color3(Color.Red);

                //    GL.Enable(EnableCap.DepthTest);

                //    Vector3 min = model.Min;
                //    Vector3 max = model.Max;
                //    Vector3[] vertices = new Vector3[8];
                //    UInt32[] indices = { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4 };

                //    vertices[0] = min;
                //    vertices[1] = new Vector3(max.X, min.Y, min.Z);
                //    vertices[2] = new Vector3(max.X, min.Y, max.Z);
                //    vertices[3] = new Vector3(min.X, min.Y, max.Z);
                //    vertices[4] = new Vector3(min.X, max.Y, min.Z);
                //    vertices[5] = new Vector3(max.X, max.Y, min.Z);
                //    vertices[6] = max;
                //    vertices[7] = new Vector3(min.X, max.Y, max.Z);

                //    GL.EnableClientState(ArrayCap.VertexArray);
                //    GL.VertexPointer(3, VertexPointerType.Float, 0, vertices);
                //    GL.DrawRangeElements(BeginMode.Lines, 0, 23, 24, DrawElementsType.UnsignedInt, indices);

                //    GL.PopAttrib();
                //}
            }

            glControl1.SwapBuffers();
        }
Esempio n. 3
0
        /// <summary>
        /// Exports a model to the given directory.
        /// </summary>
        private void ExportModel(Model model, StringBuilder stringBuilder, ref byte[] textureBuffer)
        {
            //TODO: Figure out what to do with non-version 4 models.
            if (model == null || model.Version != 4)
            {
                return;
            }

            string directory = ResourceDir + "/Models";
            string path      = directory + @"\" + Path.GetFileNameWithoutExtension(model.Name) + ".obj";

            if (File.Exists(path))
            {
                return;
            }

            // Validate meshes attached to the model
            foreach (Mesh mesh in model.Meshes)
            {
                if (!ForgelightGame.MaterialDefinitionManager.MaterialDefinitions.ContainsKey(model.Materials[(int)mesh.MaterialIndex].MaterialDefinitionHash))
                {
                    return;
                }
            }

            // The texture directory may not exist yet.
            Directory.CreateDirectory(directory + @"\Textures");

            // We reset the string builder so we don't have any previous buffer left over.
            stringBuilder.Length = 0;

            // Materials and Textures
            foreach (Mesh mesh in model.Meshes)
            {
                if (mesh.BaseDiffuse != null)
                {
                    ExportTexture(mesh.BaseDiffuse, directory, ref textureBuffer);
                    ExportMaterial(mesh, directory);
                    stringBuilder.AppendLine("mtllib " + Path.GetFileNameWithoutExtension(mesh.BaseDiffuse) + ".mtl");
                }

                if (mesh.SpecMap != null)
                {
                    ExportTexture(mesh.SpecMap, directory, ref textureBuffer);
                }

                if (mesh.BumpMap != null)
                {
                    ExportTexture(mesh.BumpMap, directory, ref textureBuffer);
                }
            }

            // Meshes
            foreach (Mesh mesh in model.Meshes)
            {
                MaterialDefinition materialDefinition = ForgelightGame.MaterialDefinitionManager.MaterialDefinitions[model.Materials[(int)mesh.MaterialIndex].MaterialDefinitionHash];
                VertexLayout       vertexLayout       = ForgelightGame.MaterialDefinitionManager.VertexLayouts[materialDefinition.DrawStyles[0].VertexLayoutNameHash];

                //position
                VertexLayout.Entry.DataTypes positionDataType;
                int positionOffset;
                int positionStreamIndex;

                vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStreamIndex, out positionOffset);

                Mesh.VertexStream positionStream = mesh.VertexStreams[positionStreamIndex];

                for (int j = 0; j < mesh.VertexCount; ++j)
                {
                    Vector3 position = ReadVector3(positionOffset, positionStream, j);

                    stringBuilder.AppendLine("v " + position.x.ToString(format) + " " +
                                             position.y.ToString(format) + " " + position.z.ToString(format));
                }

                //texture coordinates
                VertexLayout.Entry.DataTypes texCoord0DataType;
                int texCoord0Offset;
                int texCoord0StreamIndex;

                bool texCoord0Present = vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(
                    VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0StreamIndex,
                    out texCoord0Offset);

                if (texCoord0Present)
                {
                    Mesh.VertexStream texCoord0Stream = mesh.VertexStreams[texCoord0StreamIndex];

                    for (int j = 0; j < mesh.VertexCount; ++j)
                    {
                        Vector2 texCoord;

                        switch (texCoord0DataType)
                        {
                        case VertexLayout.Entry.DataTypes.Float2:
                        {
                            texCoord.x = BitConverter.ToSingle(texCoord0Stream.Data,
                                                               (j * texCoord0Stream.BytesPerVertex) + 0);
                            texCoord.y = 1.0f - BitConverter.ToSingle(texCoord0Stream.Data,
                                                                      (j * texCoord0Stream.BytesPerVertex) + 4);
                            break;
                        }

                        case VertexLayout.Entry.DataTypes.float16_2:
                        {
                            texCoord.x = Half.FromBytes(texCoord0Stream.Data,
                                                        (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 0);
                            texCoord.y = 1.0f - Half.FromBytes(texCoord0Stream.Data,
                                                               (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 2);
                            break;
                        }

                        default:
                            texCoord.x = 0;
                            texCoord.y = 0;
                            break;
                        }

                        stringBuilder.AppendLine("vt " + texCoord.x.ToString(format) + " " +
                                                 texCoord.y.ToString(format));
                    }
                }
            }

            // Faces
            uint vertexCount = 0;

            for (int i = 0; i < model.Meshes.Count; ++i)
            {
                Mesh mesh = model.Meshes[i];
                stringBuilder.AppendLine("g Mesh" + i);

                // Specify Material
                if (mesh.BaseDiffuse != null)
                {
                    stringBuilder.AppendLine("usemtl " + Path.GetFileNameWithoutExtension(mesh.BaseDiffuse));
                }

                for (int j = 0; j < mesh.IndexCount; j += 3)
                {
                    uint index0, index1, index2;

                    switch (mesh.IndexSize)
                    {
                    case 2:
                        index0 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 0) + 1;
                        index1 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 2) + 1;
                        index2 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 4) + 1;
                        break;

                    case 4:
                        index0 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 0) + 1;
                        index1 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 4) + 1;
                        index2 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 8) + 1;
                        break;

                    default:
                        index0 = 0;
                        index1 = 0;
                        index2 = 0;
                        break;
                    }

                    stringBuilder.AppendLine("f " + index2 + "/" + index2 + "/" + index2 + " " + index1 + "/" +
                                             index1 + "/" + index1 + " " + index0 + "/" + index0 + "/" +
                                             index0);
                }

                vertexCount += mesh.VertexCount;

                File.WriteAllText(path, stringBuilder.ToString());
            }
        }