File: cs_117.html

package info (click to toggle)
crystalspace 0.94-20020412-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 62,276 kB
  • ctags: 52,843
  • sloc: cpp: 274,783; ansic: 6,608; perl: 6,276; objc: 3,952; asm: 2,942; python: 2,354; php: 542; pascal: 530; sh: 430; makefile: 370; awk: 193
file content (266 lines) | stat: -rw-r--r-- 11,240 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Created by texi2html 1.64 -->
<!-- 
Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
            Karl Berry  <karl@freefriends.org>
            Olaf Bachmann <obachman@mathematik.uni-kl.de>
            and many others.
Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de>
Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
 
-->
<HTML>
<HEAD>
<TITLE>Crystal Space: HOWTO Collision Detection</TITLE>

<META NAME="description" CONTENT="Crystal Space: HOWTO Collision Detection">
<META NAME="keywords" CONTENT="Crystal Space: HOWTO Collision Detection">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META NAME="Generator" CONTENT="texi2html 1.64">

</HEAD>

<BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">

<A NAME="SEC226"></A>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_116.html#SEC225"> &lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_118.html#SEC233"> &gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_108.html#SEC209"> &lt;&lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_116.html#SEC225"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_128.html#SEC290"> &gt;&gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<HR SIZE=1>
<H3> 5.8.1 Doing Collision Detection </H3>
<!--docid::SEC226::-->
<P>

Collision detection in CS is one of the more complicated issues. In this
section I give a quick description of all the classes and interfaces in CS
and what you should do to use them.
</P><P>

<A NAME="SEC227"></A>
<H4> Loading the `<SAMP>iCollideSystem</SAMP>' </H4>
<!--docid::SEC227::-->
<P>

The basis of the collision detection system is the `<SAMP>iCollideSystem</SAMP>'.
This is an interface which implemented by some collision detection plugin.
At this moment we only have an implementation of the RAPID collision
detection system but it would be a simple matter to add a new plugin for
another system.
</P><P>

To load a collision detection system you can use the following code:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>iPluginManager* plugmgr =
  CS_QUERY_REGISTRY (object_reg, iPluginManager);
iConfigManager* config =
  CS_QUERY_REGISTRY (object_reg, iConfigManager);
const char* p = config-&#62;GetStr ("MyGame.Settings.CollDetPlugin",
  	"crystalspace.collisiondetection.rapid");
iCollideSystem* cd_sys =
  CS_LOAD_PLUGIN (plugmgr, p, iCollideSystem);
if (!cd_sys)
{
  csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
	"crystalspace.application.myapp",
  	"No Collision Detection plugin found!");
  return false;
}
</pre></td></tr></table></P><P>

This is a very general example.  It will first get the prefered collision
detection plugin from the config file.  If the config file doesn't specify it
then it will use 'crystalspace.collisiondetection.rapid' which is the only one
we have at the moment.  If you don't want to let the users choose another
plugin then you can also hardcode the string.  The cd_sys should be stored
somewhere central (i.e. your application class).
</P><P>

<A NAME="SEC228"></A>
<H4> Initializing Geometry </H4>
<!--docid::SEC228::-->
<P>

Before you can use the collision detection system you have to make
instances of `<SAMP>iCollider</SAMP>'. Only the collide system can do that. To
create an `<SAMP>iCollider</SAMP>' you have to give an instance of `<SAMP>iPolygonMesh</SAMP>'.
Several meshes in CS implement `<SAMP>iPolygonMesh</SAMP>'. If you have special
geometry on your own you can make your own classes to implement
`<SAMP>iPolygonMesh</SAMP>'. Here is some code on how to initialize the collider
for a mesh:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>iCollider* MyGame::InitCollider (iMeshWrapper* mesh)
{
  iPolygonMesh* polmesh = SCF_QUERY_INTERFACE (mesh-&#62;GetMeshObject (),
  	iPolygonMesh);
  if (polmesh)
  {
    iCollider* cd = cd_sys-&#62;CreateCollider (polmesh);
    polmesh-&#62;DecRef ();
    return cd;
  }
  else
    return NULL;
}
</pre></td></tr></table></P><P>

After that you need to store the returned collider somewhere so you
can easily retrieve it later when you want to do the collision detection.
Usually in a game you have entity classes which will have a pointer to the
mesh. In that case you can easily store the collider in that entity class.
</P><P>

