📄 tr_surface.c
字号:
for ( i = 0; i < 4; i++ )
{
c = cos( DEG2RAD( 45 + i * 90 ) );
s = sin( DEG2RAD( 45 + i * 90 ) );
v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth;
v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth;
v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth;
VectorAdd( start, v, pos[i] );
if ( numSegs > 1 )
{
// offset by 1 segment if we're doing a long distance shot
VectorAdd( pos[i], dir, pos[i] );
}
}
for ( i = 0; i < numSegs; i++ )
{
int j;
RB_CHECKOVERFLOW( 4, 6 );
for ( j = 0; j < 4; j++ )
{
VectorCopy( pos[j], tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0][0] = ( j < 2 );
tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 );
tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
tess.numVertexes++;
VectorAdd( pos[j], dir, pos[j] );
}
tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0;
tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2;
}
}
/*
** RB_SurfaceRailRinges
*/
void RB_SurfaceRailRings( void ) {
refEntity_t *e;
int numSegs;
int len;
vec3_t vec;
vec3_t right, up;
vec3_t start, end;
e = &backEnd.currentEntity->e;
VectorCopy( e->oldorigin, start );
VectorCopy( e->origin, end );
// compute variables
VectorSubtract( end, start, vec );
len = VectorNormalize( vec );
MakeNormalVectors( vec, right, up );
numSegs = ( len ) / r_railSegmentLength->value;
if ( numSegs <= 0 ) {
numSegs = 1;
}
VectorScale( vec, r_railSegmentLength->value, vec );
DoRailDiscs( numSegs, start, vec, right, up );
}
/*
** RB_SurfaceRailCore
*/
void RB_SurfaceRailCore( void ) {
refEntity_t *e;
int len;
vec3_t right;
vec3_t vec;
vec3_t start, end;
vec3_t v1, v2;
e = &backEnd.currentEntity->e;
VectorCopy( e->oldorigin, start );
VectorCopy( e->origin, end );
VectorSubtract( end, start, vec );
len = VectorNormalize( vec );
// compute side vector
VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
VectorNormalize( v1 );
VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
VectorNormalize( v2 );
CrossProduct( v1, v2, right );
VectorNormalize( right );
DoRailCore( start, end, right, len, r_railCoreWidth->integer );
}
/*
** RB_SurfaceLightningBolt
*/
void RB_SurfaceLightningBolt( void ) {
refEntity_t *e;
int len;
vec3_t right;
vec3_t vec;
vec3_t start, end;
vec3_t v1, v2;
int i;
e = &backEnd.currentEntity->e;
VectorCopy( e->oldorigin, end );
VectorCopy( e->origin, start );
// compute variables
VectorSubtract( end, start, vec );
len = VectorNormalize( vec );
// compute side vector
VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
VectorNormalize( v1 );
VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
VectorNormalize( v2 );
CrossProduct( v1, v2, right );
VectorNormalize( right );
for ( i = 0 ; i < 4 ; i++ ) {
vec3_t temp;
DoRailCore( start, end, right, len, 8 );
RotatePointAroundVector( temp, vec, right, 45 );
VectorCopy( temp, right );
}
}
/*
** VectorArrayNormalize
*
* The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
* This means that we don't have to worry about zero length or enormously long vectors.
*/
static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
{
// assert(count);
#if idppc
{
register float half = 0.5;
register float one = 1.0;
float *components = (float *)normals;
// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
// runs *much* faster than calling sqrt(). We'll use a single Newton-Raphson
// refinement step to get a little more precision. This seems to yeild results
// that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5).
// (That is, for the given input range of about 0.6 to 2.0).
do {
float x, y, z;
float B, y0, y1;
x = components[0];
y = components[1];
z = components[2];
components += 4;
B = x*x + y*y + z*z;
#ifdef __GNUC__
asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
#else
y0 = __frsqrte(B);
#endif
y1 = y0 + half*y0*(one - B*y0*y0);
x = x * y1;
y = y * y1;
components[-4] = x;
z = z * y1;
components[-3] = y;
components[-2] = z;
} while(count--);
}
#else // No assembly version for this architecture, or C_ONLY defined
// given the input, it's safe to call VectorNormalizeFast
while (count--) {
VectorNormalizeFast(normals[0]);
normals++;
}
#endif
}
/*
** LerpMeshVertexes
*/
static void LerpMeshVertexes (md3Surface_t *surf, float backlerp)
{
short *oldXyz, *newXyz, *oldNormals, *newNormals;
float *outXyz, *outNormal;
float oldXyzScale, newXyzScale;
float oldNormalScale, newNormalScale;
int vertNum;
unsigned lat, lng;
int numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
+ (backEnd.currentEntity->e.frame * surf->numVerts * 4);
newNormals = newXyz + 3;
newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
newNormalScale = 1.0 - backlerp;
numVerts = surf->numVerts;
if ( backlerp == 0 ) {
#if idppc_altivec
vector signed short newNormalsVec0;
vector signed short newNormalsVec1;
vector signed int newNormalsIntVec;
vector float newNormalsFloatVec;
vector float newXyzScaleVec;
vector unsigned char newNormalsLoadPermute;
vector unsigned char newNormalsStorePermute;
vector float zero;
newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
newXyzScaleVec = *(vector float *)&newXyzScale;
newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
newXyzScaleVec = vec_splat(newXyzScaleVec,0);
newNormalsLoadPermute = vec_lvsl(0,newXyz);
newNormalsStorePermute = vec_lvsr(0,outXyz);
zero = (vector float)vec_splat_s8(0);
//
// just copy the vertexes
//
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
newXyz += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
newNormalsLoadPermute = vec_lvsl(0,newXyz);
newNormalsStorePermute = vec_lvsr(0,outXyz);
newNormalsVec0 = vec_ld(0,newXyz);
newNormalsVec1 = vec_ld(16,newXyz);
newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
newNormalsIntVec = vec_unpackh(newNormalsVec0);
newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
//outXyz[0] = newXyz[0] * newXyzScale;
//outXyz[1] = newXyz[1] * newXyzScale;
//outXyz[2] = newXyz[2] * newXyzScale;
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
vec_ste(newNormalsFloatVec,0,outXyz);
vec_ste(newNormalsFloatVec,4,outXyz);
vec_ste(newNormalsFloatVec,8,outXyz);
}
#else
//
// just copy the vertexes
//
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
newXyz += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
outXyz[0] = newXyz[0] * newXyzScale;
outXyz[1] = newXyz[1] * newXyzScale;
outXyz[2] = newXyz[2] * newXyzScale;
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
}
#endif
} else {
//
// interpolate and copy the vertex and normal
//
oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
+ (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
oldNormals = oldXyz + 3;
oldXyzScale = MD3_XYZ_SCALE * backlerp;
oldNormalScale = backlerp;
for (vertNum=0 ; vertNum < numVerts ; vertNum++,
oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
outXyz += 4, outNormal += 4)
{
vec3_t uncompressedOldNormal, uncompressedNewNormal;
// interpolate the xyz
outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
// FIXME: interpolate lat/long instead?
lat = ( newNormals[0] >> 8 ) & 0xff;
lng = ( newNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
lat = ( oldNormals[0] >> 8 ) & 0xff;
lng = ( oldNormals[0] & 0xff );
lat *= 4;
lng *= 4;
uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
// VectorNormalize (outNormal);
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
}
}
/*
=============
RB_SurfaceMesh
=============
*/
void RB_SurfaceMesh(md3Surface_t *surface) {
int j;
float backlerp;
int *triangles;
float *texCoords;
int indexes;
int Bob, Doug;
int numVerts;
if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
backlerp = 0;
} else {
backlerp = backEnd.currentEntity->e.backlerp;
}
RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 );
LerpMeshVertexes (surface, backlerp);
triangles = (int *) ((byte *)surface + surface->ofsTriangles);
indexes = surface->numTriangles * 3;
Bob = tess.numIndexes;
Doug = tess.numVertexes;
for (j = 0 ; j < indexes ; j++) {
tess.indexes[Bob + j] = Doug + triangles[j];
}
tess.numIndexes += indexes;
texCoords = (float *) ((byte *)surface + surface->ofsSt);
numVerts = surface->numVerts;
for ( j = 0; j < numVerts; j++ ) {
tess.texCoords[Doug + j][0][0] = texCoords[j*2+0];
tess.texCoords[Doug + j][0][1] = texCoords[j*2+1];
// FIXME: fill in lightmapST for completeness?
}
tess.numVertexes += surface->numVerts;
}
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -