Jogl - 渲染环形齿轮 - 未正确绘制的表面

时间:2014-10-05 16:20:08

标签: java opengl rendering jogl

我正在尝试在Java Open GL(jogl)中渲染一个环形齿轮。我知道如何使用Jogl齿轮演示(http://jogamp.org/jogl-demos/www/)渲染一个直齿轮。这是通过我班上的“spurGear”方法完成的。

现在我想用几乎相同的代码渲染一个环形齿轮(“ringGear”方法)。不同的是,尖端和根直径交换,内孔直径与外圈直径交换。但渲染的代码是一样的。

表面似乎都在那里,但是某些东西与照明/绘画混合在一起。每个曲面都是从错误的方向绘制的(与“spurGear”中的方向相同)。

你能帮我解决如何正确渲染环形齿轮的问题吗?

为了显示正齿轮,在“spurGear(...)”中使用“渲染”方法注释。您可以使用鼠标左键旋转并使用鼠标中键进行缩放。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.awt.GLJPanel;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.jogamp.opengl.util.FPSAnimator;

public class StackOverflowExample implements GLEventListener, MouseListener, MouseMotionListener, MouseWheelListener {

    float fZoom = 1.0f;

    private float fViewRotX = 20.0f;
    private float fViewRotY = 30.0f;
    private final float fViewRotZ = 0.0f;

    private float fViewTransX = 0.0f;
    private float fViewTransY = 0.0f;
    private final float fViewTransZ = 0.0f;

    private int iPrevMouseX;
    private int iPrevMouseY;

    private final GLCanvas canvas;

    /**************************************************************
     * main
     *************************************************************/

    public static void main(String[] args) {
        StackOverflowExample cogl = new StackOverflowExample();

        JFrame frame = new JFrame("Demo");
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(cogl.getCanvas());

        frame.add(panel);
        frame.setSize(800, 600);

        frame.getContentPane().add(cogl.getCanvas());

        final FPSAnimator animator = new FPSAnimator(cogl.getCanvas(),60);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                // Run this on another thread than the AWT event queue to
                // make sure the call to Animator.stop() completes before
                // exiting
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        animator.stop();
                        System.exit(0);
                    }
                }).start();
            }
        });

        frame.setVisible(true);
        animator.start();

    }


    /**************************************************************
     * constructor
     *************************************************************/

    public StackOverflowExample() {
        // Starte App
        canvas = new GLCanvas();
        canvas.addGLEventListener(this);
        canvas.addMouseListener(this);
        canvas.addMouseWheelListener(this);
        canvas.addMouseMotionListener(this);
    }

    /**************************************************************
     * OGL methods
     *************************************************************/

    @Override
    public void display(GLAutoDrawable drawable) {

        GL2 gl = drawable.getGL().getGL2();

        // Special handling for the case where the GLJPanel is translucent
        // and wants to be composited with other Java 2D content
        if ((drawable instanceof GLJPanel) && !((GLJPanel) drawable).isOpaque() && ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
            gl.glClear(GL2.GL_DEPTH_BUFFER_BIT);
        } else {
            gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        }

        // Rotate/Translate/Zoom the entire assembly
        gl.glPushMatrix();

        gl.glRotatef(fViewRotX, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(fViewRotY, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(fViewRotZ, 0.0f, 0.0f, 1.0f);
        gl.glTranslatef(fViewTransX, fViewTransY, fViewTransZ);
        gl.glScaled(fZoom, fZoom, fZoom);

        render(gl);

        gl.glPopMatrix();
    }

    public void render(GL2 gl) {
        ringGear(gl, 5f, 4f, 3f, 1f, 25);
        //spurGear(gl, 2f, 3f, 4f, 1f, 25);
    }

    @Override
    public void dispose(GLAutoDrawable drawable) {
        // TODO Auto-generated method stub

    }

    @Override
    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();

        // lighting
        gl.glEnable(GL2.GL_CULL_FACE);
        gl.glEnable(GL2.GL_LIGHTING);
        gl.glEnable(GL2.GL_LIGHT0);
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glEnable(GL2.GL_NORMALIZE);
    }

    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        GL2 gl = drawable.getGL().getGL2();

        float h = (float) height / (float) width;

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -40.0f);

    }

    /**************************************************************
     * mouse listeners
     *************************************************************/

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        int notches = e.getWheelRotation();
        if (notches < 0) {
            fZoom *= 1.1;
        } else {
            fZoom *= 0.9;
        }

    }

    @Override
    public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        Dimension size = e.getComponent().getSize();

        // Linke MT -> rotieren
        if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
            float thetaY = 360f * ((float) (x - iPrevMouseX) / (float) size.width);
            float thetaX = 360f * ((float) (iPrevMouseY - y) / (float) size.height);

            // Vorgänger setzen
            iPrevMouseX = x;
            iPrevMouseY = y;

            // Rotation anwenden
            fViewRotX -= thetaX;
            fViewRotY += thetaY;
        }

        // Rechte MT -> bewegen
        if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
            float thetaX = 2f * ((float) (x - iPrevMouseX) / (float) size.width);
            float thetaY = 2f * ((float) (iPrevMouseY - y) / (float) size.height);
            // Vorgänger setzen

            iPrevMouseX = x;
            iPrevMouseY = y;

            fViewTransX += thetaX;
            fViewTransY += thetaY;
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent e) {
        iPrevMouseX = e.getX();
        iPrevMouseY = e.getY();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    /**************************************************************
     * getters
     *************************************************************/

    public GLCanvas getCanvas() {
        return canvas;
    }

    /**************************************************************
     * render spur gear
     *************************************************************/

    public static void spurGear(GL2 gl, float innerDiameter, float rootDiameter, float tipDiameter, float width, int teeth) {
        int i;
        float rInner, rRoot, rTip;
        float angle, quarterToothAngle;
        float u, v, len;

        rInner = innerDiameter / 2;
        rRoot = rootDiameter / 2;
        rTip = tipDiameter / 2;

        quarterToothAngle = 2.0f * (float) Math.PI / teeth / 4.0f;

        gl.glShadeModel(GL2.GL_FLAT);

        gl.glNormal3f(0.0f, 0.0f, 1.0f);

        // draw front face
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i <= teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rInner * (float) Math.cos(angle), rInner * (float) Math.sin(angle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), width * 0.5f);
            if (i < teeth) {
                gl.glVertex3f(rInner * (float) Math.cos(angle), rInner * (float) Math.sin(angle), width * 0.5f);
                gl.glVertex3f(rRoot * (float) Math.cos(angle + 3.0f * quarterToothAngle), rRoot * (float) Math.sin(angle + 3.0f * quarterToothAngle), width * 0.5f);
            }
        }
        gl.glEnd();

        // draw front sides of teeth
        gl.glBegin(GL2.GL_QUADS);
        for (i = 0; i < teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2.0f * quarterToothAngle), rTip * (float) Math.sin(angle + 2.0f * quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3.0f * quarterToothAngle), rRoot * (float) Math.sin(angle + 3.0f * quarterToothAngle), width * 0.5f);
        }
        gl.glEnd();

        // draw back face
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i <= teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), -width * 0.5f);
            gl.glVertex3f(rInner * (float) Math.cos(angle), rInner * (float) Math.sin(angle), -width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rInner * (float) Math.cos(angle), rInner * (float) Math.sin(angle), -width * 0.5f);
        }
        gl.glEnd();

        // draw back sides of teeth
        gl.glBegin(GL2.GL_QUADS);
        for (i = 0; i < teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2 * quarterToothAngle), rTip * (float) Math.sin(angle + 2 * quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), -width * 0.5f);
        }
        gl.glEnd();

        // draw outward faces of teeth
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i < teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), -width * 0.5f);
            u = rTip * (float) Math.cos(angle + quarterToothAngle) - rRoot * (float) Math.cos(angle);
            v = rTip * (float) Math.sin(angle + quarterToothAngle) - rRoot * (float) Math.sin(angle);
            len = (float) Math.sqrt(u * u + v * v);
            u /= len;
            v /= len;
            gl.glNormal3f(v, -u, 0.0f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), -width * 0.5f);
            gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2 * quarterToothAngle), rTip * (float) Math.sin(angle + 2 * quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2 * quarterToothAngle), rTip * (float) Math.sin(angle + 2 * quarterToothAngle), -width * 0.5f);
            u = rRoot * (float) Math.cos(angle + 3 * quarterToothAngle) - rTip * (float) Math.cos(angle + 2 * quarterToothAngle);
            v = rRoot * (float) Math.sin(angle + 3 * quarterToothAngle) - rTip * (float) Math.sin(angle + 2 * quarterToothAngle);
            gl.glNormal3f(v, -u, 0.0f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), -width * 0.5f);
            gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
        }
        gl.glVertex3f(rRoot * (float) Math.cos(0), rRoot * (float) Math.sin(0), width * 0.5f);
        gl.glVertex3f(rRoot * (float) Math.cos(0), rRoot * (float) Math.sin(0), -width * 0.5f);
        gl.glEnd();

        gl.glShadeModel(GL2.GL_SMOOTH);

        // draw inside radius cylinder
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i <= teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
            gl.glVertex3f(rInner * (float) Math.cos(angle), rInner * (float) Math.sin(angle), -width * 0.5f);
            gl.glVertex3f(rInner * (float) Math.cos(angle), rInner * (float) Math.sin(angle), width * 0.5f);
        }
        gl.glEnd();
    }

    /**************************************************************
     * render ring gear
     *************************************************************/

    public static void ringGear(GL2 gl, float outerDiameter, float rootDiameter, float tipDiameter, float width, int teeth) {
        int i;
        float rOuter, rRoot, rTip;
        float angle, quarterToothAngle;
        float u, v, len;

        rOuter = outerDiameter / 2;
        rRoot = rootDiameter / 2;
        rTip = tipDiameter / 2;

        quarterToothAngle = 2.0f * (float) Math.PI / teeth / 4.0f;

        gl.glShadeModel(GL2.GL_FLAT);
        gl.glNormal3f(1.0f, 0.0f, 0.0f);

        // draw front face
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i <= teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rOuter * (float) Math.cos(angle), rOuter * (float) Math.sin(angle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), width * 0.5f);
            if (i < teeth) {
                gl.glVertex3f(rOuter * (float) Math.cos(angle), rOuter * (float) Math.sin(angle), width * 0.5f);
                gl.glVertex3f(rRoot * (float) Math.cos(angle + 3.0f * quarterToothAngle), rRoot * (float) Math.sin(angle + 3.0f * quarterToothAngle), width * 0.5f);
            }
        }
        gl.glEnd();

        // draw front sides of teeth
        gl.glBegin(GL2.GL_QUADS);
        for (i = 0; i < teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2.0f * quarterToothAngle), rTip * (float) Math.sin(angle + 2.0f * quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3.0f * quarterToothAngle), rRoot * (float) Math.sin(angle + 3.0f * quarterToothAngle), width * 0.5f);
        }
        gl.glEnd();

        // draw back face
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i <= teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), -width * 0.5f);
            gl.glVertex3f(rOuter * (float) Math.cos(angle), rOuter * (float) Math.sin(angle), -width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rOuter * (float) Math.cos(angle), rOuter * (float) Math.sin(angle), -width * 0.5f);
        }
        gl.glEnd();

        // draw back sides of teeth
        gl.glBegin(GL2.GL_QUADS);
        for (i = 0; i < teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2 * quarterToothAngle), rTip * (float) Math.sin(angle + 2 * quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), -width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), -width * 0.5f);
        }
        gl.glEnd();

        // draw outward faces of teeth
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i < teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle), rRoot * (float) Math.sin(angle), -width * 0.5f);
            u = rTip * (float) Math.cos(angle + quarterToothAngle) - rRoot * (float) Math.cos(angle);
            v = rTip * (float) Math.sin(angle + quarterToothAngle) - rRoot * (float) Math.sin(angle);
            len = (float) Math.sqrt(u * u + v * v);
            u /= len;
            v /= len;
            gl.glNormal3f(v, -u, 0.0f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + quarterToothAngle), rTip * (float) Math.sin(angle + quarterToothAngle), -width * 0.5f);
            gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2 * quarterToothAngle), rTip * (float) Math.sin(angle + 2 * quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rTip * (float) Math.cos(angle + 2 * quarterToothAngle), rTip * (float) Math.sin(angle + 2 * quarterToothAngle), -width * 0.5f);
            u = rRoot * (float) Math.cos(angle + 3 * quarterToothAngle) - rTip * (float) Math.cos(angle + 2 * quarterToothAngle);
            v = rRoot * (float) Math.sin(angle + 3 * quarterToothAngle) - rTip * (float) Math.sin(angle + 2 * quarterToothAngle);
            gl.glNormal3f(v, -u, 0.0f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), width * 0.5f);
            gl.glVertex3f(rRoot * (float) Math.cos(angle + 3 * quarterToothAngle), rRoot * (float) Math.sin(angle + 3 * quarterToothAngle), -width * 0.5f);
            gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
        }
        gl.glVertex3f(rRoot * (float) Math.cos(0), rRoot * (float) Math.sin(0), width * 0.5f);
        gl.glVertex3f(rRoot * (float) Math.cos(0), rRoot * (float) Math.sin(0), -width * 0.5f);
        gl.glEnd();

        gl.glShadeModel(GL2.GL_SMOOTH);

        // draw inside radius cylinder
        gl.glBegin(GL2.GL_QUAD_STRIP);
        for (i = 0; i <= teeth; i++) {
            angle = i * 2.0f * (float) Math.PI / teeth;
            gl.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
            gl.glVertex3f(rOuter * (float) Math.cos(angle), rOuter * (float) Math.sin(angle), -width * 0.5f);
            gl.glVertex3f(rOuter * (float) Math.cos(angle), rOuter * (float) Math.sin(angle), width * 0.5f);
        }
        gl.glEnd();
    }
}

0 个答案:

没有答案