⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tutorial_30.htm

📁 如果你相信它就好好学学吧,同样这里也只是个入门
💻 HTM
📖 第 1 页 / 共 3 页
字号:
  }</font></p>
<p><font color="#aaffaa" size="3"> }</font></p>
<p><font color="#aaffaa" size="3"> if (Timedummy!=10000) { TimePoint=Timedummy;<br>
  return 1;<br>
  }</font></p>
<p><font color="#aaffaa" size="3"> return 0;<br>
  }</font></p>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_30_files/l.png"><img src="Tutorial_30_files/l.png"></td>
    <td valign="top" width="100%"><u>怎样应用我们的知识</u><br> <br>
      现在我们已经可以决定射线和平面/圆柱的交点了,如下图所示:<br> <br> <center>
        <img src="Tutorial_30_files/figure2.jpg"><br>
图 2a
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
图 2b </center>
      <br>
      当我们找到了碰撞位置后,下一步我们需要知道它是否发生在当前这一步中.如果距离碰撞点的位置小于这一步球体运动的间隔,则碰撞发生.我们使用如下的方程计算运动到碰撞时所需的时间:<br>
      Tc= Dsc*T / Dst <br>
      接着我们知道碰撞点位置,如下面公式所示:<br>
      Collision point= Start + Velocity*Tc <br> <br>
      2) 基于物理的模拟 <center>
      </center> <br> <br> <u>碰撞反应</u> <br> <br>
      为了计算对于一个静止物体的碰撞,我们需要知道以下信息:碰撞点,碰撞法线,碰撞时间.<br> <br>
      它是基于以下物理规律的,碰撞的入射角等于反射角.如下图所示:<br> <br> <center>
        <img src="Tutorial_30_files/figure3.jpg"><br>
        图 3 
      </center>
      <br> <br>
      R 为反射方向<br>
      I 为入射方向<br>
      N 为法线方向<br> <br>
      反射方向有以下公式计算 : <br> <br>
      R= 2*(-I dot N)*N + I <br>
      <font face="Tahoma,Verdana,sans-serif">
      <center>
      </center>
      </font></td>
    <td background="Tutorial_30_files/r.png"><img src="Tutorial_30_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre>rt2=ArrayVel[BallNr].mag();						<font color="#ffffaa">// 返回速度向量的模</font>
ArrayVel[BallNr].unit();						<font color="#ffffaa">// 归一化速度向量</font>

<font color="#ffffaa">// 计算反射向量</font>
ArrayVel[BallNr]=TVector::unit( (normal*(2*normal.dot(-ArrayVel[BallNr]))) + ArrayVel[BallNr] );
ArrayVel[BallNr]=ArrayVel[BallNr]*rt2;					
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_30_files/l.png"><img src="Tutorial_30_files/l.png"></td>
    <td valign="top" width="100%"><u>球体之间的碰撞</u><br> <br>
      由于它很复杂,我们用下图来说明这个原理. <br> <br> <center>
        <img src="Tutorial_30_files/figure4.jpg"><br>
        图 4 </center> <center>
      </center> <p><br>
        <br>
U1和U2为速度向量,我们用X_Axis表示两个球中心连线的轴,U1X和U2X为U1和U2在这个轴上的分量。U1y和U2y为垂直于X_Axis轴
的分量。M1和M2为两个球体的分量。V1和V2为碰撞后的速度,V1x,V1y,V2x,V2y为他们的分量。</p>
      <p>在我们的例子里,所有球的质量都相等,解得方程为,在垂直轴上的速度不变,在X_Axis轴上互相交换速度。代码如下:</p>
      </td><td background="Tutorial_30_files/r.png"><img src="Tutorial_30_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
