JOGL - 3D 三角形

在上一章中,我们已经了解了如何绘制 3D 形状,本章将教您如何绘制 3D 三角形并旋转它。

下面给出了绘制 3D 三角形并旋转它的程序。

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import com.jogamp.opengl.util.FPSAnimator;

public class Triangle3d implements GLEventListener {

   private GLU glu = new GLU();
   private float rtri = 0.0f;
      
   @Override
   public void display(GLAutoDrawable drawable) {
      final GL2 gl = drawable.getGL().getGL2();

        // 清除屏幕和深度缓冲区
        gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );
        gl.glLoadIdentity(); // 重置视图
        gl.glTranslatef( -0.5f, 0.0f, -6.0f ); // 移动三角形
        gl.glRotatef( rtri, 0.0f, 1.0f, 0.0f );
        gl.glBegin( GL2.GL_TRIANGLES );
        
        // 在所有维度上绘制三角形
        // 正面
        gl.glColor3f( 1.0f, 0.0f, 0.0f ); // 红色
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 三角形顶部(正面)
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f ); // 绿色
        gl.glVertex3f( -1.0f, -1.0f, 1.0f ); // 三角形左侧(正面)
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f ); // 蓝色
        gl.glVertex3f( 1.0f, -1.0f, 1.0f ); // 三角形右侧(正面)
        
        // 右侧
        gl.glColor3f( 1.0f, 0.0f, 0.0f ); // 红色
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 三角形顶部(右)
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f ); // 蓝色
        gl.glVertex3f( 1.0f, -1.0f, 1.0f ); // 三角形左侧(右)
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f ); // 绿色
        gl.glVertex3f( 1.0f, -1.0f, -1.0f ); // 三角形右侧(右)
        
        // 左
        gl.glColor3f( 1.0f, 0.0f, 0.0f ); // 红色
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 三角形顶部(后面)
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f ); // 绿色
        gl.glVertex3f( 1.0f, -1.0f, -1.0f ); // 三角形左侧(后面)
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f ); // 蓝色
        gl.glVertex3f( -1.0f, -1.0f, -1.0f ); // 三角形右侧(后面)
        
        //左侧
        gl.glColor3f( 0.0f, 1.0f, 0.0f ); // 红色
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 三角形顶部(左侧)
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f ); // 蓝色
        gl.glVertex3f( -1.0f, -1.0f, -1.0f ); // 三角形左侧(左)
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f ); // 绿色
        gl.glVertex3f( -1.0f, -1.0f, 1.0f ); // 三角形右侧(左)
        
        gl.glEnd(); // 完成绘制 3d 三角形(金字塔)
        gl.glFlush();
        rtri += 0.2f;
   }
   
   @Override
   public void dispose( GLAutoDrawable drawable ) {
      //方法主体
   }
   
   @Override
   public void init( GLAutoDrawable drawable ) {
      //方法主体
   }
   
   @Override
   public void reshape( GLAutoDrawable drawable, int x, int y, int width, int height ) {
	
      // TODO 自动生成的方法存根
      final GL2 gl = drawable.getGL().getGL2();
      if(height lt;=;)
         height = 1;
			
      final float h = ( float ) width / ( float ) height;
      gl.glViewport( 0, 0, width, height );
      gl.glMatrixMode( GL2.GL_PROJECTION );
      gl.glLoadIdentity();
		
      glu.gluPerspective( 45.0f, h, 1.0, 20.0 );
      gl.glMatrixMode( GL2.GL_MODELVIEW );
      gl.glLoadIdentity();
   }
   
   public static void main( String[] args ) {
   
        // TODO 自动生成的方法存根
        final GLProfile profile = GLProfile.get( GLProfile.GL2 );
        GLCapabilities capabilities = new GLCapabilities( profile );
        
        // 画布
        final GLCanvas glcanvas = new GLCanvas( capabilities );
        Triangle3d triple = new Triangle3d();
        
        glcanvas.addGLEventListener( triple );
        glcanvas.setSize( 400, 400 );
        
        final JFrame frame = new JFrame ( "3d Triangle (shallow)" );
        
        frame.getContentPane().add( glcanvas );
        frame.setSize( frame.getContentPane().getPreferredSize() );
        frame.setVisible( true );
        
        final FPSAnimator animator = new FPSAnimator(glcanvas,300,true);
        animator.start();
   }
	
}

编译并执行上述程序时,会生成以下输出。这里,您有旋转 3D 三角形的快照。由于此程序不包含深度测试,因此三角形是空心的。

Triangle 3D

要使三角形成为实心的,您需要使用 glEnable(GL_DEPTH_TEST) 启用深度测试。启用深度缓冲区会给您一个空白的 屏幕。可以使用 glClear(GL_COLOR_BUFFERBIT | GL_DEPTH_BUFFER_BIT) 方法清除颜色来清除它。要在 init() 方法或 glDisplay() 方法中启用深度测试,请编写以下代码 −

