编辑:我已经回答了这个问题并且代码已经更改,所以它是可用的,请随意在您自己的项目中使用代码。亲切的问候,利亚姆
我目前正在使用 LWJGL 进行 3D 模型渲染,我遇到了一个问题,当我运行程序时,显示出现并且除了模型之外一切都可以工作。我测试了 3D 空间代码,绘制了一些随机点,我可以看到它们并四处走动,所以我的 3D 空间代码可以工作,但模型代码不能。
我的问题如下,是我的显示代码有问题还是我的模型加载代码,以下是我的源代码(很抱歉代码量很大,但我无法缩短它)。
游戏主线:
public class GameThread implements Runnable {
private boolean running;
private Camera cam = new Camera(0, 0, 0, 0, 0.25f, 25, new int[] {Keyboard.KEY_W, Keyboard.KEY_S, Keyboard.KEY_A, Keyboard.KEY_D});
private Model testModel;
@Override
public void run()
{
initialize();
while(running)
{
if(Display.isCloseRequested())
tryClose();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
tick();
Display.update();
}
close();
}
private void initialize()
{
try
{
Display.setTitle("Test Game");
Display.setDisplayMode(new DisplayMode(1280, 768));
Display.setVSyncEnabled(true);
Display.create();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective((float) 30, 1024f / 768f, 0.001f, 100);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
testModel = new Model(this.getClass().getClassLoader().getResource("res\\untitled.obj"), new Vector3f(0, 0, 0), new Vector3f(0, 0, 0));
cam.setPosition(new Vector3f(0, 0, -10));
running = true;
}
catch(Exception e)
{
Display.destroy();
e.printStackTrace();
System.exit(1);
}
}
private void tick()
{
cam.update();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
testModel.draw();
}
private void tryClose()
{
running = false;
}
private void close()
{
Display.destroy();
}
模型加载/渲染代码:
public class Model {
private HashMap<String, ModelGroup> groups = new HashMap<String, ModelGroup>();
private Vector3f position, rotation;
public Model(URL modelLocation, Vector3f position, Vector3f rotation)
{
this.setPosition(position);
this.setRotation(rotation);
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(modelLocation.openStream()));
String line;
ModelGroup group = new ModelGroup("default");
while((line = in.readLine()) != null)
{
if(line.startsWith("g "))
{
String newGroupName = (new StringTokenizer(line)).nextToken();
if(newGroupName.equals(group.getGroupName()))
continue;
groups.put(group.getGroupName(), group);
group = new ModelGroup(newGroupName);
}
else if(line.startsWith("v "))
{
StringTokenizer vertices = new StringTokenizer(line);
vertices.nextToken(); // Skips 'v'
float x, y, z, w = 1;
x = Float.valueOf(vertices.nextToken());
y = Float.valueOf(vertices.nextToken());
z = Float.valueOf(vertices.nextToken());
if(vertices.hasMoreTokens())
w = Float.valueOf(vertices.nextToken());
else
w = 1;
group.addVertice(new Vector4f(x, y, z, w));
}
else if(line.startsWith("vn "))
{
StringTokenizer normalVertices = new StringTokenizer(line);
normalVertices.nextToken(); // Skips 'vn'
float x, y, z;
x = Float.valueOf(normalVertices.nextToken());
y = Float.valueOf(normalVertices.nextToken());
z = Float.valueOf(normalVertices.nextToken());
group.addNormal(new Vector3f(x, y, z));
}
else if(line.startsWith("vt "))
{
StringTokenizer textureVertices = new StringTokenizer(line);
textureVertices.nextToken(); // Skips 'vt'
float u, v, w;
u = Float.valueOf(textureVertices.nextToken());
if(textureVertices.hasMoreTokens())
v = Float.valueOf(textureVertices.nextToken());
else
v = 0;
if(textureVertices.hasMoreTokens())
w = Float.valueOf(textureVertices.nextToken());
else
w = 0;
group.addTextureCoordinate(new Vector3f(u, v, w));
}
else if(line.startsWith("f "))
{
StringTokenizer token = new StringTokenizer(line.replace('f', ' '));
String[] indices = new String[token.countTokens()];
int polygon_type = (indices.length == 3 ? GL_TRIANGLES : GL_QUADS);
for(int i = 0; i < indices.length; i++)
indices[i] = token.nextToken();
int mode = 0;
if(line.contains("//"))
mode = 3;
if(mode != 3)
if(indices[0].split("/").length == 2)
mode = 1;
else if(indices[0].split("/").length == 3)
mode = 2;
if(mode == 0)
{
Vector4f vertices = new Vector4f();
vertices.set(Float.valueOf(indices[0]), Float.valueOf(indices[1]), Float.valueOf(indices[2]), (indices.length == 4 ? Float.valueOf(indices[3]) : -1));
group.addFace(new ModelFace(vertices).setPolygonType(polygon_type));
}
else if(mode == 1)
{
float x, y, z, vw;
float u, v, tw;
x = Float.valueOf(indices[0].split("/")[0]);
y = Float.valueOf(indices[1].split("/")[0]);
z = Float.valueOf(indices[2].split("/")[0]);
if(indices.length == 4)
vw = Float.valueOf(indices[3].split("/")[0]);
else
vw = -1;
u = Float.valueOf(indices[0].split("/")[1]);
v = Float.valueOf(indices[1].split("/")[1]);
tw = Float.valueOf(indices[2].split("/")[1]);
group.addFace(new ModelFace(new Vector4f(x, y, z, vw), new Vector3f(u, v, tw), new Vector3f(-1, 0, 0)).setPolygonType(polygon_type));
}
else if(mode == 2)
{
float vx, vy, vz, vw;
float u, v, tw;
float nx, ny, nz;
vx = Float.valueOf(indices[0].split("/")[0]);
vy = Float.valueOf(indices[1].split("/")[0]);
vz = Float.valueOf(indices[2].split("/")[0]);
if(indices.length == 4)
vw = Float.valueOf(indices[3].split("/")[0]);
else
vw = -1;
u = Float.valueOf(indices[0].split("/")[1]);
v = Float.valueOf(indices[1].split("/")[1]);
tw = Float.valueOf(indices[2].split("/")[1]);
nx = Float.valueOf(indices[0].split("/")[2]);
ny = Float.valueOf(indices[1].split("/")[2]);
nz = Float.valueOf(indices[2].split("/")[2]);
group.addFace(new ModelFace(new Vector4f(vx, vy, vz, vw), new Vector3f(u, v, tw), new Vector3f(nx, ny, nz)).setPolygonType(polygon_type));
}
else if(mode == 3)
{
float vx, vy, vz, vw;
float nx, ny, nz;
System.out.println(indices[0]);
vx = Float.valueOf(indices[0].split("//")[0]);
vy = Float.valueOf(indices[1].split("//")[0]);
vz = Float.valueOf(indices[2].split("//")[0]);
if(indices.length == 4)
vw = Float.valueOf(indices[3].split("//")[0]);
else
vw = -1;
nx = Float.valueOf(indices[0].split("//")[1]);
ny = Float.valueOf(indices[1].split("//")[1]);
nz = Float.valueOf(indices[2].split("//")[1]);
group.addFace(new ModelFace(new Vector4f(vx, vy, vz, vw), new Vector3f(-1, 0, 0), new Vector3f(nx, ny, nz)).setPolygonType(polygon_type));
}
}
}
groups.put(group.getGroupName(), group);
in.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public Vector3f getPosition() {
return position;
}
public void setPosition(Vector3f position) {
this.position = position;
}
public Vector3f getRotation() {
return rotation;
}
public void setRotation(Vector3f rotation) {
this.rotation = rotation;
}
public void draw()
{
ArrayList<ModelGroup> groups = new ArrayList<ModelGroup>(this.groups.values());
for(int i = 0; i < groups.size(); i++)
drawGroup(groups.get(i).getGroupName());
}
public void drawGroup(String name)
{
ModelGroup group = groups.get(name);
if(group == null)
return;
glPushMatrix();
{
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
glTranslatef(position.x, position.y, position.z);
for(ModelFace face : group.getFaces())
{
glBegin(face.getPolygonType());
{
for(int id = 0; id < 3; id++)
{
Vector4f vertex = group.getVertices().get(face.getVerticeIndex(id));
glVertex4f(vertex.x, vertex.y, vertex.z, vertex.w);
if(face.hasTextureCoordinates())
{
Vector3f textureCoordinate = group.getTextureCoordinates().get(face.getTextureCoordinateIndex(id));
glTexCoord3f(textureCoordinate.x, textureCoordinate.y, textureCoordinate.z);
}
if(face.hasNormals())
{
Vector3f normal = group.getNormals().get(face.getNormalIndex(id));
glNormal3f(normal.x, normal.y, normal.z);
}
}
if(face.getPolygonType() == GL_QUADS)
{
Vector4f vertex = group.getVertices().get(face.getVerticeIndex(3));
glVertex4f(vertex.x, vertex.y, vertex.z, vertex.w);
}
}
glEnd();
}
}
glPopMatrix();
}
//====================================================================================================//
private class ModelGroup
{
private final String groupName;
private ArrayList<Vector4f> vertices = new ArrayList<Vector4f>();
private ArrayList<Vector3f> normals = new ArrayList<Vector3f>();
private ArrayList<Vector3f> textureCoordinates = new ArrayList<Vector3f>();
private ArrayList<ModelFace> faces = new ArrayList<ModelFace>();
public ModelGroup(String name) {
this.groupName = name;
}
public String getGroupName() {
return this.groupName;
}
public void addVertice(Vector4f vertice) {
this.vertices.add(vertice);
}
public ArrayList<Vector4f> getVertices() {
return this.vertices;
}
public void addNormal(Vector3f normal) {
this.normals.add(normal);
}
public ArrayList<Vector3f> getNormals() {
return this.normals;
}
public void addTextureCoordinate(Vector3f coordinate) {
this.textureCoordinates.add(coordinate);
}
public ArrayList<Vector3f> getTextureCoordinates() {
return this.textureCoordinates;
}
public void addFace(ModelFace face) {
this.faces.add(face);
}
public ArrayList<ModelFace> getFaces() {
return this.faces;
}
}
private class ModelFace {
private Vector4f vertices;
private Vector3f textureCoordinates, normals;
private int POLYGON_TYPE = 0;
private boolean hasTextureCoords = true, hasNormals = true;
public ModelFace(Vector4f vertices) {
this(vertices, new Vector3f(-1, 0, 0), new Vector3f(-1, 0, 0));
}
public ModelFace(Vector4f vertices, Vector3f textureCoordinates, Vector3f normals)
{
this.vertices = vertices;
this.textureCoordinates = textureCoordinates;
this.normals = normals;
if(this.textureCoordinates.x == -1)
this.hasTextureCoords = false;
if(this.normals.x == -1)
this.hasNormals = false;
}
public boolean hasTextureCoordinates() {
return this.hasTextureCoords;
}
public boolean hasNormals() {
return this.hasNormals;
}
public int getVerticeIndex(int id)
{
if(id == 0)
return (int)vertices.x - 1;
else if(id == 1)
return (int)vertices.y - 1;
else if(id == 2)
return (int)vertices.z - 1;
else if(id == 3)
return (int)vertices.w - 1;
else
return -1;
}
public int getTextureCoordinateIndex(int id)
{
if(id == 0)
return (int)textureCoordinates.x - 1;
else if(id == 1)
return (int)textureCoordinates.y - 1;
else if(id == 2)
return (int)textureCoordinates.z - 1;
else
return -1;
}
public int getNormalIndex(int id)
{
if(id == 0)
return (int)textureCoordinates.x - 1;
else if(id == 1)
return (int)textureCoordinates.y - 1;
else if(id == 2)
return (int)textureCoordinates.z - 1;
else
return -1;
}
public ModelFace setPolygonType(int type) {
this.POLYGON_TYPE = type;
return this;
}
public int getPolygonType() {
return this.POLYGON_TYPE;
}
}
}
谢谢,利亚姆。