~ubuntu-branches/ubuntu/hardy/openarena/hardy-backports

« back to all changes in this revision

Viewing changes to code/renderer/tr_surface.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
// tr_surf.c
 
23
#include "tr_local.h"
 
24
#if idppc_altivec && !defined(MACOS_X)
 
25
#include <altivec.h>
 
26
#endif
 
27
 
 
28
/*
 
29
 
 
30
  THIS ENTIRE FILE IS BACK END
 
31
 
 
32
backEnd.currentEntity will be valid.
 
33
 
 
34
Tess_Begin has already been called for the surface's shader.
 
35
 
 
36
The modelview matrix will be set.
 
37
 
 
38
It is safe to actually issue drawing commands here if you don't want to
 
39
use the shader system.
 
40
*/
 
41
 
 
42
 
 
43
//============================================================================
 
44
 
 
45
 
 
46
/*
 
47
==============
 
48
RB_CheckOverflow
 
49
==============
 
50
*/
 
51
void RB_CheckOverflow( int verts, int indexes ) {
 
52
        if (tess.numVertexes + verts < SHADER_MAX_VERTEXES
 
53
                && tess.numIndexes + indexes < SHADER_MAX_INDEXES) {
 
54
                return;
 
55
        }
 
56
 
 
57
        RB_EndSurface();
 
58
 
 
59
        if ( verts >= SHADER_MAX_VERTEXES ) {
 
60
                ri.Error(ERR_DROP, "RB_CheckOverflow: verts > MAX (%d > %d)", verts, SHADER_MAX_VERTEXES );
 
61
        }
 
62
        if ( indexes >= SHADER_MAX_INDEXES ) {
 
63
                ri.Error(ERR_DROP, "RB_CheckOverflow: indices > MAX (%d > %d)", indexes, SHADER_MAX_INDEXES );
 
64
        }
 
65
 
 
66
        RB_BeginSurface(tess.shader, tess.fogNum );
 
67
}
 
68
 
 
69
 
 
70
/*
 
71
==============
 
72
RB_AddQuadStampExt
 
73
==============
 
74
*/
 
75
void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2 ) {
 
76
        vec3_t          normal;
 
77
        int                     ndx;
 
78
 
 
79
        RB_CHECKOVERFLOW( 4, 6 );
 
80
 
 
81
        ndx = tess.numVertexes;
 
82
 
 
83
        // triangle indexes for a simple quad
 
84
        tess.indexes[ tess.numIndexes ] = ndx;
 
85
        tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
 
86
        tess.indexes[ tess.numIndexes + 2 ] = ndx + 3;
 
87
 
 
88
        tess.indexes[ tess.numIndexes + 3 ] = ndx + 3;
 
89
        tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
 
90
        tess.indexes[ tess.numIndexes + 5 ] = ndx + 2;
 
91
 
 
92
        tess.xyz[ndx][0] = origin[0] + left[0] + up[0];
 
93
        tess.xyz[ndx][1] = origin[1] + left[1] + up[1];
 
94
        tess.xyz[ndx][2] = origin[2] + left[2] + up[2];
 
95
 
 
96
        tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0];
 
97
        tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1];
 
98
        tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2];
 
99
 
 
100
        tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0];
 
101
        tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1];
 
102
        tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2];
 
103
 
 
104
        tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0];
 
105
        tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1];
 
106
        tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2];
 
107
 
 
108
 
 
109
        // constant normal all the way around
 
110
        VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );
 
111
 
 
112
        tess.normal[ndx][0] = tess.normal[ndx+1][0] = tess.normal[ndx+2][0] = tess.normal[ndx+3][0] = normal[0];
 
113
        tess.normal[ndx][1] = tess.normal[ndx+1][1] = tess.normal[ndx+2][1] = tess.normal[ndx+3][1] = normal[1];
 
114
        tess.normal[ndx][2] = tess.normal[ndx+1][2] = tess.normal[ndx+2][2] = tess.normal[ndx+3][2] = normal[2];
 
115
        
 
116
        // standard square texture coordinates
 
117
        tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1;
 
118
        tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1;
 
119
 
 
120
        tess.texCoords[ndx+1][0][0] = tess.texCoords[ndx+1][1][0] = s2;
 
121
        tess.texCoords[ndx+1][0][1] = tess.texCoords[ndx+1][1][1] = t1;
 
122
 
 
123
        tess.texCoords[ndx+2][0][0] = tess.texCoords[ndx+2][1][0] = s2;
 
124
        tess.texCoords[ndx+2][0][1] = tess.texCoords[ndx+2][1][1] = t2;
 
125
 
 
126
        tess.texCoords[ndx+3][0][0] = tess.texCoords[ndx+3][1][0] = s1;
 
127
        tess.texCoords[ndx+3][0][1] = tess.texCoords[ndx+3][1][1] = t2;
 
128
 
 
129
        // constant color all the way around
 
130
        // should this be identity and let the shader specify from entity?
 
131
        * ( unsigned int * ) &tess.vertexColors[ndx] = 
 
132
        * ( unsigned int * ) &tess.vertexColors[ndx+1] = 
 
133
        * ( unsigned int * ) &tess.vertexColors[ndx+2] = 
 
134
        * ( unsigned int * ) &tess.vertexColors[ndx+3] = 
 
135
                * ( unsigned int * )color;
 
136
 
 
137
 
 
138
        tess.numVertexes += 4;
 
139
        tess.numIndexes += 6;
 
140
}
 
141
 
 
142
/*
 
143
==============
 
144
RB_AddQuadStamp
 
145
==============
 
146
*/
 
147
void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color ) {
 
148
        RB_AddQuadStampExt( origin, left, up, color, 0, 0, 1, 1 );
 
149
}
 
150
 
 
151
/*
 
152
==============
 
153
RB_SurfaceSprite
 
154
==============
 
155
*/
 
156
static void RB_SurfaceSprite( void ) {
 
157
        vec3_t          left, up;
 
158
        float           radius;
 
159
 
 
160
        // calculate the xyz locations for the four corners
 
161
        radius = backEnd.currentEntity->e.radius;
 
162
        if ( backEnd.currentEntity->e.rotation == 0 ) {
 
163
                VectorScale( backEnd.viewParms.or.axis[1], radius, left );
 
164
                VectorScale( backEnd.viewParms.or.axis[2], radius, up );
 
165
        } else {
 
166
                float   s, c;
 
167
                float   ang;
 
168
                
 
169
                ang = M_PI * backEnd.currentEntity->e.rotation / 180;
 
170
                s = sin( ang );
 
171
                c = cos( ang );
 
172
 
 
173
                VectorScale( backEnd.viewParms.or.axis[1], c * radius, left );
 
174
                VectorMA( left, -s * radius, backEnd.viewParms.or.axis[2], left );
 
175
 
 
176
                VectorScale( backEnd.viewParms.or.axis[2], c * radius, up );
 
177
                VectorMA( up, s * radius, backEnd.viewParms.or.axis[1], up );
 
178
        }
 
179
        if ( backEnd.viewParms.isMirror ) {
 
180
                VectorSubtract( vec3_origin, left, left );
 
181
        }
 
182
 
 
183
        RB_AddQuadStamp( backEnd.currentEntity->e.origin, left, up, backEnd.currentEntity->e.shaderRGBA );
 
184
}
 
185
 
 
186
 
 
187
/*
 
188
=============
 
189
RB_SurfacePolychain
 
190
=============
 
191
*/
 
192
void RB_SurfacePolychain( srfPoly_t *p ) {
 
193
        int             i;
 
194
        int             numv;
 
195
 
 
196
        RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) );
 
197
 
 
198
        // fan triangles into the tess array
 
199
        numv = tess.numVertexes;
 
200
        for ( i = 0; i < p->numVerts; i++ ) {
 
201
                VectorCopy( p->verts[i].xyz, tess.xyz[numv] );
 
202
                tess.texCoords[numv][0][0] = p->verts[i].st[0];
 
203
                tess.texCoords[numv][0][1] = p->verts[i].st[1];
 
204
                *(int *)&tess.vertexColors[numv] = *(int *)p->verts[ i ].modulate;
 
205
 
 
206
                numv++;
 
207
        }
 
208
 
 
209
        // generate fan indexes into the tess array
 
210
        for ( i = 0; i < p->numVerts-2; i++ ) {
 
211
                tess.indexes[tess.numIndexes + 0] = tess.numVertexes;
 
212
                tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1;
 
213
                tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2;
 
214
                tess.numIndexes += 3;
 
215
        }
 
216
 
 
217
        tess.numVertexes = numv;
 
218
}
 
219
 
 
220
 
 
221
/*
 
222
=============
 
223
RB_SurfaceTriangles
 
224
=============
 
225
*/
 
226
void RB_SurfaceTriangles( srfTriangles_t *srf ) {
 
227
        int                     i;
 
228
        drawVert_t      *dv;
 
229
        float           *xyz, *normal, *texCoords;
 
230
        byte            *color;
 
231
        int                     dlightBits;
 
232
        qboolean        needsNormal;
 
233
 
 
234
        dlightBits = srf->dlightBits[backEnd.smpFrame];
 
235
        tess.dlightBits |= dlightBits;
 
236
 
 
237
        RB_CHECKOVERFLOW( srf->numVerts, srf->numIndexes );
 
238
 
 
239
        for ( i = 0 ; i < srf->numIndexes ; i += 3 ) {
 
240
                tess.indexes[ tess.numIndexes + i + 0 ] = tess.numVertexes + srf->indexes[ i + 0 ];
 
241
                tess.indexes[ tess.numIndexes + i + 1 ] = tess.numVertexes + srf->indexes[ i + 1 ];
 
242
                tess.indexes[ tess.numIndexes + i + 2 ] = tess.numVertexes + srf->indexes[ i + 2 ];
 
243
        }
 
244
        tess.numIndexes += srf->numIndexes;
 
245
 
 
246
        dv = srf->verts;
 
247
        xyz = tess.xyz[ tess.numVertexes ];
 
248
        normal = tess.normal[ tess.numVertexes ];
 
249
        texCoords = tess.texCoords[ tess.numVertexes ][0];
 
250
        color = tess.vertexColors[ tess.numVertexes ];
 
251
        needsNormal = tess.shader->needsNormal;
 
252
 
 
253
        for ( i = 0 ; i < srf->numVerts ; i++, dv++, xyz += 4, normal += 4, texCoords += 4, color += 4 ) {
 
254
                xyz[0] = dv->xyz[0];
 
255
                xyz[1] = dv->xyz[1];
 
256
                xyz[2] = dv->xyz[2];
 
257
 
 
258
                if ( needsNormal ) {
 
259
                        normal[0] = dv->normal[0];
 
260
                        normal[1] = dv->normal[1];
 
261
                        normal[2] = dv->normal[2];
 
262
                }
 
263
 
 
264
                texCoords[0] = dv->st[0];
 
265
                texCoords[1] = dv->st[1];
 
266
 
 
267
                texCoords[2] = dv->lightmap[0];
 
268
                texCoords[3] = dv->lightmap[1];
 
269
 
 
270
                *(int *)color = *(int *)dv->color;
 
271
        }
 
272
 
 
273
        for ( i = 0 ; i < srf->numVerts ; i++ ) {
 
274
                tess.vertexDlightBits[ tess.numVertexes + i] = dlightBits;
 
275
        }
 
276
 
 
277
        tess.numVertexes += srf->numVerts;
 
278
}
 
279
 
 
280
 
 
281
 
 
282
/*
 
283
==============
 
284
RB_SurfaceBeam
 
285
==============
 
286
*/
 
287
void RB_SurfaceBeam( void ) 
 
288
{
 
289
#define NUM_BEAM_SEGS 6
 
290
        refEntity_t *e;
 
291
        int     i;
 
292
        vec3_t perpvec;
 
293
        vec3_t direction, normalized_direction;
 
294
        vec3_t  start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
 
295
        vec3_t oldorigin, origin;
 
296
 
 
297
        e = &backEnd.currentEntity->e;
 
298
 
 
299
        oldorigin[0] = e->oldorigin[0];
 
300
        oldorigin[1] = e->oldorigin[1];
 
301
        oldorigin[2] = e->oldorigin[2];
 
302
 
 
303
        origin[0] = e->origin[0];
 
304
        origin[1] = e->origin[1];
 
305
        origin[2] = e->origin[2];
 
306
 
 
307
        normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
 
308
        normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
 
309
        normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
 
310
 
 
311
        if ( VectorNormalize( normalized_direction ) == 0 )
 
312
                return;
 
313
 
 
314
        PerpendicularVector( perpvec, normalized_direction );
 
315
 
 
316
        VectorScale( perpvec, 4, perpvec );
 
317
 
 
318
        for ( i = 0; i < NUM_BEAM_SEGS ; i++ )
 
319
        {
 
320
                RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
 
321
//              VectorAdd( start_points[i], origin, start_points[i] );
 
322
                VectorAdd( start_points[i], direction, end_points[i] );
 
323
        }
 
324
 
 
325
        GL_Bind( tr.whiteImage );
 
326
 
 
327
        GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
 
328
 
 
329
        qglColor3f( 1, 0, 0 );
 
330
 
 
331
        qglBegin( GL_TRIANGLE_STRIP );
 
332
        for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
 
333
                qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] );
 
334
                qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] );
 
335
        }
 
336
        qglEnd();
 
337
}
 
338
 
 
339
//================================================================================
 
340
 
 
341
static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth )
 
342
{
 
343
        float           spanWidth2;
 
344
        int                     vbase;
 
345
        float           t = len / 256.0f;
 
346
 
 
347
        vbase = tess.numVertexes;
 
348
 
 
349
        spanWidth2 = -spanWidth;
 
350
 
 
351
        // FIXME: use quad stamp?
 
352
        VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] );
 
353
        tess.texCoords[tess.numVertexes][0][0] = 0;
 
354
        tess.texCoords[tess.numVertexes][0][1] = 0;
 
355
        tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25;
 
356
        tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25;
 
357
        tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25;
 
358
        tess.numVertexes++;
 
359
 
 
360
        VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] );
 
361
        tess.texCoords[tess.numVertexes][0][0] = 0;
 
362
        tess.texCoords[tess.numVertexes][0][1] = 1;
 
363
        tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
 
364
        tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
 
365
        tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
 
366
        tess.numVertexes++;
 
367
 
 
368
        VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] );
 
369
 
 
370
        tess.texCoords[tess.numVertexes][0][0] = t;
 
371
        tess.texCoords[tess.numVertexes][0][1] = 0;
 
372
        tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
 
373
        tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
 
374
        tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
 
375
        tess.numVertexes++;
 
376
 
 
377
        VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] );
 
378
        tess.texCoords[tess.numVertexes][0][0] = t;
 
379
        tess.texCoords[tess.numVertexes][0][1] = 1;
 
380
        tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
 
381
        tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
 
382
        tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
 
383
        tess.numVertexes++;
 
384
 
 
385
        tess.indexes[tess.numIndexes++] = vbase;
 
386
        tess.indexes[tess.numIndexes++] = vbase + 1;
 
387
        tess.indexes[tess.numIndexes++] = vbase + 2;
 
388
 
 
389
        tess.indexes[tess.numIndexes++] = vbase + 2;
 
390
        tess.indexes[tess.numIndexes++] = vbase + 1;
 
391
        tess.indexes[tess.numIndexes++] = vbase + 3;
 
392
}
 
393
 
 
394
static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up )
 
395
{
 
396
        int i;
 
397
        vec3_t  pos[4];
 
398
        vec3_t  v;
 
399
        int             spanWidth = r_railWidth->integer;
 
400
        float c, s;
 
401
        float           scale;
 
402
 
 
403
        if ( numSegs > 1 )
 
404
                numSegs--;
 
405
        if ( !numSegs )
 
406
                return;
 
407
 
 
408
        scale = 0.25;
 
409
 
 
410
        for ( i = 0; i < 4; i++ )
 
411
        {
 
412
                c = cos( DEG2RAD( 45 + i * 90 ) );
 
413
                s = sin( DEG2RAD( 45 + i * 90 ) );
 
414
                v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth;
 
415
                v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth;
 
416
                v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth;
 
417
                VectorAdd( start, v, pos[i] );
 
418
 
 
419
                if ( numSegs > 1 )
 
420
                {
 
421
                        // offset by 1 segment if we're doing a long distance shot
 
422
                        VectorAdd( pos[i], dir, pos[i] );
 
423
                }
 
424
        }
 
425
 
 
426
        for ( i = 0; i < numSegs; i++ )
 
427
        {
 
428
                int j;
 
429
 
 
430
                RB_CHECKOVERFLOW( 4, 6 );
 
431
 
 
432
                for ( j = 0; j < 4; j++ )
 
433
                {
 
434
                        VectorCopy( pos[j], tess.xyz[tess.numVertexes] );
 
435
                        tess.texCoords[tess.numVertexes][0][0] = ( j < 2 );
 
436
                        tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 );
 
437
                        tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
 
438
                        tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
 
439
                        tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
 
440
                        tess.numVertexes++;
 
441
 
 
442
                        VectorAdd( pos[j], dir, pos[j] );
 
443
                }
 
444
 
 
445
                tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0;
 
446
                tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
 
447
                tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
 
448
                tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
 
449
                tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
 
450
                tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2;
 
451
        }
 
452
}
 
453
 
 
454
/*
 
455
** RB_SurfaceRailRinges
 
456
*/
 
457
void RB_SurfaceRailRings( void ) {
 
458
        refEntity_t *e;
 
459
        int                     numSegs;
 
460
        int                     len;
 
461
        vec3_t          vec;
 
462
        vec3_t          right, up;
 
463
        vec3_t          start, end;
 
464
 
 
465
        e = &backEnd.currentEntity->e;
 
466
 
 
467
        VectorCopy( e->oldorigin, start );
 
468
        VectorCopy( e->origin, end );
 
469
 
 
470
        // compute variables
 
471
        VectorSubtract( end, start, vec );
 
472
        len = VectorNormalize( vec );
 
473
        MakeNormalVectors( vec, right, up );
 
474
        numSegs = ( len ) / r_railSegmentLength->value;
 
475
        if ( numSegs <= 0 ) {
 
476
                numSegs = 1;
 
477
        }
 
478
 
 
479
        VectorScale( vec, r_railSegmentLength->value, vec );
 
480
 
 
481
        DoRailDiscs( numSegs, start, vec, right, up );
 
482
}
 
