JOGL入门例子(十四)----3D场景中,显示列表的重要作用.


 上一章我们已经尝试制作了一个3D场景,但是也发现了一个严重问题,就是CPU使用率的问题,那是因为我们在上一章的代码中,GL是负责了大部分画图工作,每刷新一帧,就重画一次,以至CPU使用率急升,虽然OPENGL的速度已经很快,在C++里尚且非常需要优化,在JAVA里,优化的工作更是不可缺少的,下面用NEHE-JOGL里的第十二章:显示列表来稍微修改一下来说明显示列表的重要作用.先看看效果图

 

在这例子里的display()函数只加上了下面代码:


每移动一下画图点,就调用   gl.glCallList(String name);     //调用保存在缓存里的物体.

 

CPU使用率始终是为00-05,最下面那个JAVA.EXE是netbeans .

 

 

用下面代码生成一个显示列表,String box可以随便定义.

box = gl.glGenLists(2);

gl.glNewList(box, GL2.GL_COMPILE);

..............................

gl.glEndList();

 

private void buildLists(GL2 gl) {
        box = gl.glGenLists(2);           // Generate 2 Different Lists
        gl.glNewList(box, GL2.GL_COMPILE);  // Start With The Box List

        gl.glBegin(GL2.GL_QUADS);
        gl.glNormal3f(0.0f, -1.0f, 0.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Face
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, 1.0f);

        gl.glNormal3f(0.0f, 0.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, 1.0f);  // Front Face
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, 1.0f);

        gl.glNormal3f(0.0f, 0.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, -1.0f);  // Back Face
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, -1.0f);

        gl.glNormal3f(1.0f, 0.0f, 0.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, -1.0f);  // Right face
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, 1.0f);

        gl.glNormal3f(-1.0f, 0.0f, 0.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, -1.0f);  // Left Face
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, -1.0f);
        gl.glEnd();

        gl.glEndList();

        top = box + 1;                        // Storage For "Top" Is "Box" Plus One
        gl.glNewList(top, GL2.GL_COMPILE);  // Now The "Top" Display List

        gl.glBegin(GL2.GL_QUADS);
        gl.glNormal3f(0.0f, 1.0f, 0.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, -1.0f);// Top Face
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, -1.0f);
        gl.glEnd();
        gl.glEndList();
    }

 

显示列表的原理就是预先画一次gl.glNewList()与gl.glEndList()里的物体,保存到缓存里,以后你再调用gl.glCallList从缓存里取出原先物体,取出过程几乎不占用CPU,效率就大大提高.

 

 

完整GL控制类代码:

package demos.nehe.lesson12;

import demos.common.TextureReader;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import java.io.IOException;
import javax.media.opengl.GL2;

class Renderer implements GLEventListener {
    private float[][] boxcol = {{1.0f, 0.0f, 0.0f},
                                {1.0f, 0.5f, 0.0f},
                                {1.0f, 1.0f, 0.0f},
                                {0.0f, 1.0f, 0.0f},
                                {0.0f, 1.0f, 1.0f}};
    private float[][] topcol = {{0.5f, 0.0f, 0.0f},
                                {0.5f, .25f, 0.0f},
                                {0.5f, 0.5f, 0.0f},
                                {0.0f, 0.5f, 0.0f},
                                {0.0f, 0.5f, 0.5f}};
    private float xrot;                           // Rotates Cube On The X Axis
    private boolean increaseX;
    private boolean decreaseX;

    private float yrot;                           // Rotates Cube On The Y Axis
    private boolean increaseY;
    private boolean decreaseY;

    private int[] textures = new int[1];         // Storage For 1 Texture
    private int xloop;                          // Loop For X Axis
    private int yloop;                          // Loop For Y Axis
    private int box;                            // Storage For The Box Display List
    private int top;                            // Storage For The Top Display List

    private GLU glu = new GLU();

    public void increaseXrot(boolean increase) {
        increaseX = increase;
    }

    public void decreaseXrot(boolean decrease) {
        decreaseX = decrease;
    }

