OpenGL / OpenTK中的模型纹理不一致

时间:2015-11-02 02:27:54

标签: c# opengl modeling opentk uv-mapping

我正在创建一个模型导入器,它将.obj转换为我自己的专有格式,将用于我正在创建的游戏。我的模型解析器最初看起来工作得很好,加载来自塞尔达传说等各种游戏的小型模型,但无论出于何种原因,都无法正确地纹理化高级模型,如来自Borderlands的Claptrap。以下是一些屏幕抓取来向您展示我的意思:

使用zelda模型的模型加载器: enter image description here

然后Claptrap没有正确纹理: enter image description here

尽管它在Blender中纹理很好: enter image description here

我不明白这一点,也不知道错误的来源。这是我的WavefrontParser的代码,它可能会产生一些我不知道的大型模型的无法预料的错误:

process.stdin

我的WavefrontModel类:

using System;
using System.Collections.Generic;
using System.IO;
using OpenTK;
using StardustModeling.Modeling.DataTypes;

namespace StardustModeling.Modeling.Parsers
{
    /// <summary>
    /// 
    /// Stardust Engine
    /// 
    /// A simple, lightweight WavefrontModel Parser. This
    /// class serves as the basis for the Stardust Model
    /// conversion wizard. All Stardust Models(.sdm) start
    /// out as .obj files; this class is how we load them
    /// before the conversion to .sdm begins.
    /// 
    /// Original Author: Gordon Kyle Wallace, "Krythic"
    /// 
    /// </summary>
    public static class WavefrontModelParser
    {
        /// <summary>
        /// Parses a Wavefront .obj file. The given
        /// file must be triangulated and have normals
        /// included during exportation from Blender.
        /// </summary>
        /// <param name="path">The path of the .obj on disk</param>
        /// <returns>A WavefrontModel Instance</returns>
        public static WavefrontModel Parse( string path )
        {
            WavefrontModel model = new WavefrontModel();
            VertexIndex[] verticesIndex;
            string[] wavefrontFileData = File.ReadAllLines( path );
            int loopLength = wavefrontFileData.Length; // Squeeze out every last drop!
            for( int lines = 0; lines < loopLength; lines++ )
            {
                string[] lineTokens = wavefrontFileData[ lines ].Split( ' ' );
                switch( lineTokens[ 0 ] )
                {
                    case "v": // Vector
                        float x = Single.Parse( lineTokens[ 1 ] );
                        float y = Single.Parse( lineTokens[ 2 ] );
                        float z = Single.Parse( lineTokens[ 3 ] );
                        model.Vertices.Add( new Vector3( x , y , z ) );
                        break;
                    case "vt": // Texture Coordinate
                        float u = Single.Parse( lineTokens[ 1 ] );
                        float v = Single.Parse( lineTokens[ 2 ] );
                        model.TexCoords.Add( new Vector2( u , v ) );
                        break;
                    case "vn": // Normal
                        float normalX = Single.Parse( lineTokens[ 1 ] );
                        float normalY = Single.Parse( lineTokens[ 2 ] );
                        float normalZ = Single.Parse( lineTokens[ 3 ] );
                        model.Normals.Add( new Vector3( normalX , normalY , normalZ ) );
                        break;
                    case "f":
                        verticesIndex = new VertexIndex[ 3 ];
                        for( int i = 0; i < 3; i++ )
                        {
                            string[] parameters = lineTokens[ i + 1 ].Split( '/' );
                            int vertice = Int32.Parse( parameters[ 0 ] ) - 1;
                            int texture = Int32.Parse( parameters[ 1 ] ) - 1;
                            int normal = Int32.Parse( parameters[ 2 ] ) - 1;
                            verticesIndex[ i ] = new VertexIndex( vertice , normal , texture );
                        }
                        model.Faces.Add( new Face( verticesIndex ) );
                        break;
                }
            }
            return model;
        }
    }
}

我的Material类,也可能会出错:

using System.Collections.Generic;
using OpenTK;
using StardustModeling.Modeling.Parsers;

namespace StardustModeling.Modeling.DataTypes
{
    public class WavefrontModel
    {
        public List<Vector3> Vertices;
        public List<Vector2> TexCoords;
        public List<Vector3> Normals;
        public List<Face> Faces;
        public string ModelSource;

