如标题中所述:我想创建一个10齿的3D齿轮,该齿轮绕其中心旋转(就像齿轮一样)。齿轮具有方齿,为简单起见,齿之间具有平整的侧面-此齿轮上没有弯曲。

嵌齿轮的哪一侧看起来像的可视化。请注意,角度并非100%完美。

java - 在OpenGL中绘制绕Y轴旋转的齿轮-LMLPHP

如上图所示,每个嵌齿轮齿必须是8面多边形,而齿之间的每个单面都必须是4面多边形。但是,现在,牙齿图执行以下操作:

  • 尽管未进行初始旋转,但应将面向照相机的侧齿旋转到地板上。
  • 尽管缩放和顶点创建是通过统一的数字完成的,但牙齿的宽度是其长的两倍。(它由s在x,y,z方向上缩放,并使用00.5作为顶点坐标)。

  • 完全可重现的示例:
    import java.awt.Dimension;
    
    import javax.swing.JFrame;
    
    import com.jogamp.opengl.GL;
    import com.jogamp.opengl.GL2;
    import com.jogamp.opengl.GLAutoDrawable;
    import com.jogamp.opengl.GLEventListener;
    import com.jogamp.opengl.awt.GLJPanel;
    import com.jogamp.opengl.glu.GLU;
    import com.jogamp.opengl.util.FPSAnimator;
    
    public class SpinCog3D implements GLEventListener {
    
        JFrame jf;
        GLJPanel gljpanel;
        Dimension dim = new Dimension(800, 600);
        FPSAnimator animator;
    
        float rotation;
        float speed;
    
        // set up the OpenGL Panel within a JFrame
        public SpinCog3D() {
            jf = new JFrame();
            gljpanel = new GLJPanel();
            gljpanel.addGLEventListener(this);
            gljpanel.requestFocusInWindow();
            jf.getContentPane().add(gljpanel);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.setVisible(true);
            jf.setPreferredSize(dim);
            jf.pack();
            animator = new FPSAnimator(gljpanel, 20);
            rotation = 0.0f;
            speed = 0.1f;
            animator.start();
        }
    
        public static void main(String[] args) {
            new SpinCog3D();
        }
    
        public void init(GLAutoDrawable dr) {
            GL2 gl2 = dr.getGL().getGL2();
            GLU glu = new GLU();
            gl2.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
            gl2.glEnable(GL2.GL_DEPTH_TEST);
    
            gl2.glMatrixMode(GL2.GL_PROJECTION);
            gl2.glLoadIdentity();
            glu.gluPerspective(60.0, 1.0, 100.0, 800.0);
    
        }
    
        public void display(GLAutoDrawable dr) {
    
            GL2 gl2 = dr.getGL().getGL2();
            GLU glu = new GLU();
    
            gl2.glMatrixMode(GL2.GL_MODELVIEW);
            gl2.glLoadIdentity();
            glu.gluLookAt(0.0, 200.0, 500.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    
            gl2.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
    
            // Draw 1 Cog Tooth + 1 Side
            drawTooth(gl2, 100.0, 1.0f, 0.0f, 0.0f, 0.0, 0.0, 1.0, 0.0, 0);
            drawSide(gl2, 100.0, 0.0f, 1.0f, 0.0f, 0.0, 0.0, 1.0, 0.0, 10);
    
            // Draw Floor
            sideRotatedColorScaledFloor(gl2, 300.0, 0.0f, 0.0f, 0.0f, 90.0, 1.0, 0.0, 0.0, 0.0);
    
            gl2.glFlush();
            rotation += speed;
            if (rotation > 360.9f)
                rotation = 0.0f;
        }
    
        // draw a single side with a set color and orientation
        private void drawTooth(GL2 gl2, double s, float r, float g, float b, double a, double ax, double ay,
                                            double az, double zoffset) {
            gl2.glPushMatrix();
            gl2.glRotated(a, ax, ay, az);
            gl2.glColor3f(r, g, b);
            gl2.glTranslated(0.0, 0.0, zoffset);
            gl2.glScaled(s, s, s);
    
            tooth(gl2);
            gl2.glPopMatrix();
        }
    
        private void drawSide(GL2 gl2, double s, float r, float g, float b, double a, double ax, double ay,
                               double az, double zoffset) {
            gl2.glPushMatrix();
            gl2.glRotated(a, ax, ay, az);
            gl2.glColor3f(r, g, b);
            gl2.glTranslated(0.0, 0.0, zoffset);
            gl2.glScaled(s, s, s);
    
            side(gl2);
            gl2.glPopMatrix();
        }
    
        private void sideRotatedColorScaledFloor(GL2 gl2, double s, float r, float g, float b, double a, double ax, double ay,
                                            double az, double zoffset) {
            gl2.glPushMatrix();
            gl2.glRotated(a, ax, ay, az);
            gl2.glColor3f(r, g, b);
            gl2.glTranslated(0.0, 0.0, zoffset);
            gl2.glScaled(s, s, s);
    
            side(gl2);
            gl2.glPopMatrix();
        }
    
        private void tooth(GL2 gl2) {
            gl2.glBegin(GL2.GL_POLYGON);
            gl2.glVertex3d(-0.5, -0.5, 0.0);
            gl2.glVertex3d(-0.5, 0.5, 0.0);
            gl2.glVertex3d(0.5, 0.5, 0.0);
            gl2.glVertex3d(0.5, -0.5, 0.0);
            gl2.glVertex3d(-0.5, -0.5, 0.5);
            gl2.glVertex3d(-0.5, 0.5, 0.5);
            gl2.glVertex3d(0.5, 0.5, 0.5);
            gl2.glVertex3d(0.5, -0.5, 0.5);
            gl2.glEnd();
        }
    
        private void side(GL2 gl2) {
            gl2.glBegin(GL2.GL_POLYGON);
            gl2.glVertex3d(-0.5, -0.5, 0.0);
            gl2.glVertex3d(-0.5, 0.5, 0.0);
            gl2.glVertex3d(0.5, 0.5, 0.0);
            gl2.glVertex3d(0.5, -0.5, 0.0);
            gl2.glEnd();
        }
    }
    

    是的,我知道glBegin()glEnd()自从一开始就被弃用,但这不是重点。如何使我的牙齿正确刷牙并使其与侧面正确对齐?

    最佳答案

    牙齿画做各种奇怪的事情...

    这不是很好的问题描述。我敢打赌,当您使用硬编码形状而不对齿轮的实际尺寸进行任何校正时,您的网格有很多缝隙和重叠。就像必须有多大的牙齿才能适合它们的n才能完全覆盖整个圆圈...

    如何利用参数圆方程呢?

    我认为那可以摆脱矩阵混乱,甚至更简单。

    因此,我将齿轮简单地划分为三角形切片,每个切片中的边缘点很少。因此,将它们与QUAD连接起来,并将其放入完成所有切片的for循环中。

    我不是用JAVA编写代码,而是这里的一个使用旧GL api的小型C++示例,没有花哨的C++东西,因此您应该可以轻松移植此代码:

    java - 在OpenGL中绘制绕Y轴旋转的齿轮-LMLPHP

    void glCog(float r0,float r1,float r2,float w,int n)    // shaft/inner/outer radiuses, width, tooths
        {
        int i;
        float a,da,x,y,c,s;
        float p[6][3],q[6][3];  // slice points
        // set z for slice points
        a=-0.5*w; for (i=0;i<3;i++){ p[i][2]=a; q[i][2]=a; }
        a=+0.5*w; for (i=3;i<6;i++){ p[i][2]=a; q[i][2]=a; }
        // init first slice
        q[0][0]= r0; q[5][0]= r0;
        q[0][1]=0.0; q[5][1]=0.0;
        q[1][0]= r1; q[4][0]= r1;
        q[1][1]=0.0; q[4][1]=0.0;
        q[2][0]= r2; q[3][0]= r2;
        q[2][1]=0.0; q[3][1]=0.0;
        // divide circle to 2*n slices
        da=2.0*M_PI/float(4*n);
        glBegin(GL_QUADS);
        for (a=0.0,i=0;i<=n;i++)
            {
            // points on circles at angle a
            c=cos(a); s=sin(a); a+=da;
            x=r0*c; y=r0*s; p[0][0]=x; p[5][0]=x;
                            p[0][1]=y; p[5][1]=y;
            x=r1*c; y=r1*s; p[1][0]=x; p[4][0]=x;
                            p[1][1]=y; p[4][1]=y;
            x=r2*c; y=r2*s; p[2][0]=x; p[3][0]=x;
                            p[2][1]=y; p[3][1]=y;
            // render tooth
            c=cos(a); s=sin(a); a+=da;
            glNormal3f(0.0,0.0,-1.0);   // -Z base
            glVertex3fv(p[0]);
            glVertex3fv(p[2]);
            glVertex3fv(q[2]);
            glVertex3fv(q[0]);
            glNormal3f(0.0,0.0,+1.0);   // +Z base
            glVertex3fv(p[3]);
            glVertex3fv(p[5]);
            glVertex3fv(q[5]);
            glVertex3fv(q[3]);
            glNormal3f(-c,-s,0.0);      // shaft circumference side
            glVertex3fv(p[5]);
            glVertex3fv(p[0]);
            glVertex3fv(q[0]);
            glVertex3fv(q[5]);
            glNormal3f(c,s,0.0);        // outter circumference side
            glVertex3fv(p[2]);
            glVertex3fv(p[3]);
            glVertex3fv(q[3]);
            glVertex3fv(q[2]);
            glNormal3f(-s,c,0.0);
            glVertex3fv(p[4]);
            glVertex3fv(p[3]);
            glVertex3fv(p[2]);
            glVertex3fv(p[1]);
            glNormal3f(s,-c,0.0);
            glVertex3fv(q[1]);
            glVertex3fv(q[2]);
            glVertex3fv(q[3]);
            glVertex3fv(q[4]);
    
            // points on circles at angle a
            c=cos(a); s=sin(a); a+=da;
            x=r0*c; y=r0*s; q[0][0]=x; q[5][0]=x;
                            q[0][1]=y; q[5][1]=y;
            x=r1*c; y=r1*s; q[1][0]=x; q[4][0]=x;
                            q[1][1]=y; q[4][1]=y;
            x=r2*c; y=r2*s; q[2][0]=x; q[3][0]=x;
                            q[2][1]=y; q[3][1]=y;
            // render gap
            c=cos(a); s=sin(a); a+=da;
            glNormal3f(0.0,0.0,-1.0);   // -Z base
            glVertex3fv(q[0]);
            glVertex3fv(q[1]);
            glVertex3fv(p[1]);
            glVertex3fv(p[0]);
            glNormal3f(0.0,0.0,+1.0);   // +Z base
            glVertex3fv(q[4]);
            glVertex3fv(q[5]);
            glVertex3fv(p[5]);
            glVertex3fv(p[4]);
            glNormal3f(-c,-s,0.0);      // shaft circumference side
            glVertex3fv(q[5]);
            glVertex3fv(q[0]);
            glVertex3fv(p[0]);
            glVertex3fv(p[5]);
            glNormal3f(c,s,0.0);        // outter circumference side
            glVertex3fv(q[1]);
            glVertex3fv(q[4]);
            glVertex3fv(p[4]);
            glVertex3fv(p[1]);
            }
        glEnd();
        }
    

    在这里预览glCog(0.1,0.5,0.6,0.1,10);:

    java - 在OpenGL中绘制绕Y轴旋转的齿轮-LMLPHP

    在这里预览glCog(0.2,0.5,0.52,0.2,50);:

    java - 在OpenGL中绘制绕Y轴旋转的齿轮-LMLPHP

    但是请注意,牙齿并非完全矩形。齿越少,误差越大。如果要使牙齿具有完全矩形的形状,则需要平移最外面的点而不是旋转(或校正计算它们的角度)

    使用翻译来解决这个问题:

    void glCog(float r0,float r1,float r2,float w,int n)    // shaft/inner/outer radiuses, width, tooths
        {
        int i,j;
        float a,da,dr,x,y,c,s;
        float p[6][3],q[6][3];  // slice points
        // divide circle to 2*n slices
        da=2.0*M_PI/float(4*n);
        dr=r2-r1;
        // set z for slice points
        a=-0.5*w; for (i=0;i<3;i++){ p[i][2]=a; q[i][2]=a; }
        a=+0.5*w; for (i=3;i<6;i++){ p[i][2]=a; q[i][2]=a; }
        // init first slice
        q[0][0]= r0; q[5][0]= r0;
        q[0][1]=0.0; q[5][1]=0.0;
        q[1][0]= r1; q[4][0]= r1;
        q[1][1]=0.0; q[4][1]=0.0;
        x=r1+dr*cos(-da); y=dr*sin(-da);
        q[2][0]=  x; q[3][0]=  x;
        q[2][1]=  y; q[3][1]=  y;
        glBegin(GL_QUADS);
        for (a=0.0,i=0;i<=n;i++)
            {
            // points on circles at angle a
            c=cos(a); s=sin(a);
            x=r0*c; y=r0*s; p[0][0]=x; p[5][0]=x;
                            p[0][1]=y; p[5][1]=y;
            x=r1*c; y=r1*s; p[1][0]=x; p[4][0]=x;
                            p[1][1]=y; p[4][1]=y;
            c=cos(a-da); s=sin(a-da); a+=da;
            x+=dr*c;y+=dr*s;p[2][0]=x; p[3][0]=x;
                            p[2][1]=y; p[3][1]=y;
            c=cos(a); s=sin(a); a+=da;
            // render tooth
            glNormal3f(0.0,0.0,-1.0);   // -Z base
            glVertex3fv(p[0]);
            glVertex3fv(p[1]);
            glVertex3fv(q[1]);
            glVertex3fv(q[0]);
            glVertex3fv(p[1]);
            glVertex3fv(p[2]);
            glVertex3fv(q[2]);
            glVertex3fv(q[1]);
            glNormal3f(0.0,0.0,+1.0);   // +Z base
            glVertex3fv(p[3]);
            glVertex3fv(p[4]);
            glVertex3fv(q[4]);
            glVertex3fv(q[3]);
            glVertex3fv(p[4]);
            glVertex3fv(p[5]);
            glVertex3fv(q[5]);
            glVertex3fv(q[4]);
            glNormal3f(-c,-s,0.0);      // shaft circumference side
            glVertex3fv(p[5]);
            glVertex3fv(p[0]);
            glVertex3fv(q[0]);
            glVertex3fv(q[5]);
            glNormal3f(c,s,0.0);        // outter circumference side
            glVertex3fv(p[2]);
            glVertex3fv(p[3]);
            glVertex3fv(q[3]);
            glVertex3fv(q[2]);
            glNormal3f(-s,c,0.0);
            glVertex3fv(p[4]);
            glVertex3fv(p[3]);
            glVertex3fv(p[2]);
            glVertex3fv(p[1]);
            glNormal3f(s,-c,0.0);
            glVertex3fv(q[1]);
            glVertex3fv(q[2]);
            glVertex3fv(q[3]);
            glVertex3fv(q[4]);
    
            // points on circles at angle a
            c=cos(a); s=sin(a);;
            x=r0*c; y=r0*s; q[0][0]=x; q[5][0]=x;
                            q[0][1]=y; q[5][1]=y;
            x=r1*c; y=r1*s; q[1][0]=x; q[4][0]=x;
                            q[1][1]=y; q[4][1]=y;
            c=cos(a+da); s=sin(a+da); a+=da;
            x+=dr*c;y+=dr*s;q[2][0]=x; q[3][0]=x;
                            q[2][1]=y; q[3][1]=y;
            c=cos(a); s=sin(a); a+=da;
            // render gap
            glNormal3f(0.0,0.0,-1.0);   // -Z base
            glVertex3fv(q[0]);
            glVertex3fv(q[1]);
            glVertex3fv(p[1]);
            glVertex3fv(p[0]);
            glNormal3f(0.0,0.0,+1.0);   // +Z base
            glVertex3fv(q[4]);
            glVertex3fv(q[5]);
            glVertex3fv(p[5]);
            glVertex3fv(p[4]);
            glNormal3f(-c,-s,0.0);      // shaft circumference side
            glVertex3fv(q[5]);
            glVertex3fv(q[0]);
            glVertex3fv(p[0]);
            glVertex3fv(p[5]);
            glNormal3f(c,s,0.0);        // outter circumference side
            glVertex3fv(q[1]);
            glVertex3fv(q[4]);
            glVertex3fv(p[4]);
            glVertex3fv(p[1]);
            }
        glEnd();
        }
    

    所以只是点p[2],q[2],p[3],q[3]稍有变化,并且必须用更多的QUADS来完成基本面以补偿...

    在这里预览glCog(0.2,0.5,0.6,0.2,10);:

    java - 在OpenGL中绘制绕Y轴旋转的齿轮-LMLPHP

    关于java - 在OpenGL中绘制绕Y轴旋转的齿轮,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57918291/

    10-09 13:47