483
 
 
484
/*
 
485
** RB_SurfaceRailCore
 
486
*/
 
487
void RB_SurfaceRailCore( void ) {
 
488
        refEntity_t *e;
 
489
        int                     len;
 
490
        vec3_t          right;
 
491
        vec3_t          vec;
 
492
        vec3_t          start, end;
 
493
        vec3_t          v1, v2;
 
494
 
 
495
        e = &backEnd.currentEntity->e;
 
496
 
 
497
        VectorCopy( e->oldorigin, start );
 
498
        VectorCopy( e->origin, end );
 
499
 
 
500
        VectorSubtract( end, start, vec );
 
501
        len = VectorNormalize( vec );
 
502
 
 
503
        // compute side vector
 
504
        VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
 
505
        VectorNormalize( v1 );
 
506
        VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
 
507
        VectorNormalize( v2 );
 
508
        CrossProduct( v1, v2, right );
 
509
        VectorNormalize( right );
 
510
 
 
511
        DoRailCore( start, end, right, len, r_railCoreWidth->integer );
 
512
}
 
513
 
 
514
/*
 
515
** RB_SurfaceLightningBolt
 
516
*/
 
517
void RB_SurfaceLightningBolt( void ) {
 
518
        refEntity_t *e;
 
519
        int                     len;
 
520
        vec3_t          right;
 
521
        vec3_t          vec;
 
522
        vec3_t          start, end;
 
523
        vec3_t          v1, v2;
 
524
        int                     i;
 
525
 
 
526
        e = &backEnd.currentEntity->e;
 
527
 
 
528
        VectorCopy( e->oldorigin, end );
 
529
        VectorCopy( e->origin, start );
 
530
 
 
531
        // compute variables
 
532
        VectorSubtract( end, start, vec );
 
533
        len = VectorNormalize( vec );
 
534
 
 
535
        // compute side vector
 
536
        VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
 
537
        VectorNormalize( v1 );
 
538
        VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
 
539
        VectorNormalize( v2 );
 
540
        CrossProduct( v1, v2, right );
 
541
        VectorNormalize( right );
 
542
 
 
543
        for ( i = 0 ; i < 4 ; i++ ) {
 
544
                vec3_t  temp;
 
545
 
 
546
                DoRailCore( start, end, right, len, 8 );
 
547
                RotatePointAroundVector( temp, vec, right, 45 );
 
548
                VectorCopy( temp, right );
 
549
        }
 
550
}
 
551
 
 
552
/*
 
553
** VectorArrayNormalize
 
554
*
 
555
* The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
 
556
* This means that we don't have to worry about zero length or enormously long vectors.
 
557
*/
 
558
static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
 
559
{
 
560
//    assert(count);
 
561
        
 
562
#if idppc
 
563
    {
 
564
        register float half = 0.5;
 
565
        register float one  = 1.0;
 
566
        float *components = (float *)normals;
 
567
        
 
568
        // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
 
569
        // runs *much* faster than calling sqrt().  We'll use a single Newton-Raphson
 
570
        // refinement step to get a little more precision.  This seems to yeild results
 
571
        // that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5).
 
572
        // (That is, for the given input range of about 0.6 to 2.0).
 
573
        do {
 
574
            float x, y, z;
 
575
            float B, y0, y1;
 
576
            
 
577
            x = components[0];
 
578
            y = components[1];
 
579
            z = components[2];
 
580
            components += 4;
 
581
            B = x*x + y*y + z*z;
 
582
 
 
583
#ifdef __GNUC__            
 
584
            asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
 
585
#else
 
586
                        y0 = __frsqrte(B);
 
587
#endif
 
588
            y1 = y0 + half*y0*(one - B*y0*y0);
 
589
 
 
590
            x = x * y1;
 
591
            y = y * y1;
 
592
            components[-4] = x;
 
593
            z = z * y1;
 
594
            components[-3] = y;
 
595
            components[-2] = z;
 
596
        } while(count--);
 
597
    }
 
598
#else // No assembly version for this architecture, or C_ONLY defined
 
599
        // given the input, it's safe to call VectorNormalizeFast
 
600
    while (count--) {
 
601
        VectorNormalizeFast(normals[0]);
 
602
        normals++;
 
603
    }
 
604
#endif
 
605
 
 
606
}
 
607
 
 
608
 
 
609
 
 
610
/*
 
611
** LerpMeshVertexes
 
612
*/
 
613
#if idppc_altivec
 
614
static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
 
