~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/game/bg_slidemove.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert
  • Date: 2007-01-20 12:28:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070120122809-2yza5ojt7nqiyiam
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
===========================================================================
 
3
Copyright (C) 1999-2005 Id Software, Inc.
 
4
 
 
5
This file is part of Quake III Arena source code.
 
6
 
 
7
Quake III Arena source code is free software; you can redistribute it
 
8
and/or modify it under the terms of the GNU General Public License as
 
9
published by the Free Software Foundation; either version 2 of the License,
 
10
or (at your option) any later version.
 
11
 
 
12
Quake III Arena source code is distributed in the hope that it will be
 
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with Quake III Arena source code; if not, write to the Free Software
 
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
===========================================================================
 
21
*/
 
22
//
 
23
// bg_slidemove.c -- part of bg_pmove functionality
 
24
 
 
25
#include "../qcommon/q_shared.h"
 
26
#include "bg_public.h"
 
27
#include "bg_local.h"
 
28
 
 
29
/*
 
30
 
 
31
input: origin, velocity, bounds, groundPlane, trace function
 
32
 
 
33
output: origin, velocity, impacts, stairup boolean
 
34
 
 
35
*/
 
36
 
 
37
/*
 
38
==================
 
39
PM_SlideMove
 
40
 
 
41
Returns qtrue if the velocity was clipped in some way
 
42
==================
 
43
*/
 
44
#define MAX_CLIP_PLANES 5
 
45
qboolean        PM_SlideMove( qboolean gravity ) {
 
46
        int                     bumpcount, numbumps;
 
47
        vec3_t          dir;
 
48
        float           d;
 
49
        int                     numplanes;
 
50
        vec3_t          planes[MAX_CLIP_PLANES];
 
51
        vec3_t          primal_velocity;
 
52
        vec3_t          clipVelocity;
 
53
        int                     i, j, k;
 
54
        trace_t trace;
 
55
        vec3_t          end;
 
56
        float           time_left;
 
57
        float           into;
 
58
        vec3_t          endVelocity;
 
59
        vec3_t          endClipVelocity;
 
60
        
 
61
        numbumps = 4;
 
62
 
 
63
        VectorCopy (pm->ps->velocity, primal_velocity);
 
64
 
 
65
        if ( gravity ) {
 
66
                VectorCopy( pm->ps->velocity, endVelocity );
 
67
                endVelocity[2] -= pm->ps->gravity * pml.frametime;
 
68
                pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
 
69
                primal_velocity[2] = endVelocity[2];
 
70
                if ( pml.groundPlane ) {
 
71
                        // slide along the ground plane
 
72
                        PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
 
73
                                pm->ps->velocity, OVERCLIP );
 
74
                }
 
75
        }
 
76
 
 
77
        time_left = pml.frametime;
 
78
 
 
79
        // never turn against the ground plane
 
80
        if ( pml.groundPlane ) {
 
81
                numplanes = 1;
 
82
                VectorCopy( pml.groundTrace.plane.normal, planes[0] );
 
83
        } else {
 
84
                numplanes = 0;
 
85
        }
 
86
 
 
87
        // never turn against original velocity
 
88
        VectorNormalize2( pm->ps->velocity, planes[numplanes] );
 
89
        numplanes++;
 
90
 
 
91
        for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ ) {
 
92
 
 
93
                // calculate position we are trying to move to
 
94
                VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
 
95
 
 
96
                // see if we can make it there
 
97
                pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
 
98
 
 
99
                if (trace.allsolid) {
 
100
                        // entity is completely trapped in another solid
 
101
                        pm->ps->velocity[2] = 0;        // don't build up falling damage, but allow sideways acceleration
 
102
                        return qtrue;
 
103
                }
 
104
 
 
105
                if (trace.fraction > 0) {
 
106
                        // actually covered some distance
 
107
                        VectorCopy (trace.endpos, pm->ps->origin);
 
108
                }
 
109
 
 
110
                if (trace.fraction == 1) {
 
111
                         break;         // moved the entire distance
 
112
                }
 
113
 
 
114
                // save entity for contact
 
115
                PM_AddTouchEnt( trace.entityNum );
 
116
 
 
117
                time_left -= time_left * trace.fraction;
 
118
 
 
119
                if (numplanes >= MAX_CLIP_PLANES) {
 
120
                        // this shouldn't really happen
 
121
                        VectorClear( pm->ps->velocity );
 
122
                        return qtrue;
 
123
                }
 
124
 
 
125
                //
 
126
                // if this is the same plane we hit before, nudge velocity
 
127
                // out along it, which fixes some epsilon issues with
 
128
                // non-axial planes
 
129
                //
 
130
                for ( i = 0 ; i < numplanes ; i++ ) {
 
131
                        if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) {
 
132
                                VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
 
133
                                break;
 
134
                        }
 
135
                }
 
