使用 Java 的 OBJ 文件查看器

引言

OBJ 文件格式是一种广泛使用的三维模型文件格式,通常用于 3D 打印、游戏开发和计算机图形学中。本文将指导您如何使用 Java 创建一个简单的 OBJ 文件查看器,并展示如何读取和显示 OBJ 文件中的三维模型。

OBJ 文件格式简介

OBJ 文件是文本文件,包含 3D 模型的几何数据。这些数据包括顶点、纹理坐标和法线等。OBJ 文件的基本结构如下:

  • v x y z:定义一个三维点。
  • vt u v:定义一个纹理坐标。
  • vn x y z:定义一个法线。
  • f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3:定义一个面,由顶点、纹理坐标和法线组成。

示例 OBJ 文件

以下是一个简单的 OBJ 文件示例:

# Cube
v 1.0 1.0 1.0
v -1.0 1.0 1.0
v -1.0 -1.0 1.0
v 1.0 -1.0 1.0
v 1.0 1.0 -1.0
v -1.0 1.0 -1.0
v -1.0 -1.0 -1.0
v 1.0 -1.0 -1.0

f 1 2 3 4
f 5 6 7 8
f 1 5 8 4
f 2 6 7 3
f 1 2 6 5
f 4 3 7 8

Java 实现 OBJ 文件查看器

接下来,我们将创建一个简单的 Java 应用程序,用于读取并渲染 OBJ 文件的模型。

依赖库

我们将使用两个库来帮助我们实现 3D 渲染:

  1. Java 3D - Java 的图形库。
  2. Javacv - 用于图形转换和渲染的工具。

在 Maven 项目中,您可以在 pom.xml 文件中添加如下依赖:

<dependency>
    <groupId>org.jogamp.jogl</groupId>
    <artifactId>jogl-all</artifactId>
    <version>2.4.0</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.5</version>
</dependency>

读取 OBJ 文件

下面是读取 OBJ 文件的基本代码实现:

import java.io.*;
import java.util.*;

class ObjModel {
    List<float[]> vertices = new ArrayList<>();
    List<int[]> faces = new ArrayList<>();

    public void load(String filename) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line;
        while ((line = reader.readLine()) != null) {
            String[] tokens = line.trim().split("\\s+");
            if (tokens.length == 0 || tokens[0].equals("#")) continue; // 忽略空行和注释
            if (tokens[0].equals("v")) {
                float[] vertex = { Float.parseFloat(tokens[1]),
                                   Float.parseFloat(tokens[2]),
                                   Float.parseFloat(tokens[3]) };
                vertices.add(vertex);
            } else if (tokens[0].equals("f")) {
                int[] face = { Integer.parseInt(tokens[1]) - 1,
                               Integer.parseInt(tokens[2]) - 1,
                               Integer.parseInt(tokens[3]) - 1,
                               Integer.parseInt(tokens[4]) - 1 };
                faces.add(face);
            }
        }
        reader.close();
    }
}

渲染 OBJ 模型

接下来,我们需要创建一个渲染方法,以便将读取的 OBJ 模型显示在窗口中:

import javax.swing.*;
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLCanvas;

class ObjViewer extends JFrame implements GLEventListener {
    ObjModel model = new ObjModel();

    public ObjViewer() {
        setTitle("OBJ Viewer");
        setSize(800, 600);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        GLCanvas canvas = new GLCanvas();
        canvas.addGLEventListener(this);
        add(canvas);
        setVisible(true);
    }

    @Override
    public void init(GLAutoDrawable drawable) {
        try {
            model.load("path/to/your/model.obj");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void display(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glBegin(GL2.GL_TRIANGLES);
        for (int[] face : model.faces) {
            for (int vertexIndex : face) {
                float[] vertex = model.vertices.get(vertexIndex);
                gl.glVertex3f(vertex[0], vertex[1], vertex[2]);
            }
        }
        gl.glEnd();
        gl.glFlush();
    }
    
    // 其他必需的方法
    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}

    @Override
    public void dispose(GLAutoDrawable drawable) {}
}

主方法

最后,您需要一个主方法来启动应用程序:

public class Main {
    public static void main(String[] args) {
        new ObjViewer();
    }
}

序列图

在我们创建的 OBJ 文件查看器中,OBJ 文件的读取和渲染过程可以用以下序列图表示:

sequenceDiagram
    Actor ->> ObjViewer: Init()
    ObjViewer ->> ObjModel: load("model.obj")
    ObjModel -->> ObjViewer: Vertices and Faces
    ObjViewer ->> ObjViewer: display()
    ObjViewer ->> OpenGL: Render()

结尾

本文展示了如何使用 Java 创建一个简单的 OBJ 文件查看器。通过理解 OBJ 文件格式和 Java 3D 的渲染原理,您可以进一步扩展该程序,例如添加更多的用户交互功能或者支持更复杂的对象。希望本文能帮助您在三维图形学的学习之路上迈出坚实的一步!