    public void increaseYrot(boolean increase) {
        increaseY = increase;
    }

    public void decreaseYrot(boolean decrease) {
        decreaseY = decrease;
    }

    private void loadGLTexture(GL2 gl) {
        TextureReader.Texture texture = null;
        try {
            texture = TextureReader.readTexture("demos/data/images/cube.bmp");
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        gl.glGenTextures(1, textures, 0);  // Create The Texture
        // Typical Texture Generation Using Data From The Bitmap
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textures[0]);
        gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, 3, texture.getWidth(), texture.getHeight(),
                0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture.getPixels());
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
    }

    private void buildLists(GL2 gl) {
        box = gl.glGenLists(2);           // Generate 2 Different Lists
        gl.glNewList(box, GL2.GL_COMPILE);  // Start With The Box List

        gl.glBegin(GL2.GL_QUADS);
        gl.glNormal3f(0.0f, -1.0f, 0.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Face
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, 1.0f);

        gl.glNormal3f(0.0f, 0.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, 1.0f);  // Front Face
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, 1.0f);

        gl.glNormal3f(0.0f, 0.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, -1.0f);  // Back Face
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, -1.0f);

        gl.glNormal3f(1.0f, 0.0f, 0.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, -1.0f);  // Right face
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(1.0f, -1.0f, 1.0f);

        gl.glNormal3f(-1.0f, 0.0f, 0.0f);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, -1.0f);  // Left Face
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(-1.0f, -1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, -1.0f);
        gl.glEnd();

        gl.glEndList();

        top = box + 1;                        // Storage For "Top" Is "Box" Plus One
        gl.glNewList(top, GL2.GL_COMPILE);  // Now The "Top" Display List

        gl.glBegin(GL2.GL_QUADS);
        gl.glNormal3f(0.0f, 1.0f, 0.0f);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-1.0f, 1.0f, -1.0f);// Top Face
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f(1.0f, 1.0f, 1.0f);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f(1.0f, 1.0f, -1.0f);
        gl.glEnd();
        gl.glEndList();
    }

    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        gl.glEnable(GL2.GL_TEXTURE_2D);                              // Enable Texture Mapping
        gl.glShadeModel(GL2.GL_SMOOTH);                              // Enable Smooth Shading
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                    // Black Background
        gl.glClearDepth(1.0f);                                      // Depth Buffer Setup
        gl.glEnable(GL.GL_DEPTH_TEST);      //3D场景里记得要开深度测试 Enables Depth Testing
        gl.glDepthFunc(GL.GL_LEQUAL);                               // The Type Of Depth Testing To Do
        gl.glEnable(GL2.GL_LIGHT0);                                  // Quick And Dirty Lighting (Assumes Light0 Is Set Up)
        gl.glEnable(GL2.GL_LIGHTING);                                // Enable Lighting
        gl.glEnable(GL2.GL_COLOR_MATERIAL);                          // Enable Material Coloring
        gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);  // Really Nice Perspective Calculations

        loadGLTexture(gl);
        buildLists(gl);
    }

    private void update() {
        if (decreaseX)
            xrot -= 8f;
        if (increaseX)
            xrot += 8f;
        if (decreaseY)
            yrot -= 8f;
        if (increaseY)
            yrot += 8f;
    }

    public void display(GLAutoDrawable drawable) {
        update();
        GL2 gl = drawable.getGL().getGL2();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textures[0]);
        for (yloop = 1; yloop < 6; yloop++) {
            for (xloop = 0; xloop < yloop; xloop++) {
                gl.glLoadIdentity();          // Reset The View
                gl.glTranslatef(1.4f + ((float) xloop * 2.8f) - ((float) yloop * 1.4f), ((6.0f - (float) yloop) * 2.4f) - 7.0f, -20.0f);
                gl.glRotatef(45.0f - (2.0f * yloop) + xrot, 1.0f, 0.0f, 0.0f);
                gl.glRotatef(45.0f + yrot, 0.0f, 1.0f, 0.0f);
                gl.glColor3fv(boxcol[yloop - 1], 0);
                gl.glCallList(box);
                gl.glColor3fv(topcol[yloop - 1], 0);
                gl.glCallList(top);
            }
        }


       //显示1000个箱子
       for(int i=0;i<1000;i++)
       {
           gl.glTranslatef(i*2,0.0f,0.0f);
           gl.glCallList(box);
            gl.glCallList(top);
       }
    }

    public void reshape(GLAutoDrawable drawable,
                        int xstart,
                        int ystart,
                        int width,
                        int height) {
        GL2 gl = drawable.getGL().getGL2();

        height = (height == 0) ? 1 : height;

        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();

        glu.gluPerspective(45, (float) width / height, 1, 1000);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    public void displayChanged(GLAutoDrawable drawable,
                               boolean modeChanged,
                               boolean deviceChanged) {
    }

    public void dispose(GLAutoDrawable arg0) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

 
 分享自己的技术论坛http://www.itneng.com/forum.php
 
 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 本身并没有提供原生的 3D 绘制功能,但是可以使用一些第三方库来实现。其比较常用的 3D 绘制库有 Java3DJOGL(Java OpenGL)。 以下是一个使用 JOGL 库绘制 3D 立方体的示例代码: ```java import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.GLCapabilities; import javax.media.opengl.awt.GLCanvas; import javax.swing.JFrame; import com.jogamp.opengl.util.FPSAnimator; public class Main implements GLEventListener { private GLCanvas canvas; private FPSAnimator animator; private float angle = 0.0f; public static void main(String[] args) { JFrame frame = new JFrame("3D Cube"); GLProfile profile = GLProfile.get(GLProfile.GL2); GLCapabilities capabilities = new GLCapabilities(profile); Main app = new Main(); app.canvas = new GLCanvas(capabilities); app.canvas.addGLEventListener(app); frame.getContentPane().add(app.canvas); frame.setSize(640, 480); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); app.animator = new FPSAnimator(app.canvas, 60); app.animator.start(); } public void init(GLAutoDrawable drawable) { GL gl = drawable.getGL(); gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); gl.glEnable(GL.GL_DEPTH_TEST); } public void dispose(GLAutoDrawable drawable) { } public void display(GLAutoDrawable drawable) { GL gl = drawable.getGL(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -5.0f); gl.glRotatef(angle, 1.0f, 1.0f, 1.0f); gl.glBegin(GL.GL_QUADS); gl.glColor3f(1.0f, 0.0f, 0.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); gl.glVertex3f(1.0f, 1.0f, -1.0f); gl.glVertex3f(1.0f, -1.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.glVertex3f(1.0f, 1.0f, 1.0f); gl.glVertex3f(1.0f, -1.0f, 1.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.glVertex3f(1.0f, 1.0f, -1.0f); gl.glVertex3f(1.0f, 1.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); gl.glColor3f(1.0f, 1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glVertex3f(1.0f, -1.0f, -1.0f); gl.glVertex3f(1.0f, -1.0f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); gl.glColor3f(0.0f, 1.0f, 1.0f); gl.glVertex3f(1.0f, 1.0f, -1.0f); gl.glVertex3f(1.0f, 1.0f, 1.0f); gl.glVertex3f(1.0f, -1.0f, 1.0f); gl.glVertex3f(1.0f, -1.0f, -1.0f); gl.glColor3f(1.0f, 0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glEnd(); angle += 1.0f; } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL gl = drawable.getGL(); float aspectRatio = (float) height / width; gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustum(-1.0f, 1.0f, -aspectRatio, aspectRatio, 1.0f, 100.0f); gl.glMatrixMode(GL.GL_MODELVIEW); } } ``` 这段代码创建了一个窗口,并使用 JOGL 库在窗口绘制一个 3D 立方体。在 `init` 方法启用深度测试,`display` 方法绘制立方体的六个面,`reshape` 方法设置投影矩阵。最后在 `main` 方法创建窗口并启动动画循环。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值