        public int TotalTriangles
        {
            get
            {
                return this.Vertices.Count/3;
            }
        }

        public WavefrontModel()
        {
            this.Vertices = new List<Vector3>();
            this.TexCoords = new List<Vector2>();
            this.Normals = new List<Vector3>();
            this.Faces = new List<Face>();
        }

        public WavefrontModel(int buffer)
        {
            this.Vertices = new List<Vector3>(buffer);
            this.TexCoords = new List<Vector2>(buffer);
            this.Normals = new List<Vector3>(buffer);
            this.Faces = new List<Face>(buffer);
        }

        public WavefrontModel(string modelPath, bool loadImmediately)
        {
            this.ModelSource = modelPath;
            if (loadImmediately)
            {
                Load();
            }
        }

        private void Load()
        {
            WavefrontModel model = WavefrontModelParser.Parse(ModelSource);
            this.Vertices = model.Vertices;
            this.TexCoords = model.TexCoords;
            this.Normals = model.Normals;
            this.Faces = model.Faces;
        }
    }

}

如果有人能帮助我发现这个错误,我真的很喜欢它;我开始把头发撕掉了(我不必从头开始,哈哈)。

编辑:

我忘了提到我是如何渲染这个的。我使用OpenTK / OpenGL,并通过立即模式绘制(用于初始应用程序测试)。

using System.Drawing;
using System.Drawing.Imaging;
using OpenTK.Graphics.OpenGL;
using PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat;

namespace StardustFramework.Framework.OpenGL.Texturing
{
    public enum MaterialType
    {
        /// <summary>
        /// Represents a Diffuse Texture
        /// </summary>
        Diffuse,
        /// <summary>
        /// Represents a Normal Texture
        /// </summary>
        Normal
    }

    public class Material
    {
        /// <summary>
        /// The name of the Material
        /// </summary>
        public string Name;
        /// <summary>
        /// The Diffuse Texture
        /// </summary>
        public int Diffuse;
        /// <summary>
        /// The Normal Texture
        /// </summary>
        public int NormalMap;
        /// <summary>
        /// The Ambient Color for the Material
        /// </summary>
        public Color AmbientColor;

        public Material( string materialName )
        {
            this.Name = materialName;
            this.AmbientColor = Color.White;
            this.Diffuse = 0;
            this.NormalMap = 0;
        }

        /// <summary>
        /// Loads a Bitmap as a Diffuse texture.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        public void LoadDiffuse( Bitmap bitmap)
        {
            GL.Enable( EnableCap.Texture2D );
            //GL.Hint( HintTarget.PerspectiveCorrectionHint , HintMode.Nicest );
            GL.GenTextures( 1 , out Diffuse );
            GL.BindTexture( TextureTarget.Texture2D , Diffuse );
            GL.TexParameter( TextureTarget.Texture2D , TextureParameterName.TextureMinFilter , ( int )TextureMinFilter.Nearest );
            GL.TexParameter( TextureTarget.Texture2D , TextureParameterName.TextureMagFilter , ( int )TextureMagFilter.Nearest );
            BitmapData data = bitmap.LockBits( new Rectangle( 0 , 0 , bitmap.Width , bitmap.Height ) ,
                ImageLockMode.ReadOnly , System.Drawing.Imaging.PixelFormat.Format32bppArgb );
            GL.TexImage2D( TextureTarget.Texture2D , 0 , PixelInternalFormat.Rgba , data.Width , data.Height , 0 ,
                PixelFormat.Bgra , PixelType.UnsignedByte , data.Scan0 );
            bitmap.UnlockBits( data );
            GL.BindTexture( TextureTarget.Texture2D , 0 );
        }
    }
}

1 个答案:

答案 0 :(得分:0)

在经历了许多难以忍受的撕裂我的头发之后,我终于意识到了我的问题。我没想到的,现在对我来说似乎很愚蠢,就是我试图在OpenGL环境中构建为DirectX制作的模型。为什么这很重要?好吧,在OpenGL中,纹理原点是左下角0,0。在DirectX中它是左上角。因此,只需在gimp中垂直翻转纹理,我就可以使用它。

enter image description here

很高兴知道我的模型加载器没有任何问题,我只是没有考虑我正在使用的模型的目标平台/ api。