- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我决定在我的 OpenTK C# 游戏中实现一个模型加载器;除了纹理坐标完全奇怪之外,它渲染得很好。我使用的代码是我在 Internet 上找到的 OpenTK 模型加载器的略微修改版本。我曾尝试在 blender 中对我的模型进行紫外线展开,但结果似乎总是一团糟。
这是我的模型在 Blender 中的样子:
这是它在我的游戏中的样子:
这是我的 WavefrontModel 类:
using System.Collections.Generic;
using OpenTK;
namespace GameProject.Game.Framework.ModelLoader {
public class WavefrontModel {
public List<Vector3> Vertices;
public List<Vector2> TexCoords;
public List<Vector3> Normals;
public List<Face> Faces;
public WavefrontModel( string modelPath ) {
loadModel( modelPath );
}
public WavefrontModel(
List<Vector3> points , List<Vector2> texCoords , List<Vector3> normals , List<Face> faces ) {
this.Vertices = points;
this.TexCoords = texCoords;
this.Normals = normals;
this.Faces = faces;
}
private void loadModel( string modelPath ) {
WavefrontModel model = new WavefrontModelLoader().LoadFile( modelPath );
this.Vertices = model.Vertices;
this.TexCoords = model.TexCoords;
this.Normals = model.Normals;
this.Faces = model.Faces;
}
}
public struct ModelVertex {
public int Vertex;
public int Normal;
public int TexCoord;
public ModelVertex( int v , int n , int t ) {
Vertex = v;
Normal = n;
TexCoord = t;
}
}
public struct Face {
public ModelVertex[] Points;
public Face( int i ) {
Points = new ModelVertex[ i ];
}
public Face( ModelVertex[] i ) {
Points = i;
}
}
}
这是我的 WavefrontModelLoader 类:
using System.Collections.Generic;
using System.IO;
using OpenTK;
namespace GameProject.Game.Framework.ModelLoader {
public class WavefrontModelLoader {
public WavefrontModel LoadStream( Stream stream ) {
StreamReader reader = new StreamReader( stream );
List<Vector3> points = new List<Vector3>();
List<Vector3> normals = new List<Vector3>();
List<Vector2> texCoords = new List<Vector2>();
List<int> indices = new List<int>();
List<Face> faces = new List<Face>();
string line;
char[] splitChars = { ' ' };
while( ( line = reader.ReadLine() ) != null ) {
line = line.Trim( splitChars );
line = line.Replace( " " , " " );
string[] parameters = line.Split( splitChars );
switch( parameters[ 0 ] ) {
case "p": // Point
break;
case "v": // Vertex
float x = float.Parse( parameters[ 1 ] );
float y = float.Parse( parameters[ 2 ] );
float z = float.Parse( parameters[ 3 ] );
points.Add( new Vector3( x , y , z ) );
break;
case "vt": // TexCoord
float u = float.Parse( parameters[ 1 ] );
float v = float.Parse( parameters[ 2 ] );
texCoords.Add( new Vector2( u , v ) );
break;
case "vn": // Normal
float nx = float.Parse( parameters[ 1 ] );
float ny = float.Parse( parameters[ 2 ] );
float nz = float.Parse( parameters[ 3 ] );
normals.Add( new Vector3( nx , ny , nz ) );
break;
case "f":
faces.Add( parseFace( parameters ) );
break;
}
}
return new WavefrontModel(points,texCoords,normals,faces);
}
public WavefrontModel LoadFile( string file ) {
using( FileStream s = File.Open( file , FileMode.Open ) ) {
WavefrontModel mesh = LoadStream( s );
s.Close();
return mesh;
}
}
private static Face parseFace( string[] indices ) {
ModelVertex[] p = new ModelVertex[ indices.Length - 1 ];
for( int i = 0; i < p.Length; i++ ) {
p[ i ] = parsePoint( indices[ i + 1 ] );
}
return new Face( p );
}
private static ModelVertex parsePoint( string s ) {
char[] splitChars = { '/' };
string[] parameters = s.Split( splitChars );
int vert = int.Parse( parameters[ 0 ] ) - 1;
int tex = int.Parse( parameters[ 1 ] ) - 1;
int norm = int.Parse( parameters[ 2 ] ) - 1;
return new ModelVertex( vert , norm , tex );
}
}
}
我的模型是这样加载的:
rockMesh = new WavefrontModel( "C:/Users/Krynn/Desktop/RockModel/untitled.obj" );
然后像这样呈现:
private void DrawMesh(WavefrontModel m) {
GL.Enable( EnableCap.Texture2D );
GL.BindTexture( TextureTarget.Texture2D , rockTexture.GetID() );
GL.Begin( BeginMode.Triangles );
foreach( Face f in m.Faces ) {
foreach( ModelVertex p in f.Points ) {
Vector3 v = m.Vertices[ p.Vertex ];
Vector3 n = m.Normals[ p.Normal ];
Vector2 tc = m.TexCoords[ p.TexCoord ];
GL.Vertex3( v.X , v.Y , v.Z );
GL.Normal3( n.X , n.Y , n.Z );
GL.TexCoord2( tc.Y , tc.X );
}
}
GL.End();
}
这是 Blender 生成的模型,我注意到“vt”不是 1.0 和 0.0,这可能是问题所在吗?
# Blender v2.71 (sub 0) OBJ File: 'untitled.blend'
# www.blender.org
mtllib untitled.mtl
o Cube_Cube.001
v -0.872541 -0.208332 -0.514779
v -0.872541 -0.208332 -2.514779
v 1.127459 -0.208332 -2.514779
v 1.127459 -0.208332 -0.514779
v -0.872541 1.791668 -0.514779
v -0.872541 1.791668 -2.514779
v 1.127459 1.791668 -2.514779
v 1.127459 1.791668 -0.514779
vt 0.999900 0.000100
vt 0.999900 0.999900
vt 0.000100 0.999900
vt 0.000100 0.000100
vn -1.000000 0.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 6/1/1 2/2/1 1/3/1
f 7/1/2 3/2/2 2/3/2
f 8/3/3 4/4/3 3/1/3
f 5/3/4 1/4/4 4/1/4
f 2/4/5 3/1/5 4/2/5
f 7/2/6 6/3/6 5/4/6
f 5/4/1 6/1/1 1/3/1
f 6/4/2 7/1/2 2/3/2
f 7/2/3 8/3/3 3/1/3
f 8/2/4 5/3/4 4/1/4
f 1/3/5 2/4/5 4/2/5
f 8/1/6 7/2/6 5/4/6
此外,这是我的纹理类:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;
using System.Drawing.Imaging;
namespace GameProject.Game.Framework {
public class Texture {
private int textureID;
public Texture( string texturePath ) {
Load( texturePath );
}
public Texture( Bitmap texture ) {
LoadInternal( texture );
}
private void LoadInternal( Bitmap bitmap ) {
GL.Enable( EnableCap.Texture2D );
GL.Hint( HintTarget.PerspectiveCorrectionHint , HintMode.Nicest );
GL.GenTextures( 1 , out textureID );
GL.BindTexture( TextureTarget.Texture2D , textureID );
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 ,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra , PixelType.UnsignedByte , data.Scan0 );
bitmap.UnlockBits( data );
GL.BindTexture( TextureTarget.Texture2D , 0 );
}
public int GetID() {
return textureID;
}
private void Load( string texturePath ) {
GL.Enable( EnableCap.Texture2D );
if( System.IO.File.Exists( texturePath ) ) {
GL.Enable( EnableCap.Texture2D );
Bitmap bitmap = new Bitmap( texturePath );
GL.Hint( HintTarget.PerspectiveCorrectionHint , HintMode.Nicest );
GL.GenTextures( 1 , out textureID );
GL.BindTexture( TextureTarget.Texture2D , textureID );
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 ,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra , PixelType.UnsignedByte , data.Scan0 );
bitmap.UnlockBits( data );
}
}
}
}
关卡中没有其他硬编码几何体有这个问题;几何本身也是几千体素。除模型外的所有内容都具有正确的纹理坐标。
最佳答案
在遗留 OpenGL 中使用即时模式,glVertex*()
调用发出一个新顶点,使用当时设置的其他顶点属性(例如法线、颜色)的值。
在发布的代码中,调用顺序是这样的:
GL.Vertex3( v.X , v.Y , v.Z );
GL.Normal3( n.X , n.Y , n.Z );
GL.TexCoord2( tc.Y , tc.X );
由于 Vertex3
调用先进行,它将使用最近设置的法线和纹理坐标,它们是前一个顶点的值。 Normal3
和 TexCoord2
调用将更改这些属性的当前值,但新值将仅用于下一个 Vertex3()
打电话。
要为这个 顶点使用指定的法线和纹理坐标,Vertex3()
调用需要放在最后:
GL.Normal3( n.X , n.Y , n.Z );
GL.TexCoord2( tc.Y , tc.X );
GL.Vertex3( v.X , v.Y , v.Z );
关于c# - 加载模型时出现奇怪的 OpenGL 纹理坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25836774/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!