</font><pre><font color="#aaffaa" size="3">TVector pb1,pb2,xaxis,U1x,U1y,U2x,U2y,V1x,V1y,V2x,V2y;
double a,b;
pb1=OldPos[BallColNr1]+ArrayVel[BallColNr1]*BallTime;			<font color="#ffffaa">// 球1的位置</font>
pb2=OldPos[BallColNr2]+ArrayVel[BallColNr2]*BallTime;			<font color="#ffffaa">// 球2的位置</font>
xaxis=(pb2-pb1).unit();							<font color="#ffffaa">// X-Axis轴</font>
a=xaxis.dot(ArrayVel[BallColNr1]);					<font color="#ffffaa">// X_Axis投影系数</font>
U1x=xaxis*a;								<font color="#ffffaa">// 计算在X_Axis轴上的速度</font>
U1y=ArrayVel[BallColNr1]-U1x; <font color="#aaffaa" size="3"><font color="#ffffaa">// 计算在垂直轴上的速度</font></font>
xaxis=(pb1-pb2).unit();							
b=xaxis.dot(ArrayVel[BallColNr2]);					
U2x=xaxis*b;								
U2y=ArrayVel[BallColNr2]-U2x;
V1x=(U1x+U2x-(U1x-U2x))*0.5;						<font color="#ffffaa">// 计算新的速度</font>
V2x=(U1x+U2x-(U2x-U1x))*0.5;
V1y=U1y;
V2y=U2y;
for (j=0;j&lt;NrOfBalls;j++)						<font color="#ffffaa">// 更新所有球的位置</font>
ArrayPos[j]=OldPos[j]+ArrayVel[j]*BallTime;
ArrayVel[BallColNr1]=V1x+V1y;						<font color="#ffffaa">// 设置新的速度</font>
ArrayVel[BallColNr2]=V2x+V2y;						</font></pre>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_30_files/l.png"><img src="Tutorial_30_files/l.png"></td>
    <td valign="top" width="100%"><u>万有引力的模拟</u> <br> <br>
      我们使用欧拉方程来模拟万有引力,如下所示: <br>
      Velocity_New = Velovity_Old + Acceleration*TimeStep<br>
      Position_New = Position_Old + Velocity_New*TimeStep <br> <br>
      在每次模拟中,我们用上面公式计算的速度取代旧的速度<br> <br>
      3) 特殊效果 <br> <br> <u>爆炸</u><br> <br>
      最好的表示爆炸效果的就是使用两个互相垂直的平面,并使用alpha混合在窗口中显示它们。接着让alpha变为0,设定爆炸效果不可见。代码如下所示:</td>
    <td background="Tutorial_30_files/r.png"><img src="Tutorial_30_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre><font color="#ffffaa">// 渲染/混合爆炸效果</font>
glEnable(GL_BLEND);							<font color="#ffffaa">// 使用混合</font>
glDepthMask(GL_FALSE);							<font color="#ffffaa">// 禁用深度缓存</font>
glBindTexture(GL_TEXTURE_2D, texture[1]);				<font color="#ffffaa">// 设置纹理</font>
for(i=0; i&lt;20; i++)							<font color="#ffffaa">// 渲染20个爆炸效果</font>
{
	if(ExplosionArray[i]._Alpha&gt;=0)
	{
		glPushMatrix();
		ExplosionArray[i]._Alpha-=0.01f;			<font color="#ffffaa">// 设置alpha</font>
		ExplosionArray[i]._Scale+=0.03f;			<font color="#ffffaa">// 设置缩放</font>
		<font color="#ffffaa">// 设置颜色</font>
		glColor4f(1,1,0,ExplosionArray[i]._Alpha);		
		glScalef(ExplosionArray[i]._Scale,ExplosionArray[i]._Scale,ExplosionArray[i]._Scale);
		<font color="#ffffaa">// 设置位置</font>
		glTranslatef((float)ExplosionArray[i]._Position.X()/ExplosionArray[i]._Scale,
			(float)ExplosionArray[i]._Position.Y()/ExplosionArray[i]._Scale,
			(float)ExplosionArray[i]._Position.Z()/ExplosionArray[i]._Scale);
		glCallList(dlist);					<font color="#ffffaa">// 调用显示列表绘制爆炸效果</font>
		glPopMatrix();
	}
}
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_30_files/l.png"><img src="Tutorial_30_files/l.png"></td>
    <td valign="top" width="100%"><u>声音</u> <br> <br>
      在Windows下我们简单的调用PlaySound()函数播放声音。<br> <br>
      4) 代码的流程 <br> <br>
      如果你成功的读完了理论部分,在你开始运行程序并播放声音以前。我们将用伪代码向你介绍一些整个流程,以便你能成功的看懂代码。</td>
    <td background="Tutorial_30_files/r.png"><img src="Tutorial_30_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre>While (Timestep!=0)
{
	对每一个球
	{
		计算最近的与平面碰撞的位置;
		计算最近的与圆柱碰撞的位置;
		如果碰撞发生,则保存并替换最近的碰撞点;
	}
	检测各个球之间的碰撞;
	如果碰撞发生,则保存并替换最近的碰撞点;

	If (碰撞发生)
	{
		移动所有的球道碰撞点的时间;
		(We already have computed the point, normal and collision time.)
		计算碰撞后的效果;
		Timestep-=CollisonTime;
	}
	else
		移动所有的球体一步
}
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_30_files/l.png"><img src="Tutorial_30_files/l.png"></td><td valign="top" width="100%"><p>下面是对上面伪代码的实现:</p>
      </td><td background="Tutorial_30_files/r.png"><img src="Tutorial_30_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_30_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_30_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_30_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3"> 