615
{
 
616
        short   *oldXyz, *newXyz, *oldNormals, *newNormals;
 
617
        float   *outXyz, *outNormal;
 
618
        float   oldXyzScale ALIGN(16);
 
619
        float   newXyzScale ALIGN(16);
 
620
        float   oldNormalScale ALIGN(16);
 
621
        float newNormalScale ALIGN(16);
 
622
        int             vertNum;
 
623
        unsigned lat, lng;
 
624
        int             numVerts;
 
625
 
 
626
        outXyz = tess.xyz[tess.numVertexes];
 
627
        outNormal = tess.normal[tess.numVertexes];
 
628
 
 
629
        newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
 
630
                + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
 
631
        newNormals = newXyz + 3;
 
632
 
 
633
        newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
 
634
        newNormalScale = 1.0 - backlerp;
 
635
 
 
636
        numVerts = surf->numVerts;
 
637
 
 
638
        if ( backlerp == 0 ) {
 
639
                vector signed short newNormalsVec0;
 
640
                vector signed short newNormalsVec1;
 
641
                vector signed int newNormalsIntVec;
 
642
                vector float newNormalsFloatVec;
 
643
                vector float newXyzScaleVec;
 
644
                vector unsigned char newNormalsLoadPermute;
 
645
                vector unsigned char newNormalsStorePermute;
 
646
                vector float zero;
 
647
                
 
648
                newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
 
649
                newXyzScaleVec = *(vector float *)&newXyzScale;
 
650
                newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
 
651
                newXyzScaleVec = vec_splat(newXyzScaleVec,0);           
 
652
                newNormalsLoadPermute = vec_lvsl(0,newXyz);
 
653
                newNormalsStorePermute = vec_lvsr(0,outXyz);
 
654
                zero = (vector float)vec_splat_s8(0);
 
655
                //
 
656
                // just copy the vertexes
 
657
                //
 
658
                for (vertNum=0 ; vertNum < numVerts ; vertNum++,
 
659
                        newXyz += 4, newNormals += 4,
 
660
                        outXyz += 4, outNormal += 4) 
 
661
                {
 
662
                        newNormalsLoadPermute = vec_lvsl(0,newXyz);
 
663
                        newNormalsStorePermute = vec_lvsr(0,outXyz);
 
664
                        newNormalsVec0 = vec_ld(0,newXyz);
 
665
                        newNormalsVec1 = vec_ld(16,newXyz);
 
666
                        newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
 
667
                        newNormalsIntVec = vec_unpackh(newNormalsVec0);
 
668
                        newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
 
669
                        newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
 
670
                        newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
 
671
                        //outXyz[0] = newXyz[0] * newXyzScale;
 
672
                        //outXyz[1] = newXyz[1] * newXyzScale;
 
673
                        //outXyz[2] = newXyz[2] * newXyzScale;
 
674
 
 
675
                        lat = ( newNormals[0] >> 8 ) & 0xff;
 
676
                        lng = ( newNormals[0] & 0xff );
 
677
                        lat *= (FUNCTABLE_SIZE/256);
 
678
                        lng *= (FUNCTABLE_SIZE/256);
 
679
 
 
680
                        // decode X as cos( lat ) * sin( long )
 
681
                        // decode Y as sin( lat ) * sin( long )
 
682
                        // decode Z as cos( long )
 
683
 
 
684
                        outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
 
685
                        outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
 
686
                        outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
 
687
 
 
688
                        vec_ste(newNormalsFloatVec,0,outXyz);
 
689
                        vec_ste(newNormalsFloatVec,4,outXyz);
 
690
                        vec_ste(newNormalsFloatVec,8,outXyz);
 
691
                }
 
692
        } else {
 
693
                //
 
694
                // interpolate and copy the vertex and normal
 
695
                //
 
696
                oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
 
697
                        + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
 
698
                oldNormals = oldXyz + 3;
 
699
 
 
700
                oldXyzScale = MD3_XYZ_SCALE * backlerp;
 
701
                oldNormalScale = backlerp;
 
702
 
 
703
                for (vertNum=0 ; vertNum < numVerts ; vertNum++,
 
704
                        oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
 
705
                        outXyz += 4, outNormal += 4) 
 
706
                {
 
707
                        vec3_t uncompressedOldNormal, uncompressedNewNormal;
 
708
 
 
709
                        // interpolate the xyz
 
710
                        outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
 
711
                        outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
 
712
                        outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
 
713
 
 
714
                        // FIXME: interpolate lat/long instead?
 
715
                        lat = ( newNormals[0] >> 8 ) & 0xff;
 
716
                        lng = ( newNormals[0] & 0xff );
 
717
                        lat *= 4;
 
718
                        lng *= 4;
 
719
                        uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
 
720
                        uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
 
721
                        uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
 
722
 
 
723
                        lat = ( oldNormals[0] >> 8 ) & 0xff;
 
724
                        lng = ( oldNormals[0] & 0xff );
 
725
                        lat *= 4;
 
726
                        lng *= 4;
 
727
 
 
728
                        uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
 
729
                        uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
 
730
                        uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
 
731
 
 
732
                        outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
 
733
                        outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
 
734
                        outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
 
735
 
 
736
//                      VectorNormalize (outNormal);
 
737
                }
 
738
        VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
 
739
        }
 
740
}
 
741
#endif
 
742
 
 
743
static void LerpMeshVertexes_scalar(md3Surface_t *surf, float backlerp)
 
744
{
 
745
        short   *oldXyz, *newXyz, *oldNormals, *newNormals;
 
746
        float   *outXyz, *outNormal;
 
747
        float   oldXyzScale, newXyzScale;
 
748
        float   oldNormalScale, newNormalScale;
 
749
        int             vertNum;
 
750
        unsigned lat, lng;
 
751
        int             numVerts;
 
752
 
 
753
        outXyz = tess.xyz[tess.numVertexes];
 
754
        outNormal = tess.normal[tess.numVertexes];
 
755
 
 
756
        newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
 
757
                + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
 
758
        newNormals = newXyz + 3;
 
759
 
 
760
        newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
 
761
        newNormalScale = 1.0 - backlerp;
 
762
 
 
763
        numVerts = surf->numVerts;
 
764
 
 
765
        if ( backlerp == 0 ) {
 
766
                //
 
767
                // just copy the vertexes
 
768
                //
 
769
                for (vertNum=0 ; vertNum < numVerts ; vertNum++,
 
770
                        newXyz += 4, newNormals += 4,
 
771
                        outXyz += 4, outNormal += 4) 
 
772
                {
 
773
 
 
774
                        outXyz[0] = newXyz[0] * newXyzScale;
 
775
                        outXyz[1] = newXyz[1] * newXyzScale;
 
776
                        outXyz[2] = newXyz[2] * newXyzScale;
 
777
 
 
778
                        lat = ( newNormals[0] >> 8 ) & 0xff;
 
779
                        lng = ( newNormals[0] & 0xff );
 
780
                        lat *= (FUNCTABLE_SIZE/256);
 
781
                        lng *= (FUNCTABLE_SIZE/256);
 
782
 
 
783
                        // decode X as cos( lat ) * sin( long )
 
784
                        // decode Y as sin( lat ) * sin( long )
 
785
                        // decode Z as cos( long )
 
786
 
 
787
                        outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
 
788
                        outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
 
789
                        outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
 
790
                }
 
791
        } else {
 
792
                //
 
793
                // interpolate and copy the vertex and normal
 
794
                //
 
795
                oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
 
796
                        + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
 
797
                oldNormals = oldXyz + 3;
 
798
 
 
799
                oldXyzScale = MD3_XYZ_SCALE * backlerp;
 
800
                oldNormalScale = backlerp;
 
801
 
 
802
                for (vertNum=0 ; vertNum < numVerts ; vertNum++,
 
803
                        oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
 
804
                        outXyz += 4, outNormal += 4) 
 
805
                {
 
806
                        vec3_t uncompressedOldNormal, uncompressedNewNormal;
 
807
 
 
808
                        // interpolate the xyz
 
809
                        outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
 
810
                        outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
 
811
                        outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
 
812
 
 
813
                        // FIXME: interpolate lat/long instead?
 
814
                        lat = ( newNormals[0] >> 8 ) & 0xff;
 
815
                        lng = ( newNormals[0] & 0xff );
 
816
                        lat *= 4;
 
817
                        lng *= 4;
 
818
                        uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
 
819
                        uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
 
820
                        uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
 
821
 
 
822
                        lat = ( oldNormals[0] >> 8 ) & 0xff;
 
823
                        lng = ( oldNormals[0] & 0xff );
 
824
                        lat *= 4;
 
825
                        lng *= 4;
 
826
 
 
827
                        uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
 
828
                        uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
 
829
                        uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
 
830
 
 
831
                        outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
 
832
                        outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
 
833
                        outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
 
834
 
 
835
//                      VectorNormalize (outNormal);
 
836
                }
 
837
        VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
 
838
        }
 
839
}
 
840
 
 
841
static void LerpMeshVertexes(md3Surface_t *surf, float backlerp)
 
842
{
 
843
#if idppc_altivec
 
844
        if (com_altivec->integer) {
 
845
                // must be in a seperate function or G3 systems will crash.
 
846
                LerpMeshVertexes_altivec( surf, backlerp );
 
847
                return;
 
848
        }
 
849
#endif // idppc_altivec
 
850
        LerpMeshVertexes_scalar( surf, backlerp );
 
851
}
 
852
 
 
853
 
 
854
/*
 
855
=============
 
856
RB_SurfaceMesh
 
857
=============
 
858
*/
 
859
void RB_SurfaceMesh(md3Surface_t *surface) {
 
860
        int                             j;
 
861
        float                   backlerp;
 
862
        int                             *triangles;
 
863
        float                   *texCoords;
 
864
        int                             indexes;
 
865
        int                             Bob, Doug;
 
866
        int                             numVerts;
 
867
 
 
868
        if (  backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
 
869
                backlerp = 0;
 
870
        } else  {
 
871
                backlerp = backEnd.currentEntity->e.backlerp;
 
872
        }
 
873
 
 
874
        RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 );
 
875
 
 
876
        LerpMeshVertexes (surface, backlerp);
 
877
 
 
878
        triangles = (int *) ((byte *)surface + surface->ofsTriangles);
 
879
        indexes = surface->numTriangles * 3;
 
880
        Bob = tess.numIndexes;
 
881
        Doug = tess.numVertexes;
 
882
        for (j = 0 ; j < indexes ; j++) {
 
883
                tess.indexes[Bob + j] = Doug + triangles[j];
 
884
        }
 
885
        tess.numIndexes += indexes;
 
886
 
 
887
        texCoords = (float *) ((byte *)surface + surface->ofsSt);
 
888
 
 
889
        numVerts = surface->numVerts;
 
890
        for ( j = 0; j < numVerts; j++ ) {
 
891
                tess.texCoords[Doug + j][0][0] = texCoords[j*2+0];
 
892
                tess.texCoords[Doug + j][0][1] = texCoords[j*2+1];
 
893
                // FIXME: fill in lightmapST for completeness?
 
894
        }
 
895
 
 
896
        tess.numVertexes += surface->numVerts;
 
897
 
 
898
}
 
899
 
 
900
 
 
901
/*
 
902
==============
 
903
RB_SurfaceFace
 
904
==============
 
905
*/
 
906
void RB_SurfaceFace( srfSurfaceFace_t *surf ) {
 
907
        int                     i;
 
908
        unsigned        *indices, *tessIndexes;
 
909
        float           *v;
 
910
        float           *normal;
 
911
        int                     ndx;
 
912
        int                     Bob;
 
913
        int                     numPoints;
 
914
        int                     dlightBits;
 
915
 
 
916
        RB_CHECKOVERFLOW( surf->numPoints, surf->numIndices );
 
917
 
 
918
        dlightBits = surf->dlightBits[backEnd.smpFrame];
 
919
        tess.dlightBits |= dlightBits;
 
920
 
 
921
        indices = ( unsigned * ) ( ( ( char  * ) surf ) + surf->ofsIndices );
 
922
 
 
923
        Bob = tess.numVertexes;
 
924
        tessIndexes = tess.indexes + tess.numIndexes;
 
925
        for ( i = surf->numIndices-1 ; i >= 0  ; i-- ) {
 
926
                tessIndexes[i] = indices[i] + Bob;
 
927
        }
 
928
 
 
929
        tess.numIndexes += surf->numIndices;
 
930
 
 
931
        v = surf->points[0];
 
932
 
 
933
        ndx = tess.numVertexes;
 
934
 
 
935
        numPoints = surf->numPoints;
 
936
 
 
937
        if ( tess.shader->needsNormal ) {
 
938
                normal = surf->plane.normal;
 
939
                for ( i = 0, ndx = tess.numVertexes; i < numPoints; i++, ndx++ ) {
 
940
                        VectorCopy( normal, tess.normal[ndx] );
 
941
                }
 
942
        }
 
943
 
 
944
        for ( i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++ ) {
 
945
                VectorCopy( v, tess.xyz[ndx]);
 
946
                tess.texCoords[ndx][0][0] = v[3];
 
947
                tess.texCoords[ndx][0][1] = v[4];
 
948
                tess.texCoords[ndx][1][0] = v[5];
 
949
                tess.texCoords[ndx][1][1] = v[6];
 
950
                * ( unsigned int * ) &tess.vertexColors[ndx] = * ( unsigned int * ) &v[7];
 
951
                tess.vertexDlightBits[ndx] = dlightBits;
 
952
        }
 
953
 
 
954
 
 
955
        tess.numVertexes += surf->numPoints;
 
956
}
 
957
 
 
958
 
 
959
static float    LodErrorForVolume( vec3_t local, float radius ) {
 
960
        vec3_t          world;
 
961
        float           d;
 
962
 
 
963
        // never let it go negative
 
964
        if ( r_lodCurveError->value < 0 ) {
 
965
                return 0;
 
966
        }
 
967
 
 
968
        world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] + 
 