136
                if ( i < numplanes ) {
 
137
                        continue;
 
138
                }
 
139
                VectorCopy (trace.plane.normal, planes[numplanes]);
 
140
                numplanes++;
 
141
 
 
142
                //
 
143
                // modify velocity so it parallels all of the clip planes
 
144
                //
 
145
 
 
146
                // find a plane that it enters
 
147
                for ( i = 0 ; i < numplanes ; i++ ) {
 
148
                        into = DotProduct( pm->ps->velocity, planes[i] );
 
149
                        if ( into >= 0.1 ) {
 
150
                                continue;               // move doesn't interact with the plane
 
151
                        }
 
152
 
 
153
                        // see how hard we are hitting things
 
154
                        if ( -into > pml.impactSpeed ) {
 
155
                                pml.impactSpeed = -into;
 
156
                        }
 
157
 
 
158
                        // slide along the plane
 
159
                        PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
 
160
 
 
161
                        // slide along the plane
 
162
                        PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );
 
163
 
 
164
                        // see if there is a second plane that the new move enters
 
165
                        for ( j = 0 ; j < numplanes ; j++ ) {
 
166
                                if ( j == i ) {
 
167
                                        continue;
 
168
                                }
 
169
                                if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) {
 
170
                                        continue;               // move doesn't interact with the plane
 
171
                                }
 
172
 
 
173
                                // try clipping the move to the plane
 
174
                                PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
 
175
                                PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
 
176
 
 
177
                                // see if it goes back into the first clip plane
 
178
                                if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) {
 
179
                                        continue;
 
180
                                }
 
181
 
 
182
                                // slide the original velocity along the crease
 
183
                                CrossProduct (planes[i], planes[j], dir);
 
184
                                VectorNormalize( dir );
 
185
                                d = DotProduct( dir, pm->ps->velocity );
 
186
                                VectorScale( dir, d, clipVelocity );
 
187
 
 
188
                                CrossProduct (planes[i], planes[j], dir);
 
189
                                VectorNormalize( dir );
 
190
                                d = DotProduct( dir, endVelocity );
 
191
                                VectorScale( dir, d, endClipVelocity );
 
192
 
 
193
                                // see if there is a third plane the the new move enters
 
194
                                for ( k = 0 ; k < numplanes ; k++ ) {
 
195
                                        if ( k == i || k == j ) {
 
196
                                                continue;
 
197
                                        }
 
198
                                        if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) {
 
199
                                                continue;               // move doesn't interact with the plane
 
200
                                        }
 
201
 
 
202
                                        // stop dead at a tripple plane interaction
 
203
                                        VectorClear( pm->ps->velocity );
 
204
                                        return qtrue;
 
205
                                }
 
206
                        }
 
207
 
 
208
                        // if we have fixed all interactions, try another move
 
209
                        VectorCopy( clipVelocity, pm->ps->velocity );
 
210
                        VectorCopy( endClipVelocity, endVelocity );
 
211
                        break;
 
212
                }
 
213
        }
 
214
 
 
215
        if ( gravity ) {
 
216
                VectorCopy( endVelocity, pm->ps->velocity );
 
217
        }
 
218
 
 
219
        // don't change velocity if in a timer (FIXME: is this correct?)
 
220
        if ( pm->ps->pm_time ) {
 
221
                VectorCopy( primal_velocity, pm->ps->velocity );
 
222
        }
 
