import java.io.*; import java.nio.file.*; import java.util.*; public class OBJLoader { public static class Vertex { public float x, y, z; // Position public float u, v; // Texture coordinates public float nx, ny, nz; // Normal public Vertex(float x, float y, float z, float u, float v, float nx, float ny, float nz) { this.x = x; this.y = y; this.z = z; this.u = u; this.v = v; this.nx = nx; this.ny = ny; this.nz = nz; } } public static class Model { public Listvertices = new ArrayList<>(); public List indices = new ArrayList<>(); } public static Model loadModel(String filePath) throws IOException { List positions = new ArrayList<>(); List texCoords = new ArrayList<>(); List normals = new ArrayList<>(); Model model = new Model(); List lines = Files.readAllLines(Paths.get(filePath)); for (String line : lines) { String[] tokens = line.split("\\s+"); switch (tokens[0]) { case "v": positions.add(new float[]{ Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3])}); break; case "vt": texCoords.add(new float[]{ Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2])}); break; case "vn": normals.add(new float[]{ Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3])}); break; case "f": for (int i = 1; i <= 3; i++) { // Assuming triangles String[] parts = tokens[i].split("/"); int posIndex = Integer.parseInt(parts[0]) - 1; int texIndex = Integer.parseInt(parts[1]) - 1; int normIndex = Integer.parseInt(parts[2]) - 1; float[] pos = positions.get(posIndex); float[] tex = texCoords.get(texIndex); float[] norm = normals.get(normIndex); Vertex vertex = new Vertex(pos[0], pos[1], pos[2], tex[0], tex[1], norm[0], norm[1], norm[2]); model.vertices.add(vertex); model.indices.add(model.vertices.size() - 1); } break; } } return model; } }
import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.util.glu.GLU; import org.newdawn.slick.opengl.Texture; import org.newdawn.slick.opengl.TextureLoader; import org.newdawn.slick.util.ResourceLoader; import java.io.File; import java.io.IOException; import java.nio.FloatBuffer; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL30.*; public class Main_test_simple_scene { // 窗口大小 private static final int WIDTH = 800; private static final int HEIGHT = 600; // 阴影贴图的大小 private static final int SHADOW_WIDTH = 1024; private static final int SHADOW_HEIGHT = 1024; // 帧缓冲对象和纹理对象 private int fbo; private int shadowMapTexture; // 光源位置 private float[] lightPosition = {0.0f, 10.0f, 0.0f, 1.0f}; Texture earthTexture; public void start() throws Exception { try { Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT)); Display.create(); } catch (LWJGLException e) { e.printStackTrace(); System.exit(0); } // Load texture data using your preferred library earthTexture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("Project1/Assignment3/res/earthspace.png")); initGL(); while (!Display.isCloseRequested()) { renderScene(); Display.update(); Display.sync(60); } Display.destroy(); } private void initGL() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLU.gluPerspective(45.0f, (float) WIDTH / HEIGHT, 1.0f, 100.0f); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLight(GL_LIGHT0, GL_POSITION, asFloatBuffer(new float[]{0.0f, 10.0f, 0.0f, 1.0f})); } static int xRot = 0; private void renderScene() { xRot++; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); GLU.gluLookAt(0.0f, 10.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); // 设置物体颜色 glColor3f(1.0f, 1.0f, 0.0f); // 绘制球体 glPushMatrix(); glTranslatef(0.0f, 4.0f, 0.0f); // Sphere sp = new Sphere(); // sp.draw(1.0f, 32, 32); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_CULL_FACE); // 启用剔除 glCullFace(GL_BACK); // 剔除背面 // draw obj sphere exported from blender // 然后创建缓冲区并使用这些数据进行渲染 glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, earthTexture.getTextureID()); try { glRotatef(xRot, 0, 1, 0); // glRotatef(30, 0, 0, 1); OBJLoader.Model model = OBJLoader.loadModel("C:\\Users\\adsfa\\Documents\\blender_textures\\earth.obj"); glEnable(GL_TEXTURE_2D); // 如果模型使用纹理 glBegin(GL_TRIANGLES); // 开始绘制三角形 for (int index : model.indices) { OBJLoader.Vertex v = model.vertices.get(index); glTexCoord2f(v.u, 1.f-v.v); // 纹理坐标 glNormal3f(v.nx, v.ny, v.nz); // 法线 glVertex3f(v.x, v.y, v.z); // 顶点坐标 } glEnd(); // 结束绘制 } catch (IOException e) { e.printStackTrace(); } glPopMatrix(); // // 绘制地面 glBegin(GL_QUADS); // glScalef(100, 1, 100); glNormal3f(0, 1, 1); glVertex3f(-5.0f, 0.0f, -5.0f); glVertex3f(-5.0f, 0.0f, 5.0f); glVertex3f(5.0f, 0.0f, 5.0f); glVertex3f(5.0f, 0.0f, -5.0f); glEnd(); } private FloatBuffer asFloatBuffer(float[] values) { FloatBuffer buffer = BufferUtils.createFloatBuffer(values.length); buffer.put(values); buffer.flip(); return buffer; } public static void main(String[] args) { Main_test_simple_scene example = new Main_test_simple_scene(); try { example.start(); } catch (Exception e) { e.printStackTrace(); } } }