</font><pre><font color="#aaffaa" size="3"><font color="#ffffaa">//模拟函数,计算碰撞检测和物理模拟</font><br>void idle()<br>{<br>  double rt,rt2,rt4,lamda=10000;<br>  TVector norm,uveloc;<br>  TVector normal,point,time;<br>  double RestTime,BallTime;<br>  TVector Pos2;<br>  int BallNr=0,dummy=0,BallColNr1,BallColNr2;<br>  TVector Nc;</font></pre>

<p><font color="#aaffaa" size="3"> <font color="#ffffaa">//如果没有锁定到球上,旋转摄像机</font><br>
  if (!hook_toball1)<br>
  {<br>
  camera_rotation+=0.1f;<br>
  if (camera_rotation&gt;360)<br>
  camera_rotation=0;<br>
  }<br>
  <br>
  RestTime=Time;<br>
  lamda=1000;</font></p>
<p><font color="#aaffaa" size="3"> <font color="#ffffaa">//计算重力加速度</font><br>
  for (int j=0;j&lt;NrOfBalls;j++)<br>
  ArrayVel[j]+=accel*RestTime;</font></p>
<p><font color="#aaffaa" size="3"><font color="#ffffaa"> //如果在一步的模拟时间内(如果来不及计算,则跳过几步)</font><br>
  while (RestTime&gt;ZERO)<br>
  {<br>
  lamda=10000; <br>
  <br>
 <font color="#ffffaa"> //对于每个球,找到它们最近的碰撞点</font><br>
  for (int i=0;i&lt;NrOfBalls;i++)<br>
  {<br>
  <font color="#ffffaa">//计算新的位置和移动的距离</font><br>
  OldPos[i]=ArrayPos[i];<br>
  TVector::unit(ArrayVel[i],uveloc);<br>
  ArrayPos[i]=ArrayPos[i]+ArrayVel[i]*RestTime;<br>
  rt2=OldPos[i].dist(ArrayPos[i]);</font></p>
<p><font color="#aaffaa" size="3"> <font color="#ffffaa">//测试是否和墙面碰撞</font><br>
  if (TestIntersionPlane(pl1,OldPos[i],uveloc,rt,norm))<br>
  { <br>
  <font color="#ffffaa">//计算碰撞的时间</font><br>
  rt4=rt*RestTime/rt2;</font></p>
<p><font color="#aaffaa" size="3"> <font color="#ffffaa">//如果小于当前保存的碰撞时间,则更新它</font><br>
  if (rt4&lt;=lamda)<br>
  { <br>
  if (rt4&lt;=RestTime+ZERO)<br>
  if (! ((rt&lt;=ZERO)&amp;&amp;(uveloc.dot(norm)&gt;ZERO)) )<br>
  {<br>
  normal=norm;<br>
  point=OldPos[i]+uveloc*rt;<br>
  lamda=rt4;<br>
  BallNr=i;<br>
  }<br>
  }<br>
  }<br>
  <br>
  if (TestIntersionPlane(pl2,OldPos[i],uveloc,rt,norm))<br>
  {<br>
  rt4=rt*RestTime/rt2;</font></p>
<p><font color="#aaffaa" size="3"> if (rt4&lt;=lamda)<br>
  { <br>
  if (rt4&lt;=RestTime+ZERO)<br>
  if (! ((rt&lt;=ZERO)&amp;&amp;(uveloc.dot(norm)&gt;ZERO)) )<br>
  {<br>
  normal=norm;<br>
  point=OldPos[i]+uveloc*rt;<br>
  lamda=rt4;<br>
  BallNr=i;<br>
  dummy=1;<br>
  }<br>
  }<br>
  <br>
  }</font></p>
<p><font color="#aaffaa" size="3"> if (TestIntersionPlane(pl3,OldPos[i],uveloc,rt,norm))<br>
  {<br>

⌨️ 快捷键说明

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