223
 
 
224
        return ( bumpcount != 0 );
 
225
}
 
226
 
 
227
/*
 
228
==================
 
229
PM_StepSlideMove
 
230
 
 
231
==================
 
232
*/
 
233
void PM_StepSlideMove( qboolean gravity ) {
 
234
        vec3_t          start_o, start_v;
 
235
        vec3_t          down_o, down_v;
 
236
        trace_t         trace;
 
237
//      float           down_dist, up_dist;
 
238
//      vec3_t          delta, delta2;
 
239
        vec3_t          up, down;
 
240
        float           stepSize;
 
241
 
 
242
        VectorCopy (pm->ps->origin, start_o);
 
243
        VectorCopy (pm->ps->velocity, start_v);
 
244
 
 
245
        if ( PM_SlideMove( gravity ) == 0 ) {
 
246
                return;         // we got exactly where we wanted to go first try       
 
247
        }
 
248
 
 
249
        VectorCopy(start_o, down);
 
250
        down[2] -= STEPSIZE;
 
251
        pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
 
252
        VectorSet(up, 0, 0, 1);
 
253
        // never step up when you still have up velocity
 
254
        if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 ||
 
255
                                                                                DotProduct(trace.plane.normal, up) < 0.7)) {
 
256
                return;
 
257
        }
 
258
 
 
259
        VectorCopy (pm->ps->origin, down_o);
 
260
        VectorCopy (pm->ps->velocity, down_v);
 
261
 
 
262
        VectorCopy (start_o, up);
 
263
        up[2] += STEPSIZE;
 
264
 
 
265
        // test the player position if they were a stepheight higher
 
266
        pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask);
 
267
        if ( trace.allsolid ) {
 
268
                if ( pm->debugLevel ) {
 
269
                        Com_Printf("%i:bend can't step\n", c_pmove);
 
270
                }
 
271
                return;         // can't step up
 
272
        }
 
273
 
 
274
        stepSize = trace.endpos[2] - start_o[2];
 
275
        // try slidemove from this position
 
276
        VectorCopy (trace.endpos, pm->ps->origin);
 
277
        VectorCopy (start_v, pm->ps->velocity);
 
278
 
 
279
        PM_SlideMove( gravity );
 
280
 
 
281
        // push down the final amount
 
282
        VectorCopy (pm->ps->origin, down);
 
283
        down[2] -= stepSize;
 
284
        pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
 
285
        if ( !trace.allsolid ) {
 
286
                VectorCopy (trace.endpos, pm->ps->origin);
 
287
        }
 
288
        if ( trace.fraction < 1.0 ) {
 
289
                PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
 
290
        }
 
291
 
 
292
#if 0
 
293
        // if the down trace can trace back to the original position directly, don't step
 
294
        pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask);
 
295
        if ( trace.fraction == 1.0 ) {
 
296
                // use the original move
 
297
                VectorCopy (down_o, pm->ps->origin);
 
298
                VectorCopy (down_v, pm->ps->velocity);
 
299
                if ( pm->debugLevel ) {
 
300
                        Com_Printf("%i:bend\n", c_pmove);
 
301
                }
 
302
        } else 
 
303
#endif
 
304
        {
 
305
                // use the step move
 
306
                float   delta;
 
307
 
 
308
                delta = pm->ps->origin[2] - start_o[2];
 
309
                if ( delta > 2 ) {
 
310
                        if ( delta < 7 ) {
 
311
                                PM_AddEvent( EV_STEP_4 );
 
312
                        } else if ( delta < 11 ) {
 
313
                                PM_AddEvent( EV_STEP_8 );
 
314
                        } else if ( delta < 15 ) {
 
315
                                PM_AddEvent( EV_STEP_12 );
 
316
                        } else {
 
317
                                PM_AddEvent( EV_STEP_16 );
 
318
                        }
 
319
                }
 
320
                if ( pm->debugLevel ) {
 
321
                        Com_Printf("%i:stepped\n", c_pmove);
 
322
                }
 
323
        }
 
324
}
 
325