我正在尝试在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();
}
}