我正在創建一個模型導入器,它將.obj的轉換爲我自己的專有格式,將用於我創建的遊戲。我的模型解析器似乎一開始就工作得很好,從像塞爾達傳說這樣的各種遊戲中加載小模型,但無論如何,都無法正確紋理先進的模型,比如來自無主之地的Claptrap。下面是一些屏幕爭奪向你展示我的意思:在OpenGL/OpenTK中不一致的模型紋理
我不明白這一點,也不知道錯誤來自哪裏。這裏是我的WavefrontParser的代碼,這可能會產生一些不可預見的錯誤較大的模型,我不知道的:
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;
}
}
}
我WavefrontModel類:
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;
}
}
}
我的材料類,這也可能產生一個錯誤:
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);
}
}
}
我真的很喜歡它,如果有人能幫我發現這個bug;我開始把我的頭髮撕掉(我不必從頭開始,哈哈)。
編輯:
我忘了提到我如何渲染這個。我使用OpenTK/OpenGL,並通過即時模式繪製(用於初始應用程序測試)。
private void DrawMesh(WavefrontModel m)
{
GL.Enable(EnableCap.Texture2D);
GL.Color3(_modelMaterial.AmbientColor);
if(_modelMaterial.Diffuse > 0)
{
GL.BindTexture(TextureTarget.Texture2D , _modelMaterial.Diffuse);
}
GL.Begin(PrimitiveType.Triangles);
for(int i = 0; i < m.Faces.Count; i++)
{
for(int index = 0; index < m.Faces[ i ].Indices.Length; index++)
{
Vector3 v = m.Vertices[ m.Faces[ i ].Indices[ index ].Vector ];
Vector3 n = m.Normals[ m.Faces[ i ].Indices[ index ].Normal ];
Vector2 tc = m.TexCoords[ m.Faces[ i ].Indices[ index ].TextureCoordinateIndex ];
GL.Normal3(n.X , n.Y , n.Z);
GL.TexCoord2(tc.X , tc.Y);
GL.Vertex3(v.X , v.Y , v.Z);
}
}
GL.End();
}
我剛放下牀,開始打瞌睡,當一個可能的解決方案打我。我認爲問題在於Floats的解析。我可能會在將字符串轉換爲浮點數的時候出現一些降級(當float更抽象時,比如使用高級uv建模)。我明天會做一些調試。不過,這可能與其他東西完全不相關。 – Krythic
downvote的理由?如有必要,我可以提供更多代碼。僅僅因爲一個問題很複雜,並不值得降低價值。 – Krythic