vetexarray.htm
来自「电脑图学(Computer Graphics)是资料结构、演算法与数学的应用」· HTM 代码 · 共 151 行
HTM
151 行
<!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: 顶点索引阵列</a></h1>
无论是2D或是3D绘制,顶点的使用是一个重要的课题,顶点的使用与座标息息相关,这也就是为何之前一直在谈论座标系统的原因。<br>
<br>
顶点的记录方式有许多种,不同的绘图目的应搭配不同的顶点资料结构,这边介绍最简单的几个立体物件顶点记录方式。<br>
<br>
假设有一个正立方体,其中心位于原点,则可以如下图先定出顶点的座标: <br>
<img style="width: 394px; height: 232px;" alt="" src="images/vetexArray-1.jpg"><br>
<br>
纸上作业与程式规划所不同的是,如何使用这些顶点来绘制一个立方体,基本上必须以四个顶点为一个单位,使用绘制多边型的函式来绘制一个四边形,然后以较方
便的方式选择四个顶点,通常会使用回圈,但为了能使用回圈,顶点资料结构必须有可重复索引的性质,在这边介绍两种规划方式。<br>
<br>
其中一个规划方式是使用6*4=24个元素的阵列,每个面使用掉四个顶点,如下图所示: <br>
<span class="postbody"></span><img style="width: 542px; height: 404px;" alt="" src="images/vetexArray-2.jpg"><br>
<br>
如此就可以使用回圈取出顶点资讯,这个方法的好处是简单,但由于顶点会有重复,因而会耗用大量的记忆体,对于复杂图形并不适用。<br>
<br>
可以使用顶点索引来解决顶点重复的问题,首先必须先将顶点编号,如下图所示: <br>
<img style="width: 240px; height: 190px;" alt="" src="images/vetexArray-3.jpg"><br>
<br>
通常为了具有判别法向量的作用,顶点编号时使用右手定则,以逆时针的顺序来编号同一个面的顶点;顶点编号完毕后,使用一个顶点索引阵列来记录每个面所使用到的顶点编号,如下所示:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">int v_ord[][] = {{0, 1, 2, 3}, {0, 7, 6, 1}, {4, 5, 6, 7},</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">
{2, 5, 4, 3}, {0, 3, 4, 7}, {1, 6, 5, 2}};</span><br>
</div>
<br>
<br>
使用索引阵列的好处是减少记忆体使用量,虽然额外使用了一个索引阵列,但对于顶点越多时,记忆体的减少使用会更显著,但缺点就是必须额外耗用一些运算是处理顶点资讯。<br>
<br>
下面是使用顶点索引阵列来绘制正立方体的Java Applet程式,您可以参考我们是如何处理顶点资讯的:<br>
<ul>
<li> Vetex.java</li>
</ul>
<pre>import java.awt.*;<br>import java.applet.*;<br>import java.awt.event.*;<br> <br>class Point3D {<br> public int x, y, z;<br> <br> public Point3D() {<br> x = y = z = 0;<br> }<br> <br> public Point3D(int x, int y, int z) {<br> this.x = x;<br> this.y = y;<br> this.z = z;<br> }<br>}<br> <br>public class Vetex extends Applet {<br> public void paint(Graphics g) {<br> final int r = 100;<br> <br> // 索引array<br> int v_ord[][] = <br> {{0, 1, 2, 3}, {0, 7, 6, 1}, {4, 5, 6, 7},<br> {2, 5, 4, 3}, {0, 3, 4, 7}, {1, 6, 5, 2}};<br> <br> // 立方体顶点<br> Point3D[] vetex = <br> {new Point3D(r, r, r), new Point3D(r, -r, r),<br> new Point3D(r, -r, -r), new Point3D(r, r, -r),<br> new Point3D(-r, r, -r), new Point3D(-r, -r, -r),<br> new Point3D(-r, -r, r), new Point3D(-r, r, r)};<br> <br> Point3D[] tp = new Point3D[4];<br> <br> // 视窗中心<br> final int orgX = (int)getSize().width / 2,<br> orgY = (int)getSize().height / 2;<br> final double rd = Math.PI / 180;<br> double ax, ay;<br> <br> int[] px = new int[4],<br> py = new int[4];<br> <br> int i, j, k;<br> <br> // 旋转以斜角绘制图形<br> ax = 30 * rd;<br> ay = -30 * rd;<br> <br> setBackground(Color.black);<br> g.setColor(Color.yellow);<br> <br> for(i = 0; i < 6; i++) {<br> for(j = 0; j < 4; j++) {<br> // 利用索引array取出正确的顶点<br> tp[j] = vetex[v_ord[i][j]];<br> <br> // 旋转以斜角绘制图形<br> px[j] = (int) (tp[j].x*Math.cos(ay) <br> + tp[j].z*Math.sin(ay));<br> py[j] = (int) (tp[j].y*Math.cos(ax) <br> - (-tp[j].x*Math.sin(ay)<br> + tp[j].z*Math.cos(ay)) * Math.sin(ax));<br> px[j] = px[j] + orgX;<br> py[j] = -py[j] + orgY;<br> }<br> g.drawPolyline(px, py, 4);<br> }<br> }<br>}</pre>
<br>
如果您使用3D函式库时,通常可以自行选择使用哪一种顶点记录方式,而且包装成物件之后,您也无须亲自处理索引的细节。<br>
<br>
<img style="width: 600px; height: 453px;" alt="" src="images/vetexArray-4.jpg"><br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?