doublebuffer.htm

来自「电脑图学(Computer Graphics)是资料结构、演算法与数学的应用」· HTM 代码 · 共 133 行

HTM
133
字号
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>







  
  
  
  
  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">







  
  
  
  
  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">







  
  
  
  
  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">







  
  
  
  
  
  
  
  <title>双缓冲区绘图</title>
</head>


<body>







<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>







<h1><a href="ComputerGraphics.htm">Computer Graphics:&nbsp;双缓冲区绘图</a></h1>







如果我们要绘制的图形很多时,在动画制作时,如果直接画在前景上,可能会发生图形一个一个显现出来的画面,让整个画面不完整呈现。<br>
<br>
这时候可使用双缓冲区(double-buffer)的方法,要准备两个绘图物件,其中一个是前景区,也就是您所看到的画面,另一个绘图物件您看不到,在
画面准备好之前,所有的图形先绘制在您看不到的画面,当所有的图形都绘制完毕,再将所有的图形绘制到前景,此时前景会整个被后绘图区所覆盖,完成一次画面
的播放,下图为简单的示意图: <br>







<img style="width: 474px; height: 239px;" alt="" src="images/doubleBuffer-1.jpg"><br>







<br>
实作双缓冲区的方法依所使用的API而有所不同,在Java中可以用Image物件来完成,而在使用DirectDraw时,可以使用
Surface来建立,下面这个程式是使用Java来制作,这个程式是至今所有文件内容验收,包括了顶点配置、索引阵列、动画、双缓冲区等等,您可以先观
看结果:<a href="dbuf.html">一个绕Y轴旋转的空心立方块</a>。 <br>
<ul>
  <li> DoubleBuffer.java
  </li>
</ul>

<pre>package onlyfun.caterpillar.graphics.animation;<br> <br>import javax.swing.JApplet; <br>import java.awt.*; <br> <br>class Point3D { <br>   public double x, y, z; <br> <br>   public Point3D() { <br>      x = y = z = 0; <br>   } <br> <br>   public Point3D(double x, double y, double z) { <br>      this.x = x; <br>      this.y = y; <br>      this.z = z; <br>   } <br>} <br> <br>// 立方体类别 <br>class Cubic { <br>    public int NFc;        // 平面数量 <br>    public int NVt;        // 顶点的数量 <br>    public int Nvt;        // 1个平面的顶点数 <br>    public Point3D[] Vt;   // 顶点的座标 <br>    public int[][] Ord;    // 顶点索引 <br> <br>    public Cubic(int r) { <br>        NFc = 6; <br>        NVt = 8; <br>        Nvt = 4; <br>        Vt = new Point3D[NVt]; <br>        Ord = new int[NFc][Nvt]; <br>        double sq3 = Math.sqrt(3.0); <br>        Vt[0] = new Point3D(r/sq3,r/sq3,r/sq3); <br>        Vt[1] = new Point3D(r/sq3,r/sq3,-r/sq3); <br>        Vt[2] = new Point3D(-r/sq3,r/sq3,-r/sq3); <br>        Vt[3] = new Point3D(-r/sq3,r/sq3,r/sq3); <br> <br>        for(int i = 0; i &lt; NVt/2; i++) <br>            Vt[NVt/2+i] = new Point3D(<br>                           -Vt[i].x, -Vt[i].y, -Vt[i].z); <br> <br>        int[][] ord={{0,1,2,3},{0,3,5,6},{0,6,7,1}, <br>                     {4,7,6,5},{4,2,1,7},{4,5,3,2}}; <br> <br>        for(int i = 0; i &lt; NFc; i++) <br>            for(int j = 0; j &lt; Nvt; j++) <br>                Ord[i][j]=ord[i][j]; <br>    } <br>} <br> <br>public class DoubleBuffer extends JApplet implements Runnable { <br>    private Image OffScreen; <br>    private Graphics drawOffScreen; <br>    private int orgX, orgY; <br>    private Cubic cubic; <br> <br>    public void init() { <br>        setBackground(Color.black); <br> <br>        orgX = (int)(getSize().width / 2); <br>        orgY = (int)(getSize().height / 2);<br> <br>        OffScreen = createImage(getSize().width,<br>                                getSize().height); <br>        drawOffScreen = OffScreen.getGraphics(); <br> <br>        cubic = new Cubic(100); <br>    } <br> <br>    public void start() { <br>        (new Thread(this)).start(); <br>    } <br> <br>    public void run() { <br>        int[] px = new int[4], <br>              py = new int[4]; <br>        Point3D[] tp = new Point3D[4]; <br> <br>        drawOffScreen.setColor(Color.yellow); <br> <br>        // 旋转以斜角绘制图形 <br>        double sinAx = Math.sin(Math.toRadians(30));<br>        double cosAx = Math.cos(Math.toRadians(30));<br>        <br>        double[] cosAys = new double[360];<br>        double[] sinAys = new double[360];<br>        <br>        for(int i = 0; i &lt; 360; i++) {<br>            cosAys[i] = Math.cos(Math.toRadians(i));<br>            sinAys[i] = Math.sin(Math.toRadians(i));<br>        }<br>        <br>        int angle = 330;<br>        <br>        double sinAy = sinAys[angle];<br>        double cosAy = cosAys[angle];<br>         <br>        // 动画回圈 <br>        while(true) { <br>            drawOffScreen.clearRect(0, 0, <br>                        getSize().width, getSize().height); <br>            for(int i = 0; i &lt; cubic.NFc; i++) { <br>                 for(int j = 0; j &lt; cubic.Nvt; j++) { <br>                     // 利用索引array取出正确的顶点 <br>                     tp[j] = cubic.Vt[cubic.Ord[i][j]]; <br> <br>                    // 旋转以斜角绘制图形 <br>                     px[j] = (int) (tp[j].x*cosAy <br>                                    + tp[j].z*sinAy); <br>                     py[j] = (int) (tp[j].y*cosAx <br>                                    - (-tp[j].x*sinAy <br>                                  + tp[j].z*cosAy) * sinAx); <br>                     px[j] = px[j] + orgX; <br>                     py[j] = -py[j] + orgY; <br>                 } <br><br>                 // 在缓冲区上缩图 <br>                 drawOffScreen.drawPolyline(px, py, 4); <br>            } <br> <br>            // 暂停 20 毫秒 <br>            try { <br>               Thread.sleep(20); <br>            } <br>            catch(InterruptedException e) { <br>            } <br> <br>            repaint();  // 重绘画面 <br>            // 绕 y 轴转动 <br>            angle = (angle+1) % 360; <br>            sinAy = sinAys[angle];<br>            cosAy = cosAys[angle];<br>        } <br>    } <br> <br>    // 重新定义update() <br>    public void update(Graphics g) { <br>        paint(g); <br>    } <br> <br>    public void paint(Graphics g) { <br>        // 将缓冲区画面绘到前景 <br>        g.drawImage(OffScreen, 0, 0, this); <br>    } <br>}</pre>
<br>
<br>







</body>
</html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?