public void init(GLAutoDrawable drawable) {
   final GL2 gl = drawable.getGL().getGL2();
	
   gl.glShadeModel(GL2.GL_SMOOTH);
   gl.glClearColor(0f, 0f, 0f, 0f);
   gl.glClearDepth(1.0f);
   gl.glEnable(GL2.GL_DEPTH_TEST);
   gl.glDepthFunc(GL2.GL_LEQUAL);
   gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
 }

下面给出的是使用深度测试绘制 3D 三角形的程序。

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import com.jogamp.opengl.util.FPSAnimator;

public class Triangledepthtest implements GLEventListener {

   private GLU glu = new GLU();
   private float rtri = 0.0f; 
	
   @Override
   public void display( GLAutoDrawable drawable ) {
	
        final GL2 gl = drawable.getGL().getGL2();
        
        gl.glShadeModel( GL2.GL_SMOOTH );
        gl.glClearColor( 0f, 0f, 0f, 0f );
        gl.glClearDepth( 1.0f );
        gl.glEnable( GL2.GL_DEPTH_TEST );
        gl.glDepthFunc( GL2.GL_LEQUAL );
        gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
        
        // 清除屏幕和深度缓冲区
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity(); // 重置视图
        gl.glTranslatef( -0.5f,0.0f,-6.0f ); // 移动三角形
        gl.glRotatef( rtri, 0.0f, 1.0f, 0.0f );
        gl.glBegin( GL2.GL_TRIANGLES );
        
        //在所有维度上绘制三角形
        //正面
        gl.glColor3f( 1.0f, 0.0f, 0.0f ); // 红色
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 顶部
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f ); // 绿色
        gl.glVertex3f( -1.0f, -1.0f, 1.0f ); // 左
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f ); // 蓝色
        gl.glVertex3f( 1.0f, -1.0f, 1.0f ); // 右)
        
        //右
        gl.glColor3f( 1.0f, 0.0f, 0.0f );
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 上
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f );
        gl.glVertex3f( 1.0f, -1.0f, 1.0f ); // 左
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f );
        gl.glVertex3f( 1.0f, -1.0f, -1.0f ); // 右
        
        //左
        gl.glColor3f( 1.0f, 0.0f, 0.0f );
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 上
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f );
        gl.glVertex3f( 1.0f, -1.0f, -1.0f ); // 左
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f );
        gl.glVertex3f( -1.0f, -1.0f, -1.0f ); // 右
        
        //上
        gl.glColor3f( 0.0f, 1.0f, 0.0f );
        gl.glVertex3f( 1.0f, 2.0f, 0.0f ); // 顶部
        
        gl.glColor3f( 0.0f, 0.0f, 1.0f );
        gl.glVertex3f( -1.0f, -1.0f, -1.0f ); // 左侧
        
        gl.glColor3f( 0.0f, 1.0f, 0.0f );
        gl.glVertex3f( -1.0f, -1.0f, 1.0f ); // 右侧
        
        gl.glEnd(); // 完成绘制 3d 三角形(金字塔)
        
        gl.glFlush();
        rtri += 0.2f;
   }
      
   @Override
   public void dispose( GLAutoDrawable drawable ) {
   }
   
   @Override
   public void init( GLAutoDrawable drawable ) {
	
      final GL2 gl = drawable.getGL().getGL2();
		
      gl.glShadeModel( GL2.GL_SMOOTH );
      gl.glClearColor( 0f, 0f, 0f, 0f );
      gl.glClearDepth( 1.0f );
      gl.glEnable( GL2.GL_DEPTH_TEST );
      gl.glDepthFunc( GL2.GL_LEQUAL );
      gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST );
   }
   
   @Override
   public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height ) {
	
      // TODO 自动生成的方法存根
      final GL2 gl = drawable.getGL().getGL2();
      if( height <= 0 ) 
         height = 1;
			
      final float h = ( float ) width / ( float ) height;
      gl.glViewport( 0, 0, width, height );
      gl.glMatrixMode( GL2.GL_PROJECTION );
      gl.glLoadIdentity();
		
      glu.gluPerspective( 45.0f, h, 1.0, 20.0 );
      gl.glMatrixMode( GL2.GL_MODELVIEW );
      gl.glLoadIdentity();
   }
      
   public static void main( String[] args ) {
	
        // TODO 自动生成的方法存根
        final GLProfile profile = GLProfile.get( GLProfile.GL2 );
        GLCapabilities capabilities = new GLCapabilities( profile );
        
        // 画布
        final GLCanvas glcanvas = new GLCanvas( capabilities );
        Triangledepthtest tripledepthtest = new Triangledepthtest();
        
        glcanvas.addGLEventListener( tripledepthtest );
        glcanvas.setSize( 400, 400 );
        
        final JFrame frame = new JFrame ( "3d Triangle (solid)" );
        frame.getContentPane().add(glcanvas);
        frame.setSize( frame.getContentPane().getPreferredSize() );
        frame.setVisible( true );
        final FPSAnimator animator = new FPSAnimator( glcanvas, 300,true);
        
        animator.start();
   }
	
}

编译并执行上述程序时,将生成以下输出。

在这里,您可以看到旋转的 3D 三角形的快照。由于此程序包含深度测试代码,因此三角形是实心的。

Triangle Depth Test