969
                local[2] * backEnd.or.axis[2][0] + backEnd.or.origin[0];
 
970
        world[1] = local[0] * backEnd.or.axis[0][1] + local[1] * backEnd.or.axis[1][1] + 
 
971
                local[2] * backEnd.or.axis[2][1] + backEnd.or.origin[1];
 
972
        world[2] = local[0] * backEnd.or.axis[0][2] + local[1] * backEnd.or.axis[1][2] + 
 
973
                local[2] * backEnd.or.axis[2][2] + backEnd.or.origin[2];
 
974
 
 
975
        VectorSubtract( world, backEnd.viewParms.or.origin, world );
 
976
        d = DotProduct( world, backEnd.viewParms.or.axis[0] );
 
977
 
 
978
        if ( d < 0 ) {
 
979
                d = -d;
 
980
        }
 
981
        d -= radius;
 
982
        if ( d < 1 ) {
 
983
                d = 1;
 
984
        }
 
985
 
 
986
        return r_lodCurveError->value / d;
 
987
}
 
988
 
 
989
/*
 
990
=============
 
991
RB_SurfaceGrid
 
992
 
 
993
Just copy the grid of points and triangulate
 
994
=============
 
995
*/
 
996
void RB_SurfaceGrid( srfGridMesh_t *cv ) {
 
997
        int             i, j;
 
998
        float   *xyz;
 
999
        float   *texCoords;
 
1000
        float   *normal;
 
1001
        unsigned char *color;
 
1002
        drawVert_t      *dv;
 
1003
        int             rows, irows, vrows;
 
1004
        int             used;
 
1005
        int             widthTable[MAX_GRID_SIZE];
 
1006
        int             heightTable[MAX_GRID_SIZE];
 
1007
        float   lodError;
 
1008
        int             lodWidth, lodHeight;
 
1009
        int             numVertexes;
 
1010
        int             dlightBits;
 
1011
        int             *vDlightBits;
 
1012
        qboolean        needsNormal;
 
1013
 
 
1014
        dlightBits = cv->dlightBits[backEnd.smpFrame];
 
1015
        tess.dlightBits |= dlightBits;
 
1016
 
 
1017
        // determine the allowable discrepance
 
1018
        lodError = LodErrorForVolume( cv->lodOrigin, cv->lodRadius );
 
1019
 
 
1020
        // determine which rows and columns of the subdivision
 
1021
        // we are actually going to use
 
1022
        widthTable[0] = 0;
 
1023
        lodWidth = 1;
 
1024
        for ( i = 1 ; i < cv->width-1 ; i++ ) {
 
1025
                if ( cv->widthLodError[i] <= lodError ) {
 
1026
                        widthTable[lodWidth] = i;
 
1027
                        lodWidth++;
 
1028
                }
 
1029
        }
 
1030
        widthTable[lodWidth] = cv->width-1;
 
1031
        lodWidth++;
 
1032
 
 
1033
        heightTable[0] = 0;
 
1034
        lodHeight = 1;
 
1035
        for ( i = 1 ; i < cv->height-1 ; i++ ) {
 
1036
                if ( cv->heightLodError[i] <= lodError ) {
 
1037
                        heightTable[lodHeight] = i;
 
1038
                        lodHeight++;
 
1039
                }
 
1040
        }
 
1041
        heightTable[lodHeight] = cv->height-1;
 
1042
        lodHeight++;
 
1043
 
 
1044
 
 
1045
        // very large grids may have more points or indexes than can be fit
 
1046
        // in the tess structure, so we may have to issue it in multiple passes
 
1047
 
 
1048
        used = 0;
 
1049
        rows = 0;
 
1050
        while ( used < lodHeight - 1 ) {
 
1051
                // see how many rows of both verts and indexes we can add without overflowing
 
1052
                do {
 
1053
                        vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth;
 
1054
                        irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 );
 
1055
 
 
1056
                        // if we don't have enough space for at least one strip, flush the buffer
 
1057
                        if ( vrows < 2 || irows < 1 ) {
 
1058
                                RB_EndSurface();
 
1059
                                RB_BeginSurface(tess.shader, tess.fogNum );
 
1060
                        } else {
 
1061
                                break;
 
1062
                        }
 
1063
                } while ( 1 );
 
1064
                
 
1065
                rows = irows;
 
1066
                if ( vrows < irows + 1 ) {
 
1067
                        rows = vrows - 1;
 
1068
                }
 
1069
                if ( used + rows > lodHeight ) {
 
1070
                        rows = lodHeight - used;
 
1071
                }
 
1072
 
 
1073
                numVertexes = tess.numVertexes;
 
1074
 
 
1075
                xyz = tess.xyz[numVertexes];
 
1076
                normal = tess.normal[numVertexes];
 
1077
                texCoords = tess.texCoords[numVertexes][0];
 
1078
                color = ( unsigned char * ) &tess.vertexColors[numVertexes];
 
1079
                vDlightBits = &tess.vertexDlightBits[numVertexes];
 
1080
                needsNormal = tess.shader->needsNormal;
 
1081
 
 
1082
                for ( i = 0 ; i < rows ; i++ ) {
 
1083
                        for ( j = 0 ; j < lodWidth ; j++ ) {
 
1084
                                dv = cv->verts + heightTable[ used + i ] * cv->width
 
1085
                                        + widthTable[ j ];
 
1086
 
 
1087
                                xyz[0] = dv->xyz[0];
 
1088
                                xyz[1] = dv->xyz[1];
 
1089
                                xyz[2] = dv->xyz[2];
 
1090
                                texCoords[0] = dv->st[0];
 
1091
                                texCoords[1] = dv->st[1];
 
1092
                                texCoords[2] = dv->lightmap[0];
 
1093
                                texCoords[3] = dv->lightmap[1];
 
1094
                                if ( needsNormal ) {
 
1095
                                        normal[0] = dv->normal[0];
 
1096
                                        normal[1] = dv->normal[1];
 
1097
                                        normal[2] = dv->normal[2];
 
1098
                                }
 
1099
                                * ( unsigned int * ) color = * ( unsigned int * ) dv->color;
 
1100
                                *vDlightBits++ = dlightBits;
 
1101
                                xyz += 4;
 
1102
                                normal += 4;
 
1103
                                texCoords += 4;
 
1104
                                color += 4;
 
1105
                        }
 
1106
                }
 
1107
 
 
1108
 
 
1109
                // add the indexes
 
1110
                {
 
1111
                        int             numIndexes;
 
1112
                        int             w, h;
 
1113
 
 
1114
                        h = rows - 1;
 
1115
                        w = lodWidth - 1;
 
1116
                        numIndexes = tess.numIndexes;
 
1117
                        for (i = 0 ; i < h ; i++) {
 
1118
                                for (j = 0 ; j < w ; j++) {
 
1119
                                        int             v1, v2, v3, v4;
 
1120
                        
 
1121
                                        // vertex order to be reckognized as tristrips
 
1122
                                        v1 = numVertexes + i*lodWidth + j + 1;
 
1123
                                        v2 = v1 - 1;
 
1124
                                        v3 = v2 + lodWidth;
 
1125
                                        v4 = v3 + 1;
 
1126
 
 
1127
                                        tess.indexes[numIndexes] = v2;
 
1128
                                        tess.indexes[numIndexes+1] = v3;
 
1129
                                        tess.indexes[numIndexes+2] = v1;
 
1130
                                        
 
1131
                                        tess.indexes[numIndexes+3] = v1;
 
1132
                                        tess.indexes[numIndexes+4] = v3;
 
1133
                                        tess.indexes[numIndexes+5] = v4;
 
1134
                                        numIndexes += 6;
 
1135
                                }
 
1136
                        }
 
1137
 
 
1138
                        tess.numIndexes = numIndexes;
 
1139
                }
 
1140
 
 
1141
                tess.numVertexes += rows * lodWidth;
 
1142
 
 
1143
                used += rows - 1;
 
1144
        }
 
