📄 构建高级粒子系统.htm
字号:
particles within the specific system will have the same
texture assigned.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">BlendMode</TD>
<TD class=ColorCode vAlign=top width="19%">blendMode</TD>
<TD class=EtoC vAlign=top width="63%">The blend mode you want
to use for the particles. Smoke will probably have a different
blend mode from blood-that's the reason you also store the
blend mode for each particle system.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">int</TD>
<TD class=ColorCode vAlign=top width="19%">systemType</TD>
<TD class=EtoC vAlign=top width="63%">A unique ID, which
represents the type of system (smoke or sparks, for example).
The systemType identifier is also required, since you may want
to check for a specific type of particle system within the
collection of all systems. For example, to remove all smoke
systems, you need to know whether a given system is a smoke
system or not.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">Array Particle</TD>
<TD class=ColorCode vAlign=top width="19%">particles</TD>
<TD class=EtoC vAlign=top width="63%">The collection of
particles within this system. This may also be a linked list
instead of an array.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">Array PShape</TD>
<TD class=ColorCode vAlign=top width="19%">shapes</TD>
<TD class=EtoC vAlign=top width="63%">A collection of shapes,
describing the shapes of the particles. The shape descriptions
of the particles usually consist of four positions in 3D
camera-space. These four positions are used to draw the two
triangles for our particle. As you can see in Table 1, a
particle is only stored as a single position, but it requires
four positions (vertices) to draw the texture-mapped shape of
the particle.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">int</TD>
<TD class=ColorCode vAlign=top width="19%">nrAlive</TD>
<TD class=EtoC vAlign=top width="63%">Number of particles in
the system which are still alive. If this value is zero, it
means all particles are dead and the system can be
removed.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">BoundingBox3</TD>
<TD class=ColorCode vAlign=top width="19%">boundingBox</TD>
<TD class=EtoC vAlign=top width="63%">The 3D axis-aligned
bounding box (AABB), used for visibility determination. We can
use this for frustum, portal, and anti-portal checks.</TD></TR>
<TR bgColor=#ffffff>
<TD class=BGRed colSpan=3 vAlign=top>
<DIV align=center><B><FONT color=#cccccc>表2
粒子系统基类的属性</FONT></B></DIV></TD></TR></TBODY></TABLE><BR> 下面将讲述如何计算经常面对活动镜头的粒子的四个位置。首先,把粒子世界空间坐标变换到镜头空间(用世界空间的位置坐标乘以活动镜头矩阵)使用粒子的大小属性来计算四个顶点。<BR><BR>
<TABLE align=center border=0 cellPadding=2 cellSpacing=0
class=BGRed>
<TBODY>
<TR align=middle>
<TD><IMG height=180 src="AParSystem-3.gif"
width=187></TD></TR>
<TR align=middle>
<TD><FONT color=#cccccc><B>图3
为渲染粒子的建立形状</B></FONT></TD></TR></TBODY></TABLE><BR> 我们使用这四个形成形状的顶点来渲染粒子,虽然一个粒子只有一个位置:xyz。为了渲染一个粒子(例如一个火花),我们需要建立一个形状(用4个顶点)。然后在四个顶点之间我们得到两个三角形。想象一个非伸展的粒子总是面对你前面的镜头,就像图3所描述的一样。对我们来说,粒子总是面对活动镜头的,这意味着我们可以简单的加减粒子的镜头空间坐标的x和y值。换句话说,保留z值不变就好像你在作2D一样。你可以在清单1中看到一个计算的例子。<BR><BR> <SPAN
class=ColorCatchword>// 清单1 — Calculating the shape of a particle
facing the camera.</SPAN><BR> <SPAN class=ColorCode>void
ParticleSystem::SetupShape(int nr)<BR> {<BR> assert(nr <
shapes.Length());</SPAN> <SPAN class=ColorCatchword>// make sure we
don't try to shape anything we<BR> // don't
have<BR><BR> // calculate cameraspace
position<BR></SPAN> <SPAN class=ColorCode>Vector3 csPos =
gCamera->GetViewMatrix() *
particles[nr].position;<BR></SPAN><BR> <SPAN
class=ColorCatchword>// set up shape vertex
positions<BR></SPAN> <SPAN class=ColorCode>shapes[nr].vertex[0] =
csPos + Vector3(-particles[nr].size, particles[nr].size,
0);<BR> shapes[nr].vertex[1] = csPos + Vector3(
particles[nr].size, particles[nr].size,
0);<BR> shapes[nr].vertex[2] = csPos + Vector3(
particles[nr].size, -particles[nr].size,
0);<BR> shapes[nr].vertex[3] = csPos +
Vector3(-particles[nr].size, -particles[nr].size,
0);<BR> }</SPAN><BR><A name=3.0></A><BR><B>3、函数</B>(<SPAN
class=English>The
Functions</SPAN>)<BR> 现在我们知道在粒子系统的基类中需要什么属性,我们能够开始思考需要什么样的函数。既然是基类大多数的函数被声明为虚函数。每种粒子系统都用不同的方式来更新粒子属性,所以我们需要一个虚拟的更新函数。这个更新函数将完成以下任务:
<UL>
<LI>更新所有粒子的位置和其他属性。
<LI>如果我们不能预先计算绑定盒,则需更新它
<LI>计算存活的粒子数量。如果没有存活的粒子则返回FALSE,反之返回TRUE。返回值将被用于判定系统是否可被删除。
</LI></UL> 现在我们的基类已有能力来更新粒子,我们也将要建立可用新的(也可能是旧的)位置来构建的形状。这个函数<SPAN
class=ColorCode>,SetupShape</SPAN>,必须是个虚拟函数,因为某些粒子系统会要伸展粒子,而有些系统不会这么做。你可以在清单1中看到这样一个函数。<BR> 要向给定的系统加入一个粒子或是重新生成它,建立一个做这件事的函数将是十分有益的。同样,这应该是个虚拟函数,并应该如此定义:<BR><BR> <SPAN
class=ColorCode>virtual void SetParticleDefault(Particle
&p);</SPAN><BR><BR> 就像我在前面解释过的,这个函数初始化给定粒子的属性值。但如果你想要改变烟的速度或是影响你的烟系统的风向。这是我们接触下一个主题:粒子系统的构造函数。许多粒子系统需要他们独特的构造函数,强迫我们在基类中建立一个虚拟构造函数和析构函数。在基类的构造函数中你应该输入以下信息:
<UL>
<LI>你一开始想在系统中构建的粒子数量。
<LI>粒子系统的位置。
<LI>你想在系统中使用的混合模式。
<LI>你想在系统中使用的底纹或底纹文件名。
<LI>系统方式(即ID)。 </LI></UL> 在我的引擎中,粒子系统的基类中的构造函数是这样的:<BR><BR> <SPAN
class=ColorCode>virtual ParticleSystem( int nr,<BR> rcVector3
centerPos,<BR> BlendMode blend=Blend_AddAlpha,<BR> rcString
file name=óEffects/Particles/
green_particleó,<BR> ParticleSystemType
type=PS_Manual<BR> );</SPAN><BR><BR> 那么应该在哪儿做例如烟系统的风向的各种设置呢?你可以在构造函数中加入根据特定系统的设定值,也可以在每个类中建立一个名为InitInfo的结构体(<SPAN
class=English>structure</SPAN>),其中包含所有的必须的设定值。如果你使用后一种方法,确保在构造函数中加入一个新的参数,即指向新结构的指针。如果指针为空(NULL),使用默认的设定值。<BR> 正如你所想象的,第一种方法要在构造函数中加入很多参数,而这对于程序员来说过于繁琐。这是我不使用第一种方法的主要原因。使用第二种方法则简单得多,我们可以在每一个粒子系统类中建立一个函数以用默认值来初始化它的结构。这段代码的例子和演示程序可在这里得到。<BR><A
name=4.0></A><BR><B>4、粒子管理器</B>(<SPAN class=English>The Particle
Manager</SPAN>)<BR> 现在我们已经发现了每个粒子系统背后的隐藏的技术,该是创建一个管理类来控制我们的各种粒子系统时候。一个管理类将掌管创建、释放、更新及渲染所有的系统。这样,管理类必须有一个属性是指向粒子系统的指针。我强烈推荐你建立或是使用一个数组模板(<SPAN
class=English>Array
Template</SPAN>),因为这将会简单些。<BR> 你制作的粒子系统的使用者或许会希望较容易地增加系统。他们也不想跟踪所有的系统以保证所有粒子均已死亡从而可以从内存中释放它们。这就是设计管理类的目。管理器将会在需要时自动更新和渲染系统,并删除已死亡的系统。<BR> 当使用不定时系统(系统将在给定的时间后死亡)时,有一个检查系统是否已被删除的函数是很有用的(例如,是否它还存在于粒子管理器中)。想象你创建了一个系统并存储了指向系统的指针。你通过这个指针每一帧访问系统。如果系统恰巧在你使用指针之前死亡,会发生什么?崩溃。这就是为什么我们需要一个检查系统是否存活还是已经被管理类删除的函数。粒子管理类中需要的函数列表如表3所示。<BR><BR>
<TABLE align=center bgColor=#000000 border=0 cellPadding=2
cellSpacing=1 width="95%">
<TBODY>
<TR class=BGRed>
<TD width="18%"><B><FONT color=#cccccc>函数</FONT></B></TD>
<TD colSpan=2><B></B><B><FONT
color=#cccccc>描述</FONT></B></TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">Init</TD>
<TD class=EtoC colSpan=2 vAlign=top>Initializes the particle
manager.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">AddSystem</TD>
<TD class=EtoC colSpan=2 vAlign=top>Adds a specified particle
system to the manager.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">RemoveSystem</TD>
<TD class=EtoC colSpan=2 vAlign=top>Removes a specified
particle system.</TD></TR>
<TR bgColor=#ffffff>
<TD class=ColorCode vAlign=top width="18%">Update</TD>
<TD class=EtoC colSpan=2 vAlign=top>Updates all active
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -