Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_surface.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // tr_surf.c
00023 #include "tr_local.h"
00024 
00025 /*
00026 
00027   THIS ENTIRE FILE IS BACK END
00028 
00029 backEnd.currentEntity will be valid.
00030 
00031 Tess_Begin has already been called for the surface's shader.
00032 
00033 The modelview matrix will be set.
00034 
00035 It is safe to actually issue drawing commands here if you don't want to
00036 use the shader system.
00037 */
00038 
00039 
00040 //============================================================================
00041 
00042 
00043 /*
00044 ==============
00045 RB_CheckOverflow
00046 ==============
00047 */
00048 void RB_CheckOverflow( int verts, int indexes ) {
00049     if (tess.numVertexes + verts < SHADER_MAX_VERTEXES
00050         && tess.numIndexes + indexes < SHADER_MAX_INDEXES) {
00051         return;
00052     }
00053 
00054     RB_EndSurface();
00055 
00056     if ( verts >= SHADER_MAX_VERTEXES ) {
00057         ri.Error(ERR_DROP, "RB_CheckOverflow: verts > MAX (%d > %d)", verts, SHADER_MAX_VERTEXES );
00058     }
00059     if ( indexes >= SHADER_MAX_INDEXES ) {
00060         ri.Error(ERR_DROP, "RB_CheckOverflow: indices > MAX (%d > %d)", indexes, SHADER_MAX_INDEXES );
00061     }
00062 
00063     RB_BeginSurface(tess.shader, tess.fogNum );
00064 }
00065 
00066 
00067 /*
00068 ==============
00069 RB_AddQuadStampExt
00070 ==============
00071 */
00072 void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2 ) {
00073     vec3_t      normal;
00074     int         ndx;
00075 
00076     RB_CHECKOVERFLOW( 4, 6 );
00077 
00078     ndx = tess.numVertexes;
00079 
00080     // triangle indexes for a simple quad
00081     tess.indexes[ tess.numIndexes ] = ndx;
00082     tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
00083     tess.indexes[ tess.numIndexes + 2 ] = ndx + 3;
00084 
00085     tess.indexes[ tess.numIndexes + 3 ] = ndx + 3;
00086     tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
00087     tess.indexes[ tess.numIndexes + 5 ] = ndx + 2;
00088 
00089     tess.xyz[ndx][0] = origin[0] + left[0] + up[0];
00090     tess.xyz[ndx][1] = origin[1] + left[1] + up[1];
00091     tess.xyz[ndx][2] = origin[2] + left[2] + up[2];
00092 
00093     tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0];
00094     tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1];
00095     tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2];
00096 
00097     tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0];
00098     tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1];
00099     tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2];
00100 
00101     tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0];
00102     tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1];
00103     tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2];
00104 
00105 
00106     // constant normal all the way around
00107     VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );
00108 
00109     tess.normal[ndx][0] = tess.normal[ndx+1][0] = tess.normal[ndx+2][0] = tess.normal[ndx+3][0] = normal[0];
00110     tess.normal[ndx][1] = tess.normal[ndx+1][1] = tess.normal[ndx+2][1] = tess.normal[ndx+3][1] = normal[1];
00111     tess.normal[ndx][2] = tess.normal[ndx+1][2] = tess.normal[ndx+2][2] = tess.normal[ndx+3][2] = normal[2];
00112     
00113     // standard square texture coordinates
00114     tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1;
00115     tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1;
00116 
00117     tess.texCoords[ndx+1][0][0] = tess.texCoords[ndx+1][1][0] = s2;
00118     tess.texCoords[ndx+1][0][1] = tess.texCoords[ndx+1][1][1] = t1;
00119 
00120     tess.texCoords[ndx+2][0][0] = tess.texCoords[ndx+2][1][0] = s2;
00121     tess.texCoords[ndx+2][0][1] = tess.texCoords[ndx+2][1][1] = t2;
00122 
00123     tess.texCoords[ndx+3][0][0] = tess.texCoords[ndx+3][1][0] = s1;
00124     tess.texCoords[ndx+3][0][1] = tess.texCoords[ndx+3][1][1] = t2;
00125 
00126     // constant color all the way around
00127     // should this be identity and let the shader specify from entity?
00128     * ( unsigned int * ) &tess.vertexColors[ndx] = 
00129     * ( unsigned int * ) &tess.vertexColors[ndx+1] = 
00130     * ( unsigned int * ) &tess.vertexColors[ndx+2] = 
00131     * ( unsigned int * ) &tess.vertexColors[ndx+3] = 
00132         * ( unsigned int * )color;
00133 
00134 
00135     tess.numVertexes += 4;
00136     tess.numIndexes += 6;
00137 }
00138 
00139 /*
00140 ==============
00141 RB_AddQuadStamp
00142 ==============
00143 */
00144 void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color ) {
00145     RB_AddQuadStampExt( origin, left, up, color, 0, 0, 1, 1 );
00146 }
00147 
00148 /*
00149 ==============
00150 RB_SurfaceSprite
00151 ==============
00152 */
00153 static void RB_SurfaceSprite( void ) {
00154     vec3_t      left, up;
00155     float       radius;
00156 
00157     // calculate the xyz locations for the four corners
00158     radius = backEnd.currentEntity->e.radius;
00159     if ( backEnd.currentEntity->e.rotation == 0 ) {
00160         VectorScale( backEnd.viewParms.or.axis[1], radius, left );
00161         VectorScale( backEnd.viewParms.or.axis[2], radius, up );
00162     } else {
00163         float   s, c;
00164         float   ang;
00165         
00166         ang = M_PI * backEnd.currentEntity->e.rotation / 180;
00167         s = sin( ang );
00168         c = cos( ang );
00169 
00170         VectorScale( backEnd.viewParms.or.axis[1], c * radius, left );
00171         VectorMA( left, -s * radius, backEnd.viewParms.or.axis[2], left );
00172 
00173         VectorScale( backEnd.viewParms.or.axis[2], c * radius, up );
00174         VectorMA( up, s * radius, backEnd.viewParms.or.axis[1], up );
00175     }
00176     if ( backEnd.viewParms.isMirror ) {
00177         VectorSubtract( vec3_origin, left, left );
00178     }
00179 
00180     RB_AddQuadStamp( backEnd.currentEntity->e.origin, left, up, backEnd.currentEntity->e.shaderRGBA );
00181 }
00182 
00183 
00184 /*
00185 =============
00186 RB_SurfacePolychain
00187 =============
00188 */
00189 void RB_SurfacePolychain( srfPoly_t *p ) {
00190     int     i;
00191     int     numv;
00192 
00193     RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) );
00194 
00195     // fan triangles into the tess array
00196     numv = tess.numVertexes;
00197     for ( i = 0; i < p->numVerts; i++ ) {
00198         VectorCopy( p->verts[i].xyz, tess.xyz[numv] );
00199         tess.texCoords[numv][0][0] = p->verts[i].st[0];
00200         tess.texCoords[numv][0][1] = p->verts[i].st[1];
00201         *(int *)&tess.vertexColors[numv] = *(int *)p->verts[ i ].modulate;
00202 
00203         numv++;
00204     }
00205 
00206     // generate fan indexes into the tess array
00207     for ( i = 0; i < p->numVerts-2; i++ ) {
00208         tess.indexes[tess.numIndexes + 0] = tess.numVertexes;
00209         tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1;
00210         tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2;
00211         tess.numIndexes += 3;
00212     }
00213 
00214     tess.numVertexes = numv;
00215 }
00216 
00217 
00218 /*
00219 =============
00220 RB_SurfaceTriangles
00221 =============
00222 */
00223 void RB_SurfaceTriangles( srfTriangles_t *srf ) {
00224     int         i;
00225     drawVert_t  *dv;
00226     float       *xyz, *normal, *texCoords;
00227     byte        *color;
00228     int         dlightBits;
00229     qboolean    needsNormal;
00230 
00231     dlightBits = srf->dlightBits[backEnd.smpFrame];
00232     tess.dlightBits |= dlightBits;
00233 
00234     RB_CHECKOVERFLOW( srf->numVerts, srf->numIndexes );
00235 
00236     for ( i = 0 ; i < srf->numIndexes ; i += 3 ) {
00237         tess.indexes[ tess.numIndexes + i + 0 ] = tess.numVertexes + srf->indexes[ i + 0 ];
00238         tess.indexes[ tess.numIndexes + i + 1 ] = tess.numVertexes + srf->indexes[ i + 1 ];
00239         tess.indexes[ tess.numIndexes + i + 2 ] = tess.numVertexes + srf->indexes[ i + 2 ];
00240     }
00241     tess.numIndexes += srf->numIndexes;
00242 
00243     dv = srf->verts;
00244     xyz = tess.xyz[ tess.numVertexes ];
00245     normal = tess.normal[ tess.numVertexes ];
00246     texCoords = tess.texCoords[ tess.numVertexes ][0];
00247     color = tess.vertexColors[ tess.numVertexes ];
00248     needsNormal = tess.shader->needsNormal;
00249 
00250     for ( i = 0 ; i < srf->numVerts ; i++, dv++, xyz += 4, normal += 4, texCoords += 4, color += 4 ) {
00251         xyz[0] = dv->xyz[0];
00252         xyz[1] = dv->xyz[1];
00253         xyz[2] = dv->xyz[2];
00254 
00255         if ( needsNormal ) {
00256             normal[0] = dv->normal[0];
00257             normal[1] = dv->normal[1];
00258             normal[2] = dv->normal[2];
00259         }
00260 
00261         texCoords[0] = dv->st[0];
00262         texCoords[1] = dv->st[1];
00263 
00264         texCoords[2] = dv->lightmap[0];
00265         texCoords[3] = dv->lightmap[1];
00266 
00267         *(int *)color = *(int *)dv->color;
00268     }
00269 
00270     for ( i = 0 ; i < srf->numVerts ; i++ ) {
00271         tess.vertexDlightBits[ tess.numVertexes + i] = dlightBits;
00272     }
00273 
00274     tess.numVertexes += srf->numVerts;
00275 }
00276 
00277 
00278 
00279 /*
00280 ==============
00281 RB_SurfaceBeam
00282 ==============
00283 */
00284 void RB_SurfaceBeam( void ) 
00285 {
00286 #define NUM_BEAM_SEGS 6
00287     refEntity_t *e;
00288     int i;
00289     vec3_t perpvec;
00290     vec3_t direction, normalized_direction;
00291     vec3_t  start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
00292     vec3_t oldorigin, origin;
00293 
00294     e = &backEnd.currentEntity->e;
00295 
00296     oldorigin[0] = e->oldorigin[0];
00297     oldorigin[1] = e->oldorigin[1];
00298     oldorigin[2] = e->oldorigin[2];
00299 
00300     origin[0] = e->origin[0];
00301     origin[1] = e->origin[1];
00302     origin[2] = e->origin[2];
00303 
00304     normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
00305     normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
00306     normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
00307 
00308     if ( VectorNormalize( normalized_direction ) == 0 )
00309         return;
00310 
00311     PerpendicularVector( perpvec, normalized_direction );
00312 
00313     VectorScale( perpvec, 4, perpvec );
00314 
00315     for ( i = 0; i < NUM_BEAM_SEGS ; i++ )
00316     {
00317         RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
00318 //      VectorAdd( start_points[i], origin, start_points[i] );
00319         VectorAdd( start_points[i], direction, end_points[i] );
00320     }
00321 
00322     GL_Bind( tr.whiteImage );
00323 
00324     GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
00325 
00326     qglColor3f( 1, 0, 0 );
00327 
00328     qglBegin( GL_TRIANGLE_STRIP );
00329     for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
00330         qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] );
00331         qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] );
00332     }
00333     qglEnd();
00334 }
00335 
00336 //================================================================================
00337 
00338 static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth )
00339 {
00340     float       spanWidth2;
00341     int         vbase;
00342     float       t = len / 256.0f;
00343 
00344     vbase = tess.numVertexes;
00345 
00346     spanWidth2 = -spanWidth;
00347 
00348     // FIXME: use quad stamp?
00349     VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] );
00350     tess.texCoords[tess.numVertexes][0][0] = 0;
00351     tess.texCoords[tess.numVertexes][0][1] = 0;
00352     tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25;
00353     tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25;
00354     tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25;
00355     tess.numVertexes++;
00356 
00357     VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] );
00358     tess.texCoords[tess.numVertexes][0][0] = 0;
00359     tess.texCoords[tess.numVertexes][0][1] = 1;
00360     tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
00361     tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
00362     tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
00363     tess.numVertexes++;
00364 
00365     VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] );
00366 
00367     tess.texCoords[tess.numVertexes][0][0] = t;
00368     tess.texCoords[tess.numVertexes][0][1] = 0;
00369     tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
00370     tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
00371     tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
00372     tess.numVertexes++;
00373 
00374     VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] );
00375     tess.texCoords[tess.numVertexes][0][0] = t;
00376     tess.texCoords[tess.numVertexes][0][1] = 1;
00377     tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
00378     tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
00379     tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
00380     tess.numVertexes++;
00381 
00382     tess.indexes[tess.numIndexes++] = vbase;
00383     tess.indexes[tess.numIndexes++] = vbase + 1;
00384     tess.indexes[tess.numIndexes++] = vbase + 2;
00385 
00386     tess.indexes[tess.numIndexes++] = vbase + 2;
00387     tess.indexes[tess.numIndexes++] = vbase + 1;
00388     tess.indexes[tess.numIndexes++] = vbase + 3;
00389 }
00390 
00391 static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up )
00392 {
00393     int i;
00394     vec3_t  pos[4];
00395     vec3_t  v;
00396     int     spanWidth = r_railWidth->integer;
00397     float c, s;
00398     float       scale;
00399 
00400     if ( numSegs > 1 )
00401         numSegs--;
00402     if ( !numSegs )
00403         return;
00404 
00405     scale = 0.25;
00406 
00407     for ( i = 0; i < 4; i++ )
00408     {
00409         c = cos( DEG2RAD( 45 + i * 90 ) );
00410         s = sin( DEG2RAD( 45 + i * 90 ) );
00411         v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth;
00412         v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth;
00413         v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth;
00414         VectorAdd( start, v, pos[i] );
00415 
00416         if ( numSegs > 1 )
00417         {
00418             // offset by 1 segment if we're doing a long distance shot
00419             VectorAdd( pos[i], dir, pos[i] );
00420         }
00421     }
00422 
00423     for ( i = 0; i < numSegs; i++ )
00424     {
00425         int j;
00426 
00427         RB_CHECKOVERFLOW( 4, 6 );
00428 
00429         for ( j = 0; j < 4; j++ )
00430         {
00431             VectorCopy( pos[j], tess.xyz[tess.numVertexes] );
00432             tess.texCoords[tess.numVertexes][0][0] = ( j < 2 );
00433             tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 );
00434             tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
00435             tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
00436             tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
00437             tess.numVertexes++;
00438 
00439             VectorAdd( pos[j], dir, pos[j] );
00440         }
00441 
00442         tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0;
00443         tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
00444         tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
00445         tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
00446         tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
00447         tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2;
00448     }
00449 }
00450 
00451 /*
00452 ** RB_SurfaceRailRinges
00453 */
00454 void RB_SurfaceRailRings( void ) {
00455     refEntity_t *e;
00456     int         numSegs;
00457     int         len;
00458     vec3_t      vec;
00459     vec3_t      right, up;
00460     vec3_t      start, end;
00461 
00462     e = &backEnd.currentEntity->e;
00463 
00464     VectorCopy( e->oldorigin, start );
00465     VectorCopy( e->origin, end );
00466 
00467     // compute variables
00468     VectorSubtract( end, start, vec );
00469     len = VectorNormalize( vec );
00470     MakeNormalVectors( vec, right, up );
00471     numSegs = ( len ) / r_railSegmentLength->value;
00472     if ( numSegs <= 0 ) {
00473         numSegs = 1;
00474     }
00475 
00476     VectorScale( vec, r_railSegmentLength->value, vec );
00477 
00478     DoRailDiscs( numSegs, start, vec, right, up );
00479 }
00480 
00481 /*
00482 ** RB_SurfaceRailCore
00483 */
00484 void RB_SurfaceRailCore( void ) {
00485     refEntity_t *e;
00486     int         len;
00487     vec3_t      right;
00488     vec3_t      vec;
00489     vec3_t      start, end;
00490     vec3_t      v1, v2;
00491 
00492     e = &backEnd.currentEntity->e;
00493 
00494     VectorCopy( e->oldorigin, start );
00495     VectorCopy( e->origin, end );
00496 
00497     VectorSubtract( end, start, vec );
00498     len = VectorNormalize( vec );
00499 
00500     // compute side vector
00501     VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
00502     VectorNormalize( v1 );
00503     VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
00504     VectorNormalize( v2 );
00505     CrossProduct( v1, v2, right );
00506     VectorNormalize( right );
00507 
00508     DoRailCore( start, end, right, len, r_railCoreWidth->integer );
00509 }
00510 
00511 /*
00512 ** RB_SurfaceLightningBolt
00513 */
00514 void RB_SurfaceLightningBolt( void ) {
00515     refEntity_t *e;
00516     int         len;
00517     vec3_t      right;
00518     vec3_t      vec;
00519     vec3_t      start, end;
00520     vec3_t      v1, v2;
00521     int         i;
00522 
00523     e = &backEnd.currentEntity->e;
00524 
00525     VectorCopy( e->oldorigin, end );
00526     VectorCopy( e->origin, start );
00527 
00528     // compute variables
00529     VectorSubtract( end, start, vec );
00530     len = VectorNormalize( vec );
00531 
00532     // compute side vector
00533     VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
00534     VectorNormalize( v1 );
00535     VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
00536     VectorNormalize( v2 );
00537     CrossProduct( v1, v2, right );
00538     VectorNormalize( right );
00539 
00540     for ( i = 0 ; i < 4 ; i++ ) {
00541         vec3_t  temp;
00542 
00543         DoRailCore( start, end, right, len, 8 );
00544         RotatePointAroundVector( temp, vec, right, 45 );
00545         VectorCopy( temp, right );
00546     }
00547 }
00548 
00549 /*
00550 ** VectorArrayNormalize
00551 *
00552 * The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
00553 * This means that we don't have to worry about zero length or enormously long vectors.
00554 */
00555 static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
00556 {
00557 //    assert(count);
00558         
00559 #if idppc
00560     {
00561         register float half = 0.5;
00562         register float one  = 1.0;
00563         float *components = (float *)normals;
00564         
00565         // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
00566         // runs *much* faster than calling sqrt().  We'll use a single Newton-Raphson
00567         // refinement step to get a little more precision.  This seems to yeild results
00568         // that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5).
00569         // (That is, for the given input range of about 0.6 to 2.0).
00570         do {
00571             float x, y, z;
00572             float B, y0, y1;
00573             
00574             x = components[0];
00575             y = components[1];
00576             z = components[2];
00577             components += 4;
00578             B = x*x + y*y + z*z;
00579 
00580 #ifdef __GNUC__            
00581             asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
00582 #else
00583             y0 = __frsqrte(B);
00584 #endif
00585             y1 = y0 + half*y0*(one - B*y0*y0);
00586 
00587             x = x * y1;
00588             y = y * y1;
00589             components[-4] = x;
00590             z = z * y1;
00591             components[-3] = y;
00592             components[-2] = z;
00593         } while(count--);
00594     }
00595 #else // No assembly version for this architecture, or C_ONLY defined
00596     // given the input, it's safe to call VectorNormalizeFast
00597     while (count--) {
00598         VectorNormalizeFast(normals[0]);
00599         normals++;
00600     }
00601 #endif
00602 
00603 }
00604 
00605 
00606 
00607 /*
00608 ** LerpMeshVertexes
00609 */
00610 static void LerpMeshVertexes (md3Surface_t *surf, float backlerp) 
00611 {
00612     short   *oldXyz, *newXyz, *oldNormals, *newNormals;
00613     float   *outXyz, *outNormal;
00614     float   oldXyzScale, newXyzScale;
00615     float   oldNormalScale, newNormalScale;
00616     int     vertNum;
00617     unsigned lat, lng;
00618     int     numVerts;
00619 
00620     outXyz = tess.xyz[tess.numVertexes];
00621     outNormal = tess.normal[tess.numVertexes];
00622 
00623     newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
00624         + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
00625     newNormals = newXyz + 3;
00626 
00627     newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
00628     newNormalScale = 1.0 - backlerp;
00629 
00630     numVerts = surf->numVerts;
00631 
00632     if ( backlerp == 0 ) {
00633 #if idppc_altivec
00634         vector signed short newNormalsVec0;
00635         vector signed short newNormalsVec1;
00636         vector signed int newNormalsIntVec;
00637         vector float newNormalsFloatVec;
00638         vector float newXyzScaleVec;
00639         vector unsigned char newNormalsLoadPermute;
00640         vector unsigned char newNormalsStorePermute;
00641         vector float zero;
00642         
00643         newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
00644         newXyzScaleVec = *(vector float *)&newXyzScale;
00645         newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
00646         newXyzScaleVec = vec_splat(newXyzScaleVec,0);       
00647         newNormalsLoadPermute = vec_lvsl(0,newXyz);
00648         newNormalsStorePermute = vec_lvsr(0,outXyz);
00649         zero = (vector float)vec_splat_s8(0);
00650         //
00651         // just copy the vertexes
00652         //
00653         for (vertNum=0 ; vertNum < numVerts ; vertNum++,
00654             newXyz += 4, newNormals += 4,
00655             outXyz += 4, outNormal += 4) 
00656         {
00657             newNormalsLoadPermute = vec_lvsl(0,newXyz);
00658             newNormalsStorePermute = vec_lvsr(0,outXyz);
00659             newNormalsVec0 = vec_ld(0,newXyz);
00660             newNormalsVec1 = vec_ld(16,newXyz);
00661             newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
00662             newNormalsIntVec = vec_unpackh(newNormalsVec0);
00663             newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
00664             newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
00665             newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
00666             //outXyz[0] = newXyz[0] * newXyzScale;
00667             //outXyz[1] = newXyz[1] * newXyzScale;
00668             //outXyz[2] = newXyz[2] * newXyzScale;
00669 
00670             lat = ( newNormals[0] >> 8 ) & 0xff;
00671             lng = ( newNormals[0] & 0xff );
00672             lat *= (FUNCTABLE_SIZE/256);
00673             lng *= (FUNCTABLE_SIZE/256);
00674 
00675             // decode X as cos( lat ) * sin( long )
00676             // decode Y as sin( lat ) * sin( long )
00677             // decode Z as cos( long )
00678 
00679             outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
00680             outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
00681             outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
00682 
00683             vec_ste(newNormalsFloatVec,0,outXyz);
00684             vec_ste(newNormalsFloatVec,4,outXyz);
00685             vec_ste(newNormalsFloatVec,8,outXyz);
00686         }
00687         
00688 #else
00689         //
00690         // just copy the vertexes
00691         //
00692         for (vertNum=0 ; vertNum < numVerts ; vertNum++,
00693             newXyz += 4, newNormals += 4,
00694             outXyz += 4, outNormal += 4) 
00695         {
00696 
00697             outXyz[0] = newXyz[0] * newXyzScale;
00698             outXyz[1] = newXyz[1] * newXyzScale;
00699             outXyz[2] = newXyz[2] * newXyzScale;
00700 
00701             lat = ( newNormals[0] >> 8 ) & 0xff;
00702             lng = ( newNormals[0] & 0xff );
00703             lat *= (FUNCTABLE_SIZE/256);
00704             lng *= (FUNCTABLE_SIZE/256);
00705 
00706             // decode X as cos( lat ) * sin( long )
00707             // decode Y as sin( lat ) * sin( long )
00708             // decode Z as cos( long )
00709 
00710             outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
00711             outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
00712             outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
00713         }
00714 #endif
00715     } else {
00716         //
00717         // interpolate and copy the vertex and normal
00718         //
00719         oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
00720             + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
00721         oldNormals = oldXyz + 3;
00722 
00723         oldXyzScale = MD3_XYZ_SCALE * backlerp;
00724         oldNormalScale = backlerp;
00725 
00726         for (vertNum=0 ; vertNum < numVerts ; vertNum++,
00727             oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
00728             outXyz += 4, outNormal += 4) 
00729         {
00730             vec3_t uncompressedOldNormal, uncompressedNewNormal;
00731 
00732             // interpolate the xyz
00733             outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
00734             outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
00735             outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
00736 
00737             // FIXME: interpolate lat/long instead?
00738             lat = ( newNormals[0] >> 8 ) & 0xff;
00739             lng = ( newNormals[0] & 0xff );
00740             lat *= 4;
00741             lng *= 4;
00742             uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
00743             uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
00744             uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
00745 
00746             lat = ( oldNormals[0] >> 8 ) & 0xff;
00747             lng = ( oldNormals[0] & 0xff );
00748             lat *= 4;
00749             lng *= 4;
00750 
00751             uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
00752             uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
00753             uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
00754 
00755             outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
00756             outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
00757             outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
00758 
00759 //          VectorNormalize (outNormal);
00760         }
00761         VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
00762     }
00763 }
00764 
00765 /*
00766 =============
00767 RB_SurfaceMesh
00768 =============
00769 */
00770 void RB_SurfaceMesh(md3Surface_t *surface) {
00771     int             j;
00772     float           backlerp;
00773     int             *triangles;
00774     float           *texCoords;
00775     int             indexes;
00776     int             Bob, Doug;
00777     int             numVerts;
00778 
00779     if (  backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
00780         backlerp = 0;
00781     } else  {
00782         backlerp = backEnd.currentEntity->e.backlerp;
00783     }
00784 
00785     RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 );
00786 
00787     LerpMeshVertexes (surface, backlerp);
00788 
00789     triangles = (int *) ((byte *)surface + surface->ofsTriangles);
00790     indexes = surface->numTriangles * 3;
00791     Bob = tess.numIndexes;
00792     Doug = tess.numVertexes;
00793     for (j = 0 ; j < indexes ; j++) {
00794         tess.indexes[Bob + j] = Doug + triangles[j];
00795     }
00796     tess.numIndexes += indexes;
00797 
00798     texCoords = (float *) ((byte *)surface + surface->ofsSt);
00799 
00800     numVerts = surface->numVerts;
00801     for ( j = 0; j < numVerts; j++ ) {
00802         tess.texCoords[Doug + j][0][0] = texCoords[j*2+0];
00803         tess.texCoords[Doug + j][0][1] = texCoords[j*2+1];
00804         // FIXME: fill in lightmapST for completeness?
00805     }
00806 
00807     tess.numVertexes += surface->numVerts;
00808 
00809 }
00810 
00811 
00812 /*
00813 ==============
00814 RB_SurfaceFace
00815 ==============
00816 */
00817 void RB_SurfaceFace( srfSurfaceFace_t *surf ) {
00818     int         i;
00819     unsigned    *indices, *tessIndexes;
00820     float       *v;
00821     float       *normal;
00822     int         ndx;
00823     int         Bob;
00824     int         numPoints;
00825     int         dlightBits;
00826 
00827     RB_CHECKOVERFLOW( surf->numPoints, surf->numIndices );
00828 
00829     dlightBits = surf->dlightBits[backEnd.smpFrame];
00830     tess.dlightBits |= dlightBits;
00831 
00832     indices = ( unsigned * ) ( ( ( char  * ) surf ) + surf->ofsIndices );
00833 
00834     Bob = tess.numVertexes;
00835     tessIndexes = tess.indexes + tess.numIndexes;
00836     for ( i = surf->numIndices-1 ; i >= 0  ; i-- ) {
00837         tessIndexes[i] = indices[i] + Bob;
00838     }
00839 
00840     tess.numIndexes += surf->numIndices;
00841 
00842     v = surf->points[0];
00843 
00844     ndx = tess.numVertexes;
00845 
00846     numPoints = surf->numPoints;
00847 
00848     if ( tess.shader->needsNormal ) {
00849         normal = surf->plane.normal;
00850         for ( i = 0, ndx = tess.numVertexes; i < numPoints; i++, ndx++ ) {
00851             VectorCopy( normal, tess.normal[ndx] );
00852         }
00853     }
00854 
00855     for ( i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++ ) {
00856         VectorCopy( v, tess.xyz[ndx]);
00857         tess.texCoords[ndx][0][0] = v[3];
00858         tess.texCoords[ndx][0][1] = v[4];
00859         tess.texCoords[ndx][1][0] = v[5];
00860         tess.texCoords[ndx][1][1] = v[6];
00861         * ( unsigned int * ) &tess.vertexColors[ndx] = * ( unsigned int * ) &v[7];
00862         tess.vertexDlightBits[ndx] = dlightBits;
00863     }
00864 
00865 
00866     tess.numVertexes += surf->numPoints;
00867 }
00868 
00869 
00870 static float    LodErrorForVolume( vec3_t local, float radius ) {
00871     vec3_t      world;
00872     float       d;
00873 
00874     // never let it go negative
00875     if ( r_lodCurveError->value < 0 ) {
00876         return 0;
00877     }
00878 
00879     world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] + 
00880         local[2] * backEnd.or.axis[2][0] + backEnd.or.origin[0];
00881     world[1] = local[0] * backEnd.or.axis[0][1] + local[1] * backEnd.or.axis[1][1] + 
00882         local[2] * backEnd.or.axis[2][1] + backEnd.or.origin[1];
00883     world[2] = local[0] * backEnd.or.axis[0][2] + local[1] * backEnd.or.axis[1][2] + 
00884         local[2] * backEnd.or.axis[2][2] + backEnd.or.origin[2];
00885 
00886     VectorSubtract( world, backEnd.viewParms.or.origin, world );
00887     d = DotProduct( world, backEnd.viewParms.or.axis[0] );
00888 
00889     if ( d < 0 ) {
00890         d = -d;
00891     }
00892     d -= radius;
00893     if ( d < 1 ) {
00894         d = 1;
00895     }
00896 
00897     return r_lodCurveError->value / d;
00898 }
00899 
00900 /*
00901 =============
00902 RB_SurfaceGrid
00903 
00904 Just copy the grid of points and triangulate
00905 =============
00906 */
00907 void RB_SurfaceGrid( srfGridMesh_t *cv ) {
00908     int     i, j;
00909     float   *xyz;
00910     float   *texCoords;
00911     float   *normal;
00912     unsigned char *color;
00913     drawVert_t  *dv;
00914     int     rows, irows, vrows;
00915     int     used;
00916     int     widthTable[MAX_GRID_SIZE];
00917     int     heightTable[MAX_GRID_SIZE];
00918     float   lodError;
00919     int     lodWidth, lodHeight;
00920     int     numVertexes;
00921     int     dlightBits;
00922     int     *vDlightBits;
00923     qboolean    needsNormal;
00924 
00925     dlightBits = cv->dlightBits[backEnd.smpFrame];
00926     tess.dlightBits |= dlightBits;
00927 
00928     // determine the allowable discrepance
00929     lodError = LodErrorForVolume( cv->lodOrigin, cv->lodRadius );
00930 
00931     // determine which rows and columns of the subdivision
00932     // we are actually going to use
00933     widthTable[0] = 0;
00934     lodWidth = 1;
00935     for ( i = 1 ; i < cv->width-1 ; i++ ) {
00936         if ( cv->widthLodError[i] <= lodError ) {
00937             widthTable[lodWidth] = i;
00938             lodWidth++;
00939         }
00940     }
00941     widthTable[lodWidth] = cv->width-1;
00942     lodWidth++;
00943 
00944     heightTable[0] = 0;
00945     lodHeight = 1;
00946     for ( i = 1 ; i < cv->height-1 ; i++ ) {
00947         if ( cv->heightLodError[i] <= lodError ) {
00948             heightTable[lodHeight] = i;
00949             lodHeight++;
00950         }
00951     }
00952     heightTable[lodHeight] = cv->height-1;
00953     lodHeight++;
00954 
00955 
00956     // very large grids may have more points or indexes than can be fit
00957     // in the tess structure, so we may have to issue it in multiple passes
00958 
00959     used = 0;
00960     rows = 0;
00961     while ( used < lodHeight - 1 ) {
00962         // see how many rows of both verts and indexes we can add without overflowing
00963         do {
00964             vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth;
00965             irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 );
00966 
00967             // if we don't have enough space for at least one strip, flush the buffer
00968             if ( vrows < 2 || irows < 1 ) {
00969                 RB_EndSurface();
00970                 RB_BeginSurface(tess.shader, tess.fogNum );
00971             } else {
00972                 break;
00973             }
00974         } while ( 1 );
00975         
00976         rows = irows;
00977         if ( vrows < irows + 1 ) {
00978             rows = vrows - 1;
00979         }
00980         if ( used + rows > lodHeight ) {
00981             rows = lodHeight - used;
00982         }
00983 
00984         numVertexes = tess.numVertexes;
00985 
00986         xyz = tess.xyz[numVertexes];
00987         normal = tess.normal[numVertexes];
00988         texCoords = tess.texCoords[numVertexes][0];
00989         color = ( unsigned char * ) &tess.vertexColors[numVertexes];
00990         vDlightBits = &tess.vertexDlightBits[numVertexes];
00991         needsNormal = tess.shader->needsNormal;
00992 
00993         for ( i = 0 ; i < rows ; i++ ) {
00994             for ( j = 0 ; j < lodWidth ; j++ ) {
00995                 dv = cv->verts + heightTable[ used + i ] * cv->width
00996                     + widthTable[ j ];
00997 
00998                 xyz[0] = dv->xyz[0];
00999                 xyz[1] = dv->xyz[1];
01000                 xyz[2] = dv->xyz[2];
01001                 texCoords[0] = dv->st[0];
01002                 texCoords[1] = dv->st[1];
01003                 texCoords[2] = dv->lightmap[0];
01004                 texCoords[3] = dv->lightmap[1];
01005                 if ( needsNormal ) {
01006                     normal[0] = dv->normal[0];
01007                     normal[1] = dv->normal[1];
01008                     normal[2] = dv->normal[2];
01009                 }
01010                 * ( unsigned int * ) color = * ( unsigned int * ) dv->color;
01011                 *vDlightBits++ = dlightBits;
01012                 xyz += 4;
01013                 normal += 4;
01014                 texCoords += 4;
01015                 color += 4;
01016             }
01017         }
01018 
01019 
01020         // add the indexes
01021         {
01022             int     numIndexes;
01023             int     w, h;
01024 
01025             h = rows - 1;
01026             w = lodWidth - 1;
01027             numIndexes = tess.numIndexes;
01028             for (i = 0 ; i < h ; i++) {
01029                 for (j = 0 ; j < w ; j++) {
01030                     int     v1, v2, v3, v4;
01031             
01032                     // vertex order to be reckognized as tristrips
01033                     v1 = numVertexes + i*lodWidth + j + 1;
01034                     v2 = v1 - 1;
01035                     v3 = v2 + lodWidth;
01036                     v4 = v3 + 1;
01037 
01038                     tess.indexes[numIndexes] = v2;
01039                     tess.indexes[numIndexes+1] = v3;
01040                     tess.indexes[numIndexes+2] = v1;
01041                     
01042                     tess.indexes[numIndexes+3] = v1;
01043                     tess.indexes[numIndexes+4] = v3;
01044                     tess.indexes[numIndexes+5] = v4;
01045                     numIndexes += 6;
01046                 }
01047             }
01048 
01049             tess.numIndexes = numIndexes;
01050         }
01051 
01052         tess.numVertexes += rows * lodWidth;
01053 
01054         used += rows - 1;
01055     }
01056 }
01057 
01058 
01059 /*
01060 =============================================================