1145
}
 
1146
 
 
1147
 
 
1148
/*
 
1149
===========================================================================
 
1150
 
 
1151
NULL MODEL
 
1152
 
 
1153
===========================================================================
 
1154
*/
 
1155
 
 
1156
/*
 
1157
===================
 
1158
RB_SurfaceAxis
 
1159
 
 
1160
Draws x/y/z lines from the origin for orientation debugging
 
1161
===================
 
1162
*/
 
1163
void RB_SurfaceAxis( void ) {
 
1164
        GL_Bind( tr.whiteImage );
 
1165
        qglLineWidth( 3 );
 
1166
        qglBegin( GL_LINES );
 
1167
        qglColor3f( 1,0,0 );
 
1168
        qglVertex3f( 0,0,0 );
 
1169
        qglVertex3f( 16,0,0 );
 
1170
        qglColor3f( 0,1,0 );
 
1171
        qglVertex3f( 0,0,0 );
 
1172
        qglVertex3f( 0,16,0 );
 
1173
        qglColor3f( 0,0,1 );
 
1174
        qglVertex3f( 0,0,0 );
 
1175
        qglVertex3f( 0,0,16 );
 
1176
        qglEnd();
 
1177
        qglLineWidth( 1 );
 
1178
}
 
1179
 
 
1180
//===========================================================================
 
1181
 
 
1182
/*
 
1183
====================
 
1184
RB_SurfaceEntity
 
1185
 
 
1186
Entities that have a single procedurally generated surface
 
1187
====================
 
1188
*/
 
1189
void RB_SurfaceEntity( surfaceType_t *surfType ) {
 
1190
        switch( backEnd.currentEntity->e.reType ) {
 
1191
        case RT_SPRITE:
 
1192
                RB_SurfaceSprite();
 
1193
                break;
 
1194
        case RT_BEAM:
 
1195
                RB_SurfaceBeam();
 
1196
                break;
 
1197
        case RT_RAIL_CORE:
 
1198
                RB_SurfaceRailCore();
 
1199
                break;
 
1200
        case RT_RAIL_RINGS:
 
1201
                RB_SurfaceRailRings();
 
1202
                break;
 
1203
        case RT_LIGHTNING:
 
1204
                RB_SurfaceLightningBolt();
 
1205
                break;
 
1206
        default:
 
1207
                RB_SurfaceAxis();
 
1208
                break;
 
1209
        }
 
1210
        return;
 
1211
}
 
1212
 
 
1213
void RB_SurfaceBad( surfaceType_t *surfType ) {
 
1214
        ri.Printf( PRINT_ALL, "Bad surface tesselated.\n" );
 
1215
}
 
1216
 
 
1217
void RB_SurfaceFlare(srfFlare_t *surf)
 
1218
{
 
1219
        if (r_flares->integer)
 
1220
                RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);
 
1221
}
 
1222
 
 
1223
void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {
 
1224
        // all apropriate state must be set in RB_BeginSurface
 
1225
        // this isn't implemented yet...
 
1226
        qglCallList( surf->listNum );
 
1227
}
 
1228
 
 
1229
void RB_SurfaceSkip( void *surf ) {
 
1230
}
 
1231
 
 
1232
 
 
1233
void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
 
1234
        (void(*)(void*))RB_SurfaceBad,                  // SF_BAD, 
 
1235
        (void(*)(void*))RB_SurfaceSkip,                 // SF_SKIP, 
 
1236
        (void(*)(void*))RB_SurfaceFace,                 // SF_FACE,
 
1237
        (void(*)(void*))RB_SurfaceGrid,                 // SF_GRID,
 
1238
        (void(*)(void*))RB_SurfaceTriangles,            // SF_TRIANGLES,
 
1239
        (void(*)(void*))RB_SurfacePolychain,            // SF_POLY,
 
1240
        (void(*)(void*))RB_SurfaceMesh,                 // SF_MD3,
 
1241
        (void(*)(void*))RB_SurfaceAnim,                 // SF_MD4,
 
1242
#ifdef RAVENMD4
 
1243
        (void(*)(void*))RB_MDRSurfaceAnim,              // SF_MDR,
 
1244
#endif
 
1245
        (void(*)(void*))RB_SurfaceFlare,                // SF_FLARE,
 
1246
        (void(*)(void*))RB_SurfaceEntity,               // SF_ENTITY
 
1247
        (void(*)(void*))RB_SurfaceDisplayList           // SF_DISPLAY_LIST
 
1248
};