📄 tutorial_10.htm
字号:
<font color="#aaffaa" size="3">
<pre><font color="#ffffaa">// 先前的定义: char* worldfile = "data\\world.txt";</font>
void SetupWorld() <font color="#ffffaa">// 设置我们的世界</font>
{
FILE *filein; <font color="#ffffaa">// 工作文件</font>
filein = fopen(worldfile, "rt"); <font color="#ffffaa">// 打开文件</font>
...
(读入数据资料))
...
fclose(filein); <font color="#ffffaa">// 关闭文件</font>
return; <font color="#ffffaa">// 返回</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td background="Tutorial_10_files/l.gif"><img src="Tutorial_10_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">
下一个挑战是将每个单独的文本行读入变量。这有很多办法可以做到。一个问题是文件中并不是所有的行都包含有意义的信息。空行和注释不应该被读入。我们创建
了一个叫做readstr()的函数。这个函数会从数据文件中读入一个有意义的行至一个已经初始化过的字符串。下面就是代码:<br></td>
<td background="Tutorial_10_files/r.gif"><img src="Tutorial_10_files/r.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/br.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<font color="#aaffaa" size="3">
<pre>void readstr(FILE *f,char *string) <font color="#ffffaa">// 读入一个字符串</font>
{
do <font color="#ffffaa">// 循环开始</font>
{
fgets(string, 255, f); <font color="#ffffaa">// 读入一行</font>
} while ((string[0] == '/') || (string[0] == '\n')); <font color="#ffffaa">// 考察是否有必要进行处理</font>
return; <font color="#ffffaa">// 返回</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td background="Tutorial_10_files/l.gif"><img src="Tutorial_10_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%"> 下一步我们读入区段数据。这一课将只处理一个区段,不过实现一个多区段引擎也很容易。让我们将注意力转回SetupWorld()。程序必须知道区段内包含了多少个三角形。我们在数据文件中以下面这种形式定义三角形数量:<br>
接下来是读取三角形数量的代码:</td>
<td background="Tutorial_10_files/r.gif"><img src="Tutorial_10_files/r.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/br.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<font color="#aaffaa" size="3">
<pre>int numtriangles; <font color="#ffffaa">// 区段中的三角形数量</font>
char oneline[255]; <font color="#ffffaa">// 存储数据的字符串</font>
...
readstr(filein,oneline); <font color="#ffffaa">// 读入一行数据</font>
sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles); <font color="#ffffaa">// 读入三角形数量</font>
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td background="Tutorial_10_files/l.gif"><img src="Tutorial_10_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%">余下的世界载入过程采用了相似的方法。接着,我们对区段进行初始化,并读入部分数据:</td>
<td background="Tutorial_10_files/r.gif"><img src="Tutorial_10_files/r.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/br.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<font color="#aaffaa" size="3">
</font><pre><font color="#aaffaa" size="3"><font color="#ffffaa">// 先前的定义: SECTOR sector1;</font>
char oneline[255]; <font color="#ffffaa">// 存储数据的字符串</font>
int numtriangles; <font color="#ffffaa">// 区段的三角形数量</font>
float x, y, z, u, v; <font color="#ffffaa">// 3D 和 纹理坐标</font>
...
sector1.triangle = new TRIANGLE[numtriangles]; <font color="#ffffaa">// 为numtriangles个三角形分配内存并设定指针</font>
sector1.numtriangles = numtriangles; <font color="#ffffaa">// 定义区段1中的三角形数量</font>
<font color="#ffffaa">// 遍历区段中的每个三角形</font>
for (int triloop = 0; triloop < numtriangles; triloop++) <font color="#ffffaa">// 遍历所有的三角形</font>
{
<font color="#ffffaa">// 遍历三角形的每个顶点</font>
for (int vertloop = 0; vertloop < 3; vertloop++) <font color="#ffffaa">// 遍历所有的顶点</font>
{
readstr(filein,oneline); <font color="#ffffaa">// 读入一行数据</font>
<font color="#ffffaa">// 读入各自的顶点数据</font>
sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
<font color="#ffffaa">// 将顶点数据存入各自的顶点</font>
sector1.triangle[triloop].vertex[vertloop].x = x; <font color="#ffffaa">// 区段 1, 第 triloop 个三角形, 第 vertloop 个顶点, 值 x =x</font>
sector1.triangle[triloop].vertex[vertloop].y = y; <font color="#ffffaa">// 区段 1, 第 triloop 个三角形, 第 vertloop 个顶点, 值 y =y</font>
sector1.triangle[triloop].vertex[vertloop].z = z; <font color="#ffffaa">// 区段 1, 第 triloop 个三角形, 第 vertloop 个顶点, 值 z =z</font>
sector1.triangle[triloop].vertex[vertloop].u = u; <font color="#ffffaa">// 区段 1, 第 triloop 个三角形, 第 vertloop 个顶点, 值 u =u</font>
sector1.triangle[triloop].vertex[vertloop].v = v; <font color="#ffffaa">// 区段 1, 第 triloop 个三角形, 第 vertloop 个顶点, 值 e=v</font>
}
}
</font></pre>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/tl.jpg" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/tc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/tr.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td background="Tutorial_10_files/l.gif"><img src="Tutorial_10_files/l.gif" height="28" width="28"></td>
<td valign="top" width="100%"><font face="arial" size="-1"> </font>数据文件中每个三角形都以如下形式声明:<br>
X1 Y1 Z1 U1 V1<br>
X2 Y2 Z2 U2 V2<br>
X3 Y3 Z3 U3 V3<br>
显示世界<br>
现在区段已经载入内存,我们下一步要在屏幕上显示它。到目前为止,我们所作过的都是些简单的旋转和平移。但我们的镜头始终位于原点(0,0,0)处。任何
一个不错的3D引擎都会允许用户在这个世界中游走和遍历,我们的这个也一样。实现这个功能的一种途径是直接移动镜头并绘制以镜头为中心的3D环境。这样做
会很慢并且不易用代码实现。我们的解决方法如下: <ul>
<li>根据用户的指令旋转并变换镜头位置。</li>
<li>围绕原点,以与镜头相反的旋转方向来旋转世界。(让人产生镜头旋转的错觉)</li>
<li>以与镜头平移方式相反的方式来平移世界(让人产生镜头移动的错觉)。</li>
</ul>
<p>这样实现起来就很简单.<br>
下面从第一步开始吧(平移并旋转镜头)。<br>
</p>
</td>
<td background="Tutorial_10_files/r.gif"><img src="Tutorial_10_files/r.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><img src="Tutorial_10_files/bl.gif" height="28" width="28"></td>
<td width="100%"><img src="Tutorial_10_files/bc.gif" height="28" width="100%"></td>
<td><img src="Tutorial_10_files/br.gif" height="28" width="28"></td>
</tr>
</tbody>
</table>
<font color="#aaffaa" size="3">
</font><pre><font color="#aaffaa" size="3">if (keys[VK_RIGHT]) <font color="#ffffaa">// 右方向键按下了么?</font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -