Java lwjgl 围绕其中心旋转模型

Java lwjgl rotating a model around its center

我一直在制作一个轻量级的项目 java 图形库,我在其中加载了一个模型并用每个三角形的颜色渲染它。我的下一步是围绕其中心旋转模型。通过阅读文章和源代码,我对我需要做什么有一个大致的了解,但我并不完全理解 glTranslatef() 方法。以我的理解你想要

glPushMatrix()

glTranslatef(0,0,0);

glRotatef(旋转值);

glTranslatef(原始坐标);

渲染模型

然后是 glPopMatrix();

我的主要问题是我在我的 glVertex() 方法调用中手动进行数学运算而不是翻译它们,我相信这使得从 0,0,0 返回到原始点的翻译变得困难。感谢您的时间和帮助。

package render;

import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glRotatef;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glTranslatef;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glNormal3f;
import static org.lwjgl.opengl.GL11.glVertex3f;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.lwjgl.util.vector.Vector3f;

import models.Faces;
import models.Material;
import models.Model;
import models.OBJLoader;

public class OBJRender {
    Material material = new Material();
    private int count;
    Model m = null;
    Vector3f rgb = null;
    Vector3f v1 = new Vector3f();
    Vector3f v2 = new Vector3f();
    Vector3f v3 = new Vector3f();

public void load_model(String model_name){ //loads model data
    try{
        m = OBJLoader.loadModel(new File("res/obj/"+model_name+".obj"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void model_render(Vector3f coords, Vector3f degrees){
    count = 0; //count of triangle for coloring
    model_rotate(coords, degrees); //coords is the obj coords degrees is rotation coords
    glBegin(GL_TRIANGLES);
    for (Faces face : m.faces) {
        String mat = OBJLoader.getMaterialList().get(count);
        rgb = material.getMaterial(mat);
        glColor3f(rgb.x, rgb.y, rgb.z);
        Vector3f n1 = m.normals.get((int) face.normals.x - 1);        
        v1 = m.vertices.get((int) face.Vertex.x - 1);
        Vector3f n2 = m.normals.get((int) face.normals.y - 1);            
        v2 = m.vertices.get((int) face.Vertex.y - 1);           
        Vector3f n3 = m.normals.get((int) face.normals.z - 1);
        v3 = m.vertices.get((int) face.Vertex.z - 1);
        glNormal3f(n1.x, n1.y, n1.z);
        glVertex3f(coords.x-v1.x, coords.y+v1.y+80, coords.z-v1.z);
        glNormal3f(n2.x, n2.y, n2.z);
        glVertex3f(coords.x-v2.x, coords.y+v2.y+80, coords.z-v2.z);
        glNormal3f(n3.x, n3.y, n3.z);
        glVertex3f(coords.x-v3.x, coords.y+v3.y+80, coords.z-v3.z);
        count++;
    }
    glClearColor(rgb.x,rgb.y,rgb.z,0);
    glEnd();
    glPopMatrix();
}

public void model_rotate(Vector3f coords, Vector3f degrees){
    glPushMatrix();
    glTranslatef(-0, -0, -0);
    glRotatef(degrees.y,0,1,0);
    }
}

虽然还不完全清楚实际问题是什么(除了"What do I have to change so that the code does what I want"),尝试回答:

当您从 OBJ 文件加载对象时,您通常 不会 修改顶点坐标。您只需在从文件中读取它们时使用它们。当您想要将对象作为一个整体进行变换时,您可以使用 OpenGL 矩阵运算 - 在这种情况下,只有 glTranslateglRotate.

为了围绕其中心旋转物体,您首先必须知道这个中心。有疑问的,可以从顶点或者物体的边界框来计算。

然后,为了围绕其中心旋转对象,您必须

  • 移动对象,使用glTranslate,使对象的中心位于原点
  • 旋转对象,使用glRotate
  • 使用glTranslate
  • 将对象移回原来的位置

请注意,这些操作应用于对象的顺序与它们在源代码中出现的顺序相反。所以调用顺序将是

glTranslatef( center.x,  center.y,  center.z);
glRotatef(rotationAngleDeg,0,0,1);
glTranslatef(-center.x, -center.y, -center.z);

这里是一个MCVE,它使用一个由4个顶点组成的简单矩形作为对象,并绕其中心旋转。您可以看到,在 glVertex 调用中,它只是按原样使用顶点(在您的例子中,它们将从 OBJ 文件中读取)。整个转换是在 GL_MODELVIEW 矩阵上完成的,使用上面提到的命令。

import static org.lwjgl.opengl.GL11.*;
import java.awt.Canvas;
import javax.swing.JFrame;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;

public class RotateAboutCenter
{
    public static void main(String[] args)
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500,500);
        f.setLocationRelativeTo(null);
        Canvas canvas = new Canvas();
        f.add(canvas);
        try
        {
            Display.setParent(canvas);
            f.setVisible(true);
            Display.create();
        }
        catch (LWJGLException e)
        {
            e.printStackTrace();
        }
        while (!Display.isCloseRequested())
        {
            draw();
            Display.update();
            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException e)
            {
                Thread.currentThread().interrupt();
            }
            rotationAngleDeg += 1.0f;
        }
        Display.destroy();
    }

    private static float rotationAngleDeg = 0;

    // The vertices of the model
    private static Vector3f v0 = new Vector3f(10,10,0);
    private static Vector3f v1 = new Vector3f(20,10,0);
    private static Vector3f v2 = new Vector3f(20,20,0);
    private static Vector3f v3 = new Vector3f(10,20,0);

    // The center of the model
    private static Vector3f center = new Vector3f(15,15,0);

    private static void draw() 
    {
        // Basic setup of view etc.
        int w = Display.getWidth();
        int h = Display.getHeight();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        GLU.gluPerspective(45, (float) w / (float) h, 0.1f, 1000);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        GLU.gluLookAt(0,0,70,0,0,0,0,1,0);

        glPushMatrix();

        // ===================================================================
        // Now, do the model transform. Remember that this has to 
        // be read "backwards":

        // THIRD STEP: Move the model back so that its center is
        // again at its original position
        glTranslatef(center.x, center.y, center.z);

        // SECOND STEP: Rotate the model about the origin (which now
        // is the center of the model)
        glRotatef(rotationAngleDeg,0,0,1);

        // FIRST STEP: Translate the model so that its center is at the origin
        glTranslatef(-center.x, -center.y, -center.z);

        // ===================================================================

        // Draw the object, with its original coordinates. All the
        // transforms are now contained in the MODELVIEW matrix.
        glBegin(GL_TRIANGLES);
        glColor3f(1,0,0);
        glVertex3f(v0.x, v0.y, v0.z);
        glVertex3f(v1.x, v1.y, v1.z);
        glVertex3f(v3.x, v3.y, v3.z);
        glVertex3f(v1.x, v1.y, v1.z);
        glVertex3f(v2.x, v2.y, v2.z);
        glVertex3f(v3.x, v3.y, v3.z);

        glEnd();
        glPopMatrix();
    }
}