However, you can also use the `<SAMP>iObject</SAMP>' system to attach your collider
to the mesh itself. An easy way to do this is to use the
<CODE>csColliderWrapper</CODE> class that you can find in the <CODE>cstool</CODE>
library. <CODE>csColliderWrapper</CODE> is a subclass of <CODE>csObject</CODE> which
means that you can attach this object to any other <CODE>csObject</CODE>.
<CODE>csColliderWrapper</CODE> additionally holds a pointer to an <CODE>iCollider</CODE>.
This means that you can create a <CODE>csColliderWrapper</CODE> to hold your
<CODE>iCollider</CODE> for some mesh object and then you can attach
that <CODE>csColliderWrapper</CODE> to the mesh object itself. To do this
use the following code instead of the <CODE>InitCollider()</CODE> routine
above:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>csColliderWrapper* colwrap =
  new csColliderWrapper(mymesh-&#62;QueryObject(), cd_sys, 

bool MyGame::InitCollider (iMeshWrapper* mesh)
{
  iPolygonMesh* polmesh = SCF_QUERY_INTERFACE (mesh-&#62;GetMeshObject (),
  	iPolygonMesh);
  if (polmesh)
  {
    new csColliderWrapper (mesh-&#62;QueryObject (), cd_sys, polmesh);
    polmesh-&#62;DecRef ();
    return true;
  }
  else
    return false;
}
</pre></td></tr></table></P><P>

This example creates a new instance of <CODE>csColliderWrapper</CODE> which
is automatically stored with the <CODE>iObject</CODE> that belongs
with the given mesh. So there is no need to store it otherwise. Later
on you can retrieve the collider for some mesh by doing:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>csColliderWrapper* colwrap = csColliderWrapper::GetColliderWrapper (
	mesh-&#62;QueryObject ());
iCollider* collider = colwrap-&#62;GetCollider ();
</pre></td></tr></table></P><P>

<A NAME="SEC229"></A>
<H4> The Player Collider </H4>
<!--docid::SEC229::-->
<P>

Depending on the game your player might have a representation of
geometry or not. If it doesn't you will have to make your own version
of `<SAMP>iPolygonMesh</SAMP>' to create a collider for the player. Even if
your player has geometry (i.e. a 3D sprite) it is sometimes still preferable
to create your own special geometry for the player. The reason is
gravity. When you would just use one collider for the player you can have
problems moving around because the player would not be able to jump over
even the tiniest elevation in height. Sometimes the edge between adjacent
polygons can even cause the player to collide with that other polygon due
to numerical inprecision. To solve this problem it is best to make one
collider that is used for gravity only and another collider that is used
to test if you can move around. The gravity collider will be used only
to test if the player can go downwards or upwards. To avoid not being able
to go over small height elevations, the player collider should float slightly
above the ground.
</P><P>

The best way to make the gravity collider is to make your own implementation
of `<SAMP>iPolygonMesh</SAMP>'. This is very efficient. To keep the returned
collider I recommend storing them somewhere in the player class or else the
main game class.
</P><P>

<A NAME="SEC230"></A>
<H4> Doing Collision Detection </H4>
<!--docid::SEC230::-->
<P>

When everything is set up it is time to do collision detection. To test
for collisions you use the <CODE>Collide</CODE> function in `<SAMP>iCollideSystem</SAMP>'.
This will test the collisions between two colliders. The result of this
will be true or false and in addition the collide system will keep a list
of all triangle pairs for the hits. Those triangle pairs can be used to
decide what to do on collision (i.e. slide on a wall for example).
</P><P>

Because collision detection works on two objects at a time it is a good
idea to have some system on top of the collision detection system that
detects when it is useful to do collision detection. You can use a bounding
sphere for that. Also you should only do collision detection if the object
moves.
</P><P>

<A NAME="SEC231"></A>
<H4> Limitation of RAPID </H4>
<!--docid::SEC231::-->
<P>

The current RAPID collision detection implementation has one
important limitation. It assumes that the transform from object to world
space will not change the size of the object. i.e. you cannot scale the
object using the object to world transformation (which is kept in the
`<SAMP>iMovable</SAMP>') and expect collision detection to be ok. The only way
aroud this limitation is to use <CODE>HardTransform()</CODE> to transform
the object space vertices itself. But this can of course not be used
dynamically as you would have to recalculate the collider every time
the object changes.
</P><P>

<A NAME="SEC232"></A>
<H4> Include Files </H4>
<!--docid::SEC232::-->
<P>

The include files useful for this section are:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>#include "iutil/object.h"
#include "iutil/plugin.h"
#include "ivaria/collider.h"
#include "ivaria/polymesh.h"
#include "iengine/mesh.h"
#include "cstool/collider.h"
</pre></td></tr></table></P><P>

<A NAME="HOWTO Mesh LightAnim"></A>
<HR SIZE=1>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_116.html#SEC225"> &lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_118.html#SEC233"> &gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_108.html#SEC209"> &lt;&lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_116.html#SEC225"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_128.html#SEC290"> &gt;&gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<BR>  
<FONT SIZE="-1">
This document was generated

using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
"><I>texi2html</I></A>

</BODY>
</HTML>