ioquake3 porting

This commit is contained in:
OM 2023-05-24 19:03:05 +02:00
parent 2704b798e2
commit ca3340b158
449 changed files with 104109 additions and 77701 deletions

View file

@ -0,0 +1,523 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "tr_local.h"
/*
All bones should be an identity orientation to display the mesh exactly
as it is specified.
For all other frames, the bones represent the transformation from the
orientation of the bone in the base frame to the orientation in this
frame.
*/
// copied and adapted from tr_mesh.c
/*
=============
R_MDRCullModel
=============
*/
static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) {
vec3_t bounds[2];
mdrFrame_t *oldFrame, *newFrame;
int i, frameSize;
frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
// compute frame pointers
newFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
oldFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.oldframe);
// cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes )
{
if ( ent->e.frame == ent->e.oldframe )
{
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
// Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend
// we do. After all, the purpose of mdrs are not that different, are they?
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
case CULL_IN:
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_sphere_cull_md3_clip++;
break;
}
}
else
{
int sphereCull, sphereCullB;
sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
if ( newFrame == oldFrame ) {
sphereCullB = sphereCull;
} else {
sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
}
if ( sphereCull == sphereCullB )
{
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
}
else if ( sphereCull == CULL_IN )
{
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
}
else
{
tr.pc.c_sphere_cull_md3_clip++;
}
}
}
}
// calculate a bounding box in the current coordinate system
for (i = 0 ; i < 3 ; i++) {
bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
}
switch ( R_CullLocalBox( bounds ) )
{
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
return CULL_CLIP;
case CULL_OUT:
default:
tr.pc.c_box_cull_md3_out++;
return CULL_OUT;
}
}
/*
=================
R_MDRComputeFogNum
=================
*/
int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) {
int i, j;
fog_t *fog;
mdrFrame_t *mdrFrame;
vec3_t localOrigin;
int frameSize;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
}
frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
// FIXME: non-normalized axis issues
mdrFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
VectorAdd( ent->e.origin, mdrFrame->localOrigin, localOrigin );
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) {
if ( localOrigin[j] - mdrFrame->radius >= fog->bounds[1][j] ) {
break;
}
if ( localOrigin[j] + mdrFrame->radius <= fog->bounds[0][j] ) {
break;
}
}
if ( j == 3 ) {
return i;
}
}
return 0;
}
/*
==============
R_MDRAddAnimSurfaces
==============
*/
// much stuff in there is just copied from R_AddMd3Surfaces in tr_mesh.c
void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
mdrHeader_t *header;
mdrSurface_t *surface;
mdrLOD_t *lod;
shader_t *shader;
skin_t *skin;
int i, j;
int lodnum = 0;
int fogNum = 0;
int cull;
int cubemapIndex;
qboolean personalModel;
header = (mdrHeader_t *) tr.currentModel->modelData;
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal
|| (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)));
if ( ent->e.renderfx & RF_WRAP_FRAMES )
{
ent->e.frame %= header->numFrames;
ent->e.oldframe %= header->numFrames;
}
//
// Validate the frames so there is no chance of a crash.
// This will write directly into the entity structure, so
// when the surfaces are rendered, they don't need to be
// range checked again.
//
if ((ent->e.frame >= header->numFrames)
|| (ent->e.frame < 0)
|| (ent->e.oldframe >= header->numFrames)
|| (ent->e.oldframe < 0) )
{
ri.Printf( PRINT_DEVELOPER, "R_MDRAddAnimSurfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame, tr.currentModel->name );
ent->e.frame = 0;
ent->e.oldframe = 0;
}
//
// cull the entire model if merged bounding box of both frames
// is outside the view frustum.
//
cull = R_MDRCullModel (header, ent);
if ( cull == CULL_OUT ) {
return;
}
// figure out the current LOD of the model we're rendering, and set the lod pointer respectively.
lodnum = R_ComputeLOD(ent);
// check whether this model has as that many LODs at all. If not, try the closest thing we got.
if(header->numLODs <= 0)
return;
if(header->numLODs <= lodnum)
lodnum = header->numLODs - 1;
lod = (mdrLOD_t *)( (byte *)header + header->ofsLODs);
for(i = 0; i < lodnum; i++)
{
lod = (mdrLOD_t *) ((byte *) lod + lod->ofsEnd);
}
// set up lighting
if ( !personalModel || r_shadows->integer > 1 )
{
R_SetupEntityLighting( &tr.refdef, ent );
}
// fogNum?
fogNum = R_MDRComputeFogNum( header, ent );
cubemapIndex = R_CubemapForPoint(ent->e.origin);
surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++ )
{
if(ent->e.customShader)
shader = R_GetShaderByHandle(ent->e.customShader);
else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
{
skin = R_GetSkinByHandle(ent->e.customSkin);
shader = tr.defaultShader;
for(j = 0; j < skin->numSurfaces; j++)
{
if (!strcmp(skin->surfaces[j].name, surface->name))
{
shader = skin->surfaces[j].shader;
break;
}
}
}
else if(surface->shaderIndex > 0)
shader = R_GetShaderByHandle( surface->shaderIndex );
else
shader = tr.defaultShader;
// we will add shadows even if the main object isn't visible in the view
// stencil shadows can't do personal models unless I polyhedron clip
if ( !personalModel
&& r_shadows->integer == 2
&& fogNum == 0
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
&& shader->sort == SS_OPAQUE )
{
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, qfalse, 0 );
}
// projection shadows work fine with personal models
if ( r_shadows->integer == 3
&& fogNum == 0
&& (ent->e.renderfx & RF_SHADOW_PLANE )
&& shader->sort == SS_OPAQUE )
{
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0 );
}
if (!personalModel)
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse, cubemapIndex );
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
}
}
/*
==============
RB_MDRSurfaceAnim
==============
*/
void RB_MDRSurfaceAnim( mdrSurface_t *surface )
{
int i, j, k;
float frontlerp, backlerp;
int *triangles;
int indexes;
int baseIndex, baseVertex;
int numVerts;
mdrVertex_t *v;
mdrHeader_t *header;
mdrFrame_t *frame;
mdrFrame_t *oldFrame;
mdrBone_t bones[MDR_MAX_BONES], *bonePtr, *bone;
int frameSize;
// don't lerp if lerping off, or this is the only frame, or the last frame...
//
if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame)
{
backlerp = 0; // if backlerp is 0, lerping is off and frontlerp is never used
frontlerp = 1;
}
else
{
backlerp = backEnd.currentEntity->e.backlerp;
frontlerp = 1.0f - backlerp;
}
header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader);
frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
frame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
backEnd.currentEntity->e.frame * frameSize );
oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
backEnd.currentEntity->e.oldframe * frameSize );
RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles * 3 );
triangles = (int *) ((byte *)surface + surface->ofsTriangles);
indexes = surface->numTriangles * 3;
baseIndex = tess.numIndexes;
baseVertex = tess.numVertexes;
// Set up all triangles.
for (j = 0 ; j < indexes ; j++)
{
tess.indexes[baseIndex + j] = baseVertex + triangles[j];
}
tess.numIndexes += indexes;
//
// lerp all the needed bones
//
if ( !backlerp )
{
// no lerping needed
bonePtr = frame->bones;
}
else
{
bonePtr = bones;
for ( i = 0 ; i < header->numBones*12 ; i++ )
{
((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i];
}
}
//
// deform the vertexes by the lerped bones
//
numVerts = surface->numVerts;
v = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts);
for ( j = 0; j < numVerts; j++ )
{
vec3_t tempVert, tempNormal;
mdrWeight_t *w;
VectorClear( tempVert );
VectorClear( tempNormal );
w = v->weights;
for ( k = 0 ; k < v->numWeights ; k++, w++ )
{
bone = bonePtr + w->boneIndex;
tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
}
tess.xyz[baseVertex + j][0] = tempVert[0];
tess.xyz[baseVertex + j][1] = tempVert[1];
tess.xyz[baseVertex + j][2] = tempVert[2];
R_VaoPackNormal(tess.normal[baseVertex + j], tempNormal);
tess.texCoords[baseVertex + j][0] = v->texCoords[0];
tess.texCoords[baseVertex + j][1] = v->texCoords[1];
v = (mdrVertex_t *)&v->weights[v->numWeights];
}
tess.numVertexes += surface->numVerts;
}
#define MC_MASK_X ((1<<(MC_BITS_X))-1)
#define MC_MASK_Y ((1<<(MC_BITS_Y))-1)
#define MC_MASK_Z ((1<<(MC_BITS_Z))-1)
#define MC_MASK_VECT ((1<<(MC_BITS_VECT))-1)
#define MC_SCALE_VECT (1.0f/(float)((1<<(MC_BITS_VECT-1))-2))
#define MC_POS_X (0)
#define MC_SHIFT_X (0)
#define MC_POS_Y ((((MC_BITS_X))/8))
#define MC_SHIFT_Y ((((MC_BITS_X)%8)))
#define MC_POS_Z ((((MC_BITS_X+MC_BITS_Y))/8))
#define MC_SHIFT_Z ((((MC_BITS_X+MC_BITS_Y)%8)))
#define MC_POS_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z))/8))
#define MC_SHIFT_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z)%8)))
#define MC_POS_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT))/8))
#define MC_SHIFT_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT)%8)))
#define MC_POS_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2))/8))
#define MC_SHIFT_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2)%8)))
#define MC_POS_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3))/8))
#define MC_SHIFT_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3)%8)))
#define MC_POS_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4))/8))
#define MC_SHIFT_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4)%8)))
#define MC_POS_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5))/8))
#define MC_SHIFT_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5)%8)))
#define MC_POS_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6))/8))
#define MC_SHIFT_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6)%8)))
#define MC_POS_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7))/8))
#define MC_SHIFT_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7)%8)))
#define MC_POS_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8))/8))
#define MC_SHIFT_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8)%8)))
void MC_UnCompress(float mat[3][4],const unsigned char * comp)
{
int val;
val=(int)((unsigned short *)(comp))[0];
val-=1<<(MC_BITS_X-1);
mat[0][3]=((float)(val))*MC_SCALE_X;
val=(int)((unsigned short *)(comp))[1];
val-=1<<(MC_BITS_Y-1);
mat[1][3]=((float)(val))*MC_SCALE_Y;
val=(int)((unsigned short *)(comp))[2];
val-=1<<(MC_BITS_Z-1);
mat[2][3]=((float)(val))*MC_SCALE_Z;
val=(int)((unsigned short *)(comp))[3];
val-=1<<(MC_BITS_VECT-1);
mat[0][0]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[4];
val-=1<<(MC_BITS_VECT-1);
mat[0][1]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[5];
val-=1<<(MC_BITS_VECT-1);
mat[0][2]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[6];
val-=1<<(MC_BITS_VECT-1);
mat[1][0]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[7];
val-=1<<(MC_BITS_VECT-1);
mat[1][1]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[8];
val-=1<<(MC_BITS_VECT-1);
mat[1][2]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[9];
val-=1<<(MC_BITS_VECT-1);
mat[2][0]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[10];
val-=1<<(MC_BITS_VECT-1);
mat[2][1]=((float)(val))*MC_SCALE_VECT;
val=(int)((unsigned short *)(comp))[11];
val-=1<<(MC_BITS_VECT-1);
mat[2][2]=((float)(val))*MC_SCALE_VECT;
}

View file

@ -517,6 +517,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
{
// hack the depth range to prevent view model from poking into walls
depthRange = qtrue;
if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
isCrosshair = qtrue;
}
} else {
backEnd.currentEntity = &tr.worldEntity;

View file

@ -270,10 +270,10 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
tr.numLightmaps = numLightmaps;
}
tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *) );
tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low );
if (tr.worldDeluxeMapping)
tr.deluxemaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *) );
tr.deluxemaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low );
textureInternalFormat = GL_RGBA8;
if (r_hdr->integer)
@ -584,7 +584,7 @@ static void R_LoadVisibility( lump_t *l ) {
} else {
byte *dest;
dest = ri.Hunk_Alloc( len - 8 );
dest = ri.Hunk_Alloc( len - 8, h_low );
Com_Memcpy( dest, buf + 8, len - 8 );
s_worldData.vis = dest;
}
@ -719,15 +719,15 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors,
numIndexes = LittleLong(ds->numIndexes);
//cv = ri.Hunk_Alloc(sizeof(*cv));
//cv = ri.Hunk_Alloc(sizeof(*cv), h_low);
cv = (void *)surf->data;
cv->surfaceType = SF_FACE;
cv->numIndexes = numIndexes;
cv->indexes = ri.Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]));
cv->indexes = ri.Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]), h_low);
cv->numVerts = numVerts;
cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]));
cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low);
// copy vertexes
surf->cullinfo.type = CULLINFO_PLANE | CULLINFO_BOX;
@ -880,15 +880,15 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColor
numVerts = LittleLong(ds->numVerts);
numIndexes = LittleLong(ds->numIndexes);
//cv = ri.Hunk_Alloc(sizeof(*cv));
//cv = ri.Hunk_Alloc(sizeof(*cv), h_low);
cv = (void *)surf->data;
cv->surfaceType = SF_TRIANGLES;
cv->numIndexes = numIndexes;
cv->indexes = ri.Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]));
cv->indexes = ri.Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]), h_low);
cv->numVerts = numVerts;
cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]));
cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low);
surf->data = (surfaceType_t *) cv;
@ -960,7 +960,7 @@ static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
surf->shader = tr.defaultShader;
}
//flare = ri.Hunk_Alloc( sizeof( *flare ) );
//flare = ri.Hunk_Alloc( sizeof( *flare ), h_low );
flare = (void *)surf->data;
flare->surfaceType = SF_FLARE;
@ -1658,22 +1658,22 @@ void R_MovePatchSurfacesToHunk(void) {
//
copyFrom = grid->widthLodError;
grid->widthLodError = ri.Hunk_Alloc( grid->width * 4 );
grid->widthLodError = ri.Hunk_Alloc( grid->width * 4, h_low );
Com_Memcpy(grid->widthLodError, copyFrom, grid->width * 4);
ri.Free(copyFrom);
copyFrom = grid->heightLodError;
grid->heightLodError = ri.Hunk_Alloc(grid->height * 4);
grid->heightLodError = ri.Hunk_Alloc(grid->height * 4, h_low);
Com_Memcpy(grid->heightLodError, copyFrom, grid->height * 4);
ri.Free(copyFrom);
copyFrom = grid->indexes;
grid->indexes = ri.Hunk_Alloc(grid->numIndexes * sizeof(glIndex_t));
grid->indexes = ri.Hunk_Alloc(grid->numIndexes * sizeof(glIndex_t), h_low);
Com_Memcpy(grid->indexes, copyFrom, grid->numIndexes * sizeof(glIndex_t));
ri.Free(copyFrom);
copyFrom = grid->verts;
grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t));
grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
Com_Memcpy(grid->verts, copyFrom, grid->numVerts * sizeof(srfVert_t));
ri.Free(copyFrom);
}
@ -1712,13 +1712,13 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
if ( indexLump->filelen % sizeof(*indexes))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
out = ri.Hunk_Alloc ( count * sizeof(*out) );
out = ri.Hunk_Alloc ( count * sizeof(*out), h_low );
s_worldData.surfaces = out;
s_worldData.numsurfaces = count;
s_worldData.surfacesViewCount = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesViewCount) );
s_worldData.surfacesDlightBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesDlightBits) );
s_worldData.surfacesPshadowBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesPshadowBits) );
s_worldData.surfacesViewCount = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesViewCount), h_low );
s_worldData.surfacesDlightBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesDlightBits), h_low );
s_worldData.surfacesPshadowBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesPshadowBits), h_low );
// load hdr vertex colors
if (r_hdr->integer)
@ -1748,16 +1748,16 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
for ( i = 0 ; i < count ; i++, in++, out++ ) {
switch ( LittleLong( in->surfaceType ) ) {
case MST_PATCH:
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t));
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low);
break;
case MST_TRIANGLE_SOUP:
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t));
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low);
break;
case MST_PLANAR:
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t));
out->data = ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low);
break;
case MST_FLARE:
out->data = ri.Hunk_Alloc( sizeof(srfFlare_t));
out->data = ri.Hunk_Alloc( sizeof(srfFlare_t), h_low);
break;
default:
break;
@ -1826,7 +1826,7 @@ static void R_LoadSubmodels( lump_t *l ) {
count = l->filelen / sizeof(*in);
s_worldData.numBModels = count;
s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out) );
s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out), h_low );
for ( i=0 ; i<count ; i++, in++, out++ ) {
model_t *model;
@ -1896,7 +1896,7 @@ static void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) {
numNodes = nodeLump->filelen / sizeof(dnode_t);
numLeafs = leafLump->filelen / sizeof(dleaf_t);
out = ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out));
out = ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low);
s_worldData.nodes = out;
s_worldData.numnodes = numNodes + numLeafs;
@ -1966,7 +1966,7 @@ static void R_LoadShaders( lump_t *l ) {
if (l->filelen % sizeof(*in))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
count = l->filelen / sizeof(*in);
out = ri.Hunk_Alloc ( count*sizeof(*out) );
out = ri.Hunk_Alloc ( count*sizeof(*out), h_low );
s_worldData.shaders = out;
s_worldData.numShaders = count;
@ -1995,7 +1995,7 @@ static void R_LoadMarksurfaces (lump_t *l)
if (l->filelen % sizeof(*in))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
count = l->filelen / sizeof(*in);
out = ri.Hunk_Alloc ( count*sizeof(*out));
out = ri.Hunk_Alloc ( count*sizeof(*out), h_low);
s_worldData.marksurfaces = out;
s_worldData.nummarksurfaces = count;
@ -2024,7 +2024,7 @@ static void R_LoadPlanes( lump_t *l ) {
if (l->filelen % sizeof(*in))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
count = l->filelen / sizeof(*in);
out = ri.Hunk_Alloc ( count*2*sizeof(*out));
out = ri.Hunk_Alloc ( count*2*sizeof(*out), h_low);
s_worldData.planes = out;
s_worldData.numplanes = count;
@ -2071,7 +2071,7 @@ static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump ) {
// create fog strucutres for them
s_worldData.numfogs = count + 1;
s_worldData.fogs = ri.Hunk_Alloc ( s_worldData.numfogs*sizeof(*out));
s_worldData.fogs = ri.Hunk_Alloc ( s_worldData.numfogs*sizeof(*out), h_low);
out = s_worldData.fogs + 1;
if ( !count ) {
@ -2195,7 +2195,7 @@ void R_LoadLightGrid( lump_t *l ) {
return;
}
w->lightGridData = ri.Hunk_Alloc( l->filelen );
w->lightGridData = ri.Hunk_Alloc( l->filelen, h_low );
Com_Memcpy( w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen );
// deal with overbright bits
@ -2223,7 +2223,7 @@ void R_LoadLightGrid( lump_t *l ) {
if (size != sizeof(float) * 6 * numGridPoints)
ri.Error(ERR_DROP, "Bad size for %s (%i, expected %i)!", filename, size, (int)(sizeof(float)) * 6 * numGridPoints);
w->lightGrid16 = ri.Hunk_Alloc(sizeof(w->lightGrid16) * 6 * numGridPoints);
w->lightGrid16 = ri.Hunk_Alloc(sizeof(w->lightGrid16) * 6 * numGridPoints, h_low);
for (i = 0; i < numGridPoints ; i++)
{
@ -2249,7 +2249,7 @@ void R_LoadLightGrid( lump_t *l ) {
else if (0)
{
// promote 8-bit lightgrid to 16-bit
w->lightGrid16 = ri.Hunk_Alloc(sizeof(w->lightGrid16) * 6 * numGridPoints);
w->lightGrid16 = ri.Hunk_Alloc(sizeof(w->lightGrid16) * 6 * numGridPoints, h_low);
for (i = 0; i < numGridPoints; i++)
{
@ -2286,7 +2286,7 @@ void R_LoadEntities( lump_t *l ) {
p = (char *)(fileBase + l->fileofs);
// store for reference by the cgame
w->entityString = ri.Hunk_Alloc( l->filelen + 1 );
w->entityString = ri.Hunk_Alloc( l->filelen + 1, h_low );
strcpy( w->entityString, p );
w->entityParsePoint = w->entityString;
@ -2490,7 +2490,7 @@ void R_LoadEnvironmentJson(const char *baseName)
}
tr.numCubemaps = JSON_ArrayGetIndex(cubemapArrayJson, bufferEnd, NULL, 0);
tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps));
tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low);
memset(tr.cubemaps, 0, tr.numCubemaps * sizeof(*tr.cubemaps));
for (i = 0; i < tr.numCubemaps; i++)
@ -2543,7 +2543,7 @@ void R_LoadCubemapEntities(char *cubemapEntityName)
return;
tr.numCubemaps = numCubemaps;
tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps));
tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low);
memset(tr.cubemaps, 0, tr.numCubemaps * sizeof(*tr.cubemaps));
numCubemaps = 0;
@ -2755,7 +2755,7 @@ void RE_LoadWorldMap( const char *name ) {
Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) );
COM_StripExtension(s_worldData.baseName, s_worldData.baseName, sizeof(s_worldData.baseName));
startMarker = ri.Hunk_Alloc(0);
startMarker = ri.Hunk_Alloc(0, h_low);
c_gridVerts = 0;
header = (dheader_t *)buffer.b;
@ -2998,7 +2998,7 @@ void RE_LoadWorldMap( const char *name ) {
}
}
s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0) - startMarker;
s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker;
// only set tr.world now that we know the entire level has loaded properly
tr.world = &s_worldData;

View file

@ -1,451 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_draw.c -- drawing
#include "tr_local.h"
vec4_t r_colorWhite = { 1.0, 1.0, 1.0, 1.0 };
/*
================
Draw_SetColor
================
*/
void Draw_SetColor( const vec4_t rgba ) {
#if 1
if( !rgba ) {
rgba = r_colorWhite;
}
backEnd.color2D[ 0 ] = rgba[ 0 ] * tr.identityLight;
backEnd.color2D[ 1 ] = rgba[ 1 ] * tr.identityLight;
backEnd.color2D[ 2 ] = rgba[ 2 ] * tr.identityLight;
backEnd.color2D[ 3 ] = rgba[ 3 ];
qglColor4fv( backEnd.color2D );
#else
RE_SetColor( rgba );
#endif
}
/*
================
Draw_StretchPic
================
*/
void Draw_StretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader ) {
#if 1
shader_t *shader;
R_SyncRenderThread();
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
} else {
shader = tr.defaultShader;
}
if( w <= 0 ) {
w = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
h = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
}
// draw the pic
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
RB_BeginSurface( shader, 0, 0 );
RB_Texcoord2f( s1, t1 );
RB_Vertex2f( x, y );
RB_Texcoord2f( s2, t1 );
RB_Vertex2f( x + w, y );
RB_Texcoord2f( s1, t2 );
RB_Vertex2f( x, y + h );
RB_Texcoord2f( s2, t2 );
RB_Vertex2f( x + w, y + h );
RB_StreamEnd();
#else
RE_StretchPic( x, y, w, h, s1, t1, s2, t2, hShader );
#endif
}
/*
================
Draw_TilePic
================
*/
void Draw_TilePic( float x, float y, float w, float h , qhandle_t hShader ) {
shader_t *shader;
float picw, pich;
R_SyncRenderThread();
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
}
else {
shader = tr.defaultShader;
}
if( w <= 0 ) {
w = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
h = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
}
picw = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadWidth;
pich = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadHeight;
// draw the pic
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
RB_StreamBegin( shader );
RB_Texcoord2f( x / picw, y / pich );
RB_Vertex2f( x, y );
RB_Texcoord2f( ( x + w ) / picw, y / pich );
RB_Vertex2f( x + w, y );
RB_Texcoord2f( x / picw, ( y + h ) / pich );
RB_Vertex2f( x, y + h );
RB_Texcoord2f( ( x + w ) / picw, ( y + h ) / pich );
RB_Vertex2f( x + w, y + h );
RB_StreamEnd();
}
/*
================
Draw_TilePicOffset
================
*/
void Draw_TilePicOffset( float x, float y, float w, float h, qhandle_t hShader, int offsetX, int offsetY ) {
shader_t *shader;
float picw, pich;
R_SyncRenderThread();
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
} else {
shader = tr.defaultShader;
}
if( w <= 0 ) {
w = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->width;
h = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->height;
}
picw = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadWidth;
pich = shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadHeight;
// draw the pic
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
RB_StreamBegin( shader );
RB_Texcoord2f( x / picw, y / pich );
RB_Vertex2f( x + offsetX, y + offsetY );
RB_Texcoord2f( ( x + w ) / picw, y / pich );
RB_Vertex2f( x + offsetX + w, y + offsetY );
RB_Texcoord2f( x / picw, ( y + h ) / pich );
RB_Vertex2f( x + offsetX, y + offsetY + h );
RB_Texcoord2f( ( x + w ) / picw, ( y + h ) / pich );
RB_Vertex2f( x + offsetX + w, y + offsetY + h );
RB_StreamEnd();
}
/*
================
Draw_TrianglePic
================
*/
void Draw_TrianglePic( const vec2_t vPoints[ 3 ], const vec2_t vTexCoords[ 3 ], qhandle_t hShader ) {
int i;
shader_t *shader;
R_SyncRenderThread();
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
} else {
shader = tr.defaultShader;
}
// draw the pic
RB_Color4f( backEnd.color2D[ 0 ], backEnd.color2D[ 1 ], backEnd.color2D[ 2 ], backEnd.color2D[ 3 ] );
RB_BeginSurface( shader, 0, 0 );
for( i = 0; i < 3; i++ ) {
RB_Texcoord2f( vTexCoords[ i ][ 0 ], vTexCoords[ i ][ 1 ] );
RB_Vertex2f( vPoints[ i ][ 0 ], vPoints[ i ][ 1 ] );
}
RB_StreamEnd();
}
/*
================
RE_DrawBackground_TexSubImage
================
*/
void RE_DrawBackground_TexSubImage( int cols, int rows, int bgr, byte *data ) {
GLenum format;
int w, h;
w = glConfig.vidWidth;
h = glConfig.vidHeight;
R_SyncRenderThread();
qglFinish();
if( bgr ) {
format = GL_BGR_EXT;
} else {
format = GL_RGB;
}
GL_Bind( tr.scratchImage[ 0 ] );
if( cols == tr.scratchImage[ 0 ]->width && rows == tr.scratchImage[ 0 ]->height && format == tr.scratchImage[ 0 ]->internalFormat )
{
qglTexSubImage2D( 3553, 0, 0, 0, cols, rows, format, 5121, data );
}
else
{
tr.scratchImage[ 0 ]->uploadWidth = cols;
tr.scratchImage[ 0 ]->uploadHeight = rows;
tr.scratchImage[ 0 ]->internalFormat = format;
qglTexImage2D( GL_TEXTURE_2D, 0, 3, cols, rows, 0, format, 5121, data );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9729.0 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9729.0 );
}
qglDisable( GL_CULL_FACE );
qglDisable( GL_DEPTH_TEST );
qglEnable( GL_TEXTURE_2D );
qglBegin( GL_QUADS );
qglTexCoord2f( 0.5 / ( GLfloat )cols, ( ( GLfloat )rows - 0.5 ) / rows );
qglVertex2f( 0, 0 );
qglTexCoord2f( ( ( GLfloat )cols - 0.5 ) / cols, ( ( GLfloat )rows - 0.5 ) / rows );
qglVertex2f( w, 0 );
qglTexCoord2f( ( ( GLfloat )cols - 0.5 ) / cols, 0.5 / ( GLfloat )rows );
qglVertex2f( w, h );
qglTexCoord2f( 0.5 / ( GLfloat )rows, 0.5 / ( GLfloat )rows );
qglVertex2f( 0, h );
qglEnd();
}
/*
================
RE_DrawBackground_DrawPixels
================
*/
void RE_DrawBackground_DrawPixels( int cols, int rows, int bgr, byte *data ) {
// FIXME: stub
}
/*
=============
RE_StretchRaw
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
Used for cinematics.
=============
*/
void RE_StretchRaw( int x, int y, int w, int h, int cols, int rows, int components, const byte *data ) {
int i, j;
int start, end;
if (!tr.registered) {
return;
}
R_SyncRenderThread();
// we definately want to sync every frame for the cinematics
qglFinish();
start = end = 0;
if (r_speeds->integer) {
start = ri.Milliseconds();
}
// make sure rows and cols are powers of 2
for (i = 0; (1 << i) < cols; i++) {
}
for (j = 0; (1 << j) < rows; j++) {
}
if ((1 << i) != cols || (1 << j) != rows) {
ri.Error(ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
}
GL_Bind(tr.scratchImage[0]);
// if the scratchImage isn't in the format we want, specify it as a new texture
if (cols != tr.scratchImage[0]->width || rows != tr.scratchImage[0]->height) {
tr.scratchImage[0]->width = tr.scratchImage[0]->uploadWidth = cols;
tr.scratchImage[0]->height = tr.scratchImage[0]->uploadHeight = rows;
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
else {
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
// it and don't try and do a texture compression
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
if (r_speeds->integer) {
end = ri.Milliseconds();
ri.Printf(PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start);
}
RB_SetGL2D();
qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight);
qglBegin(GL_QUADS);
qglTexCoord2f(0.5f / cols, 0.5f / rows);
qglVertex2f(x, y);
qglTexCoord2f((cols - 0.5f) / cols, 0.5f / rows);
qglVertex2f(x + w, y);
qglTexCoord2f((cols - 0.5f) / cols, (rows - 0.5f) / rows);
qglVertex2f(x + w, y + h);
qglTexCoord2f(0.5f / cols, (rows - 0.5f) / rows);
qglVertex2f(x, y + h);
qglEnd();
}
/*
================
AddBox
================
*/
void AddBox( float x, float y, float w, float h ) {
R_SyncRenderThread();
qglColor4fv( backEnd.color2D );
qglDisable( GL_TEXTURE_2D );
GL_State( 0x422 );
qglBegin( GL_QUADS );
qglVertex2f( x, y );
qglVertex2f( x + w, y );
qglVertex2f( x + w, y + h );
qglVertex2f( x, y + h );
qglEnd();
qglEnable( GL_TEXTURE_2D );
}
/*
================
DrawBox
================
*/
void DrawBox( float x, float y, float w, float h ) {
R_SyncRenderThread();
qglColor4fv( backEnd.color2D );
qglDisable( GL_TEXTURE_2D );
GL_State( 0x465 );
qglBegin( GL_QUADS );
qglVertex2f( x, y );
qglVertex2f( x + w, y );
qglVertex2f( x + w, y + h );
qglVertex2f( x, y + h );
qglEnd();
qglEnable( GL_TEXTURE_2D );
}
/*
================
DrawLineLoop
================
*/
void DrawLineLoop( const vec2_t *points, int count, int stipple_factor, int stipple_mask ) {
int i;
R_SyncRenderThread();
qglDisable( GL_TEXTURE_2D );
if( stipple_factor ) {
qglEnable( GL_LINE_STIPPLE );
qglLineStipple( stipple_factor, stipple_mask );
}
qglBegin( GL_LINE_LOOP );
for( i = 0; i < count; i++ ) {
qglVertex2i( points[ i ][ 0 ], points[ i ][ 1 ] );
}
qglEnd();
qglEnable( GL_TEXTURE_2D );
if( stipple_factor ) {
qglDisable( GL_LINE_STIPPLE );
}
}
/*
================
Set2DWindow
================
*/
void Set2DWindow( int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f ) {
// FIXME: unimplemented
}
/*
================
RE_Scissor
================
*/
void RE_Scissor( int x, int y, int width, int height ) {
qglEnable( GL_SCISSOR_TEST );
qglScissor( x, y, width, height );
}

View file

@ -156,6 +156,13 @@ void Mat4SimpleInverse( const mat4_t in, mat4_t out)
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
}
void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c)
{
c[0] = a[0] * (1.0f - lerp) + b[0] * lerp;
c[1] = a[1] * (1.0f - lerp) + b[1] * lerp;
c[2] = a[2] * (1.0f - lerp) + b[2] * lerp;
}
qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2)
{
float radiusSum = radius1 + radius2;

View file

@ -46,6 +46,7 @@ void Mat4SimpleInverse( const mat4_t in, mat4_t out);
#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define VectorSet4(v,x,y,z,w) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w))
#define DotProduct4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
#define VectorScale4(a,b,c) ((c)[0]=(a)[0]*(b),(c)[1]=(a)[1]*(b),(c)[2]=(a)[2]*(b),(c)[3]=(a)[3]*(b))
#define VectorCopy5(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4])
@ -55,6 +56,26 @@ void Mat4SimpleInverse( const mat4_t in, mat4_t out);
#define ByteToFloat(a) ((float)(a) * 1.0f/255.0f)
#define FloatToByte(a) (byte)((a) * 255.0f)
static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2)
{
if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3])
{
return 0;
}
return 1;
}
static ID_INLINE int VectorCompare5(const vec5_t v1, const vec5_t v2)
{
if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3] || v1[4] != v2[4])
{
return 0;
}
return 1;
}
void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c);
qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2);
void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3);

View file

@ -101,7 +101,7 @@ FBO_t *FBO_Create(const char *name, int width, int height)
ri.Error(ERR_DROP, "FBO_Create: MAX_FBOS hit");
}
fbo = tr.fbos[tr.numFBOs] = ri.Hunk_Alloc(sizeof(*fbo));
fbo = tr.fbos[tr.numFBOs] = ri.Hunk_Alloc(sizeof(*fbo), h_low);
Q_strncpyz(fbo->name, name, sizeof(fbo->name));
fbo->index = tr.numFBOs++;
fbo->width = width;
@ -273,10 +273,8 @@ void FBO_Init(void)
if (multisample < 2 || !glRefConfig.framebufferBlit)
multisample = 0;
if (multisample != r_ext_framebuffer_multisample->integer) {
char buf[10];
ri.Cvar_Set("r_ext_framebuffer_multisample", itoa(multisample, buf, 10));
}
if (multisample != r_ext_framebuffer_multisample->integer)
ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample);
// only create a render FBO if we need to resolve MSAA or do HDR
// otherwise just render straight to the screen (tr.renderFbo = NULL)

View file

@ -2121,7 +2121,7 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit");
}
image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ) );
image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low );
qglGenTextures(1, &image->texnum);
tr.numImages++;
@ -3098,7 +3098,7 @@ qhandle_t RE_RegisterSkin( const char *name ) {
return 0;
}
tr.numSkins++;
skin = ri.Hunk_Alloc( sizeof( skin_t ) );
skin = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
tr.skins[hSkin] = skin;
Q_strncpyz( skin->name, name, sizeof( skin->name ) );
skin->numSurfaces = 0;
@ -3108,7 +3108,7 @@ qhandle_t RE_RegisterSkin( const char *name ) {
// If not a .skin file, load as a single shader
if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) {
skin->numSurfaces = 1;
skin->surfaces = ri.Hunk_Alloc( sizeof( skinSurface_t ) );
skin->surfaces = ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low );
skin->surfaces[0].shader = R_FindShader( name, LIGHTMAP_NONE, qtrue );
return hSkin;
}
@ -3166,7 +3166,7 @@ qhandle_t RE_RegisterSkin( const char *name ) {
}
// copy surfaces to skin
skin->surfaces = ri.Hunk_Alloc( skin->numSurfaces * sizeof( skinSurface_t ) );
skin->surfaces = ri.Hunk_Alloc( skin->numSurfaces * sizeof( skinSurface_t ), h_low );
memcpy( skin->surfaces, parseSurfaces, skin->numSurfaces * sizeof( skinSurface_t ) );
return hSkin;
@ -3184,10 +3184,10 @@ void R_InitSkins( void ) {
tr.numSkins = 1;
// make the default skin have all default shaders
skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ) );
skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
Q_strncpyz( skin->name, "<default skin>", sizeof( skin->name ) );
skin->numSurfaces = 1;
skin->surfaces = ri.Hunk_Alloc( sizeof( skinSurface_t ) );
skin->surfaces = ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low );
skin->surfaces[0].shader = tr.defaultShader;
}

View file

@ -33,7 +33,6 @@ float displayAspect = 0.0f;
qboolean haveClampToEdge = qfalse;
glstate_t glState;
int r_sequencenumber;
static void GfxInfo_f( void );
static void GfxMemInfo_f( void );
@ -237,46 +236,6 @@ int max_polys;
cvar_t *r_maxpolyverts;
int max_polyverts;
cvar_t* r_staticlod;
cvar_t* r_lodscale;
cvar_t* r_lodcap;
cvar_t* r_lodviewmodelcap;
cvar_t* r_uselod;
cvar_t* lod_LOD;
cvar_t* lod_minLOD;
cvar_t* lod_maxLOD;
cvar_t* lod_LOD_slider;
cvar_t* lod_curve_0_val;
cvar_t* lod_curve_1_val;
cvar_t* lod_curve_2_val;
cvar_t* lod_curve_3_val;
cvar_t* lod_curve_4_val;
cvar_t* lod_edit_0;
cvar_t* lod_edit_1;
cvar_t* lod_edit_2;
cvar_t* lod_edit_3;
cvar_t* lod_edit_4;
cvar_t* lod_curve_0_slider;
cvar_t* lod_curve_1_slider;
cvar_t* lod_curve_2_slider;
cvar_t* lod_curve_3_slider;
cvar_t* lod_curve_4_slider;
cvar_t* lod_pitch_val;
cvar_t* lod_zee_val;
cvar_t* lod_mesh;
cvar_t* lod_meshname;
cvar_t* lod_tikiname;
cvar_t* lod_metric;
cvar_t* lod_tris;
cvar_t* lod_position;
cvar_t* lod_save;
cvar_t* lod_tool;
cvar_t* r_numdebuglines;
cvar_t* r_showSkeleton;
/*
** InitOpenGL
**
@ -909,6 +868,87 @@ void R_ExportCubemaps_f(void)
//============================================================================
/*
==================
RB_TakeVideoFrameCmd
==================
*/
const void *RB_TakeVideoFrameCmd( const void *data )
{
const videoFrameCommand_t *cmd;
byte *cBuf;
size_t memcount, linelen;
int padwidth, avipadwidth, padlen, avipadlen;
GLint packAlign;
// finish any 2D drawing if needed
if(tess.numIndexes)
RB_EndSurface();
cmd = (const videoFrameCommand_t *)data;
qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
linelen = cmd->width * 3;
// Alignment stuff for glReadPixels
padwidth = PAD(linelen, packAlign);
padlen = padwidth - linelen;
// AVI line padding
avipadwidth = PAD(linelen, AVI_LINE_PADDING);
avipadlen = avipadwidth - linelen;
cBuf = PADP(cmd->captureBuffer, packAlign);
qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB,
GL_UNSIGNED_BYTE, cBuf);
memcount = padwidth * cmd->height;
// gamma correct
if(glConfig.deviceSupportsGamma)
R_GammaCorrect(cBuf, memcount);
if(cmd->motionJpeg)
{
memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height,
r_aviMotionJpegQuality->integer,
cmd->width, cmd->height, cBuf, padlen);
ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount);
}
else
{
byte *lineend, *memend;
byte *srcptr, *destptr;
srcptr = cBuf;
destptr = cmd->encodeBuffer;
memend = srcptr + memcount;
// swap R and B and remove line paddings
while(srcptr < memend)
{
lineend = srcptr + linelen;
while(srcptr < lineend)
{
*destptr++ = srcptr[2];
*destptr++ = srcptr[1];
*destptr++ = srcptr[0];
srcptr += 3;
}
Com_Memset(destptr, '\0', avipadlen);
destptr += avipadlen;
srcptr += padlen;
}
ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height);
}
return (const void *)(cmd + 1);
}
//============================================================================
/*
@ -986,11 +1026,6 @@ void R_PrintLongString(const char *string) {
}
}
const char* RE_GetGraphicsInfo() {
// FIXME: unimplemented
return NULL;
}
/*
================
GfxInfo_f
@ -1074,16 +1109,6 @@ void GfxInfo_f( void )
}
}
qboolean R_SetMode(int mode) {
// FIXME: unimplemented
return qfalse;
}
void R_SetFullscreen(qboolean fullscreen, glconfig_t* config) {
// FIXME: unimplemented
return qfalse;
}
/*
================
GfxMemInfo_f
@ -1170,12 +1195,14 @@ void R_Register( void )
r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue );
r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_ext_multisample = ri.Cvar_Get( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH );
ri.Cvar_CheckRange( r_ext_multisample, 0, 4, qtrue );
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_mode = ri.Cvar_Get( "r_mode", "-2", CVAR_ARCHIVE | CVAR_LATCH );
@ -1190,6 +1217,7 @@ void R_Register( void )
r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse);
r_externalGLSL = ri.Cvar_Get( "r_externalGLSL", "0", CVAR_LATCH );
@ -1256,6 +1284,7 @@ void R_Register( void )
// temporary latched variables that can only change over a restart
//
r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
ri.Cvar_CheckRange( r_displayRefresh, 0, 200, qtrue );
r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
@ -1268,6 +1297,7 @@ void R_Register( void )
r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT );
ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse );
r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE );
r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
@ -1446,7 +1476,7 @@ void R_Init( void ) {
if (max_polyverts < MAX_POLYVERTS)
max_polyverts = MAX_POLYVERTS;
ptr = ri.Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts);
ptr = ri.Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
backEndData = (backEndData_t *) ptr;
backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData ));
backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys);
@ -1549,9 +1579,6 @@ void RE_EndRegistration( void ) {
}
}
void RE_SetRenderTime(int t) {
// FIXME: unimplemented
}
/*
@@@@@@@@@@@@@@@@@@@@@
@ -1579,77 +1606,43 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
// the RE_ functions are Renderer Entry points
re.Shutdown = RE_Shutdown;
re.Shutdown = RE_Shutdown;
re.FreeModels = RE_FreeModels;
re.BeginRegistration = RE_BeginRegistration;
re.EndRegistration = RE_EndRegistration;
re.RegisterModel = RE_RegisterModel;
re.SpawnEffectModel = RE_SpawnEffectModel;
re.RegisterServerModel = RE_RegisterServerModel;
re.UnregisterServerModel = RE_UnregisterServerModel;
re.RegisterShader = RE_RegisterShader;
re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
re.LoadWorld = RE_LoadWorldMap;
re.PrintBSPFileSizes = RE_PrintBSPFileSizes;
re.MapVersion = RE_MapVersion;
re.LoadFont = R_LoadFont;
re.SetWorldVisData = RE_SetWorldVisData;
re.BeginRegistration = RE_BeginRegistration;
re.RegisterModel = RE_RegisterModel;
re.RegisterSkin = RE_RegisterSkin;
re.RegisterShader = RE_RegisterShader;
re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
re.LoadWorld = RE_LoadWorldMap;
re.SetWorldVisData = RE_SetWorldVisData;
re.EndRegistration = RE_EndRegistration;
re.BeginFrame = RE_BeginFrame;
re.EndFrame = RE_EndFrame;
re.BeginFrame = RE_BeginFrame;
re.EndFrame = RE_EndFrame;
re.MarkFragments = R_MarkFragments;
re.MarkFragmentsForInlineModel = R_MarkFragmentsForInlineModel;
re.GetInlineModelBounds = R_GetInlineModelBounds;
re.GetLightingForDecal = R_GetLightingForDecal;
re.GetLightingForSmoke = R_GetLightingForSmoke;
re.R_GatherLightSources = R_GatherLightSources;
re.ModelBounds = R_ModelBounds;
re.ModelRadius = R_ModelRadius;
re.MarkFragments = R_MarkFragments;
re.LerpTag = R_LerpTag;
re.ModelBounds = R_ModelBounds;
re.ClearScene = RE_ClearScene;
re.AddRefEntityToScene = RE_AddRefEntityToScene;
re.AddRefSpriteToScene = RE_AddRefSpriteToScene;
re.AddPolyToScene = RE_AddPolyToScene;
re.AddTerrainMarkToScene = RE_AddTerrainMarkToScene;
re.AddLightToScene = RE_AddLightToScene;
re.RenderScene = RE_RenderScene;
re.GetRenderEntity = RE_GetRenderEntity;
re.ClearScene = RE_ClearScene;
re.AddRefEntityToScene = RE_AddRefEntityToScene;
re.AddPolyToScene = RE_AddPolyToScene;
re.LightForPoint = R_LightForPoint;
re.AddLightToScene = RE_AddLightToScene;
re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene;
re.RenderScene = RE_RenderScene;
re.SavePerformanceCounters = R_SavePerformanceCounters;
re.SetColor = RE_SetColor;
re.DrawStretchPic = RE_StretchPic;
re.DrawStretchRaw = RE_StretchRaw;
re.UploadCinematic = RE_UploadCinematic;
re.R_Model_GetHandle = R_Model_GetHandle;
re.SetColor = Draw_SetColor;
re.DrawStretchPic = Draw_StretchPic;
re.DrawStretchRaw = RE_StretchRaw;
re.DebugLine = R_DebugLine;
re.DrawTilePic = Draw_TilePic;
re.DrawTilePicOffset = Draw_TilePicOffset;
re.DrawTrianglePic = Draw_TrianglePic;
re.DrawBox = DrawBox;
re.AddBox = AddBox;
re.Set2DWindow = Set2DWindow;
re.Scissor = RE_Scissor;
re.DrawLineLoop = DrawLineLoop;
re.DrawString = R_DrawString;
re.GetFontHeight = R_GetFontHeight;
re.GetFontStringWidth = R_GetFontStringWidth;
re.SwipeBegin = RE_SwipeBegin;
re.SwipeEnd = RE_SwipeEnd;
re.SetRenderTime = RE_SetRenderTime;
re.Noise = R_NoiseGet4f;
re.RegisterFont = RE_RegisterFont;
re.RemapShader = R_RemapShader;
re.GetEntityToken = R_GetEntityToken;
re.inPVS = R_inPVS;
re.SetMode = R_SetMode;
re.SetFullscreen = R_SetFullscreen;
re.GetShaderHeight = RE_GetShaderHeight;
re.GetShaderWidth = RE_GetShaderWidth;
re.GetGraphicsInfo = RE_GetGraphicsInfo;
re.ForceUpdatePose = RE_ForceUpdatePose;
re.TIKI_Orientation = RE_TIKI_Orientation;
re.TIKI_IsOnGround = RE_TIKI_IsOnGround;
re.SetFrameNumber = RE_SetFrameNumber;
re.TakeVideoFrame = RE_TakeVideoFrame;
return &re;
}

View file

@ -425,9 +425,9 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
}
// save out the byte packet version
((byte *)&ent->ambientLightInt)[0] = ftol(ent->ambientLight[0]);
((byte *)&ent->ambientLightInt)[1] = ftol(ent->ambientLight[1]);
((byte *)&ent->ambientLightInt)[2] = ftol(ent->ambientLight[2]);
((byte *)&ent->ambientLightInt)[0] = ri.ftol(ent->ambientLight[0]);
((byte *)&ent->ambientLightInt)[1] = ri.ftol(ent->ambientLight[1]);
((byte *)&ent->ambientLightInt)[2] = ri.ftol(ent->ambientLight[2]);
((byte *)&ent->ambientLightInt)[3] = 0xff;
// transform the direction to local space

View file

@ -20,7 +20,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#pragma once
#ifndef TR_LOCAL_H
#define TR_LOCAL_H
#include "../qcommon/q_shared.h"
#include "../qcommon/qfiles.h"
@ -66,101 +68,6 @@ typedef unsigned int glIndex_t;
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
#define PSHADOW_MAP_SIZE 512
typedef struct skelSurfaceGame_s skelSurfaceGame_t;
typedef struct staticSurface_s staticSurface_t;
// any changes in surfaceType must be mirrored in rb_surfaceTable[]
typedef enum {
SF_BAD,
SF_SKIP, // ignore
SF_FACE,
SF_GRID,
SF_POLY,
SF_MARK_FRAG,
SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_DISPLAY_LIST,
SF_TIKI_SKEL,
SF_TIKI_STATIC,
SF_SWIPE,
SF_SPRITE,
SF_TERRAIN_PATCH,
SF_TRIANGLES,
SF_MDV,
SF_MDR,
SF_IQM,
SF_VAO_MDVMESH,
SF_VAO_IQM,
SF_NUM_SURFACE_TYPES,
SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
} surfaceType_t;
typedef struct {
struct mnode_s* cntNode;
qboolean inUse;
struct msurface_s* skySurfs[32];
int numSurfs;
vec3_t offset;
vec3_t mins;
vec3_t maxs;
} portalsky_t;
typedef struct {
vec3_t transformed;
int index;
} sphere_dlight_t;
typedef enum {
LIGHT_POINT,
LIGHT_DIRECTIONAL,
LIGHT_SPOT,
LIGHT_SPOT_FAST
} lighttype_t;
typedef struct reallightinfo_s {
vec3_t color;
lighttype_t eType;
float fIntensity;
float fDist;
float fSpotSlope;
float fSpotConst;
float fSpotScale;
vec3_t vOrigin;
vec3_t vDirection;
} reallightinfo_t;
typedef float cube_entry_t[3][4];
typedef struct {
vec3_t origin;
vec3_t worldOrigin;
vec3_t traceOrigin;
float radius;
struct mnode_s* leaves[8];
void(*TessFunction) ();
union ambient {
unsigned char level[4];
int value;
};
int numRealLights;
reallightinfo_t light[32];
int bUsesCubeMap;
float cubemap[24][3][4];
} sphereor_t;
typedef struct spherel_s {
vec3_t origin;
vec3_t color;
float intensity;
struct mnode_s* leaf;
int needs_trace;
int spot_light;
float spot_radiusbydistance;
vec3_t spot_dir;
int reference_count;
} spherel_t;
typedef struct cubemap_s {
char name[MAX_QPATH];
vec3_t origin;
@ -195,17 +102,6 @@ typedef struct {
vec3_t directedLight;
} trRefEntity_t;
typedef struct refSprite_s {
surfaceType_t surftype;
int hModel;
int shaderNum;
float origin[3];
float scale;
float axis[3][3];
unsigned char shaderRGBA[4];
int renderfx;
float shaderTime;
} refSprite_t;
typedef struct {
vec3_t origin; // in world coordinates
@ -870,18 +766,7 @@ typedef struct {
float sunAmbCol[4];
float autoExposureMinMax[2];
float toneMinAvgMaxLinear[3];
int numSpriteSurfs;
struct drawSurf_s* spriteSurfs;
int numStaticModels;
struct cStaticModelUnpacked_s* staticModels;
int numStaticModelData;
unsigned char* staticModelData;
qboolean sky_portal;
float sky_alpha;
vec3_t sky_origin;
vec3_t sky_axis[3];
float toneMinAvgMaxLinear[3];
} trRefdef_t;
@ -964,6 +849,25 @@ SURFACES
*/
typedef byte color4ub_t[4];
// any changes in surfaceType must be mirrored in rb_surfaceTable[]
typedef enum {
SF_BAD,
SF_SKIP, // ignore
SF_FACE,
SF_GRID,
SF_TRIANGLES,
SF_POLY,
SF_MDV,
SF_MDR,
SF_IQM,
SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_VAO_MDVMESH,
SF_VAO_IQM,
SF_NUM_SURFACE_TYPES,
SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
} surfaceType_t;
typedef struct drawSurf_s {
unsigned int sort; // bit combination for fast compares
@ -986,12 +890,6 @@ typedef struct srfPoly_s {
polyVert_t *verts;
} srfPoly_t;
typedef struct srfMarkFragment_s {
surfaceType_t surfaceType;
int iIndex;
int numVerts;
polyVert_t* verts;
} srfMarkFragment_t;
typedef struct srfFlare_s {
surfaceType_t surfaceType;
@ -1146,115 +1044,6 @@ typedef struct srfVaoMdvMesh_s
vao_t *vao;
} srfVaoMdvMesh_t;
typedef union varnodeUnpacked_u {
float fVariance;
byte flags;
} varnodeUnpacked_t;
typedef unsigned short terraInt;
typedef struct terrainVert_s {
vec3_t xyz;
vec2_t texCoords[2];
float fVariance;
float fHgtAvg;
float fHgtAdd;
unsigned int uiDistRecalc;
terraInt nRef;
terraInt iVertArray;
byte* pHgt;
terraInt iNext;
terraInt iPrev;
} terrainVert_t;
typedef struct terraTri_s {
unsigned short iPt[3];
terraInt nSplit;
unsigned int uiDistRecalc;
struct cTerraPatchUnpacked_s* patch;
varnodeUnpacked_t* varnode;
terraInt index;
byte lod;
byte byConstChecks;
terraInt iLeft;
terraInt iRight;
terraInt iBase;
terraInt iLeftChild;
terraInt iRightChild;
terraInt iParent;
terraInt iPrev;
terraInt iNext;
} terraTri_t;
typedef struct srfTerrain_s {
surfaceType_t surfaceType;
terraInt iVertHead;
terraInt iTriHead;
terraInt iTriTail;
terraInt iMergeHead;
int nVerts;
int nTris;
int lmapSize;
int dlightBits[2];
float lmapStep;
int dlightMap[2];
byte* lmData;
float lmapX;
float lmapY;
} srfTerrain_t;
typedef struct cTerraPatchUnpacked_s {
srfTerrain_t drawinfo;
int viewCount;
int visCountCheck;
int visCountDraw;
int frameCount;
unsigned int uiDistRecalc;
float s;
float t;
float texCoord[2][2][2];
float x0;
float y0;
float z0;
float zmax;
shader_t* shader;
short int iNorth;
short int iEast;
short int iSouth;
short int iWest;
struct cTerraPatchUnpacked_s* pNextActive;
varnodeUnpacked_t varTree[2][63];
unsigned char heightmap[81];
byte flags;
byte byDirty;
} cTerraPatchUnpacked_t;
typedef struct srfStaticModel_s {
surfaceType_t surfaceType;
struct cStaticModelUnpacked_s* parent;
} srfStaticModel_t;
typedef struct cStaticModelUnpacked_s {
qboolean useSpecialLighting;
qboolean bLightGridCalculated;
qboolean bRendered;
char model[128];
vec3_t origin;
vec3_t angles;
vec3_t axis[3];
float scale;
int firstVertexData;
int numVertexData;
int visCount;
dtiki_t* tiki;
sphere_dlight_t dlights[32];
int numdlights;
float radius;
float cull_radius;
int iGridLighting;
float lodpercentage[2];
} cStaticModelUnpacked_t;
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);
/*
@ -1351,15 +1140,6 @@ typedef struct {
int numSurfaces;
} bmodel_t;
typedef struct {
float width;
float height;
float origin_x;
float origin_y;
float scale;
shader_t* shader;
} sprite_t;
typedef struct {
char name[MAX_QPATH]; // ie: maps/tim_dm2.bsp
char baseName[MAX_QPATH]; // ie: tim_dm2
@ -1400,21 +1180,6 @@ typedef struct {
byte *lightGridData;
uint16_t *lightGrid16;
int numTerraPatches;
cTerraPatchUnpacked_t* terraPatches;
cTerraPatchUnpacked_t* activeTerraPatches;
int numVisTerraPatches;
cTerraPatchUnpacked_t** visTerraPatches;
int numStaticModelData;
byte* staticModelData;
int numStaticModels;
cStaticModelUnpacked_t* staticModels;
int numVisStaticModels;
cStaticModelUnpacked_t** visStaticModels;
int numClusters;
int clusterBytes;
@ -1501,10 +1266,11 @@ typedef struct mdvModel_s
//======================================================================
typedef enum {
MOD_BAD,
MOD_BRUSH,
MOD_TIKI,
MOD_SPRITE
MOD_BAD,
MOD_BRUSH,
MOD_MESH,
MOD_MDR,
MOD_IQM
} modtype_t;
typedef struct model_s {
@ -1517,14 +1283,7 @@ typedef struct model_s {
mdvModel_t *mdv[MD3_MAX_LODS]; // only if type == MOD_MESH
void *modelData; // only if type == (MOD_MDR | MOD_IQM)
int numLods;
qboolean serveronly;
union {
bmodel_t* bmodel;
dtiki_t* tiki;
sprite_t* sprite;
} d;
int numLods;
} model_t;
@ -1534,6 +1293,7 @@ void R_ModelInit (void);
model_t *R_GetModelByHandle( qhandle_t hModel );
int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
float frac, const char *tagName );
void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs );
void R_Modellist_f (void);
@ -1703,14 +1463,7 @@ typedef struct {
backEndCounters_t pc;
qboolean isHyperspace;
trRefEntity_t *currentEntity;
qboolean skyRenderedThisView; // flag for drawing sun
sphereor_t spheres[128];
unsigned char numSpheresUsed;
sphereor_t* currentSphere;
sphereor_t spareSphere;
sphereor_t hudSphere;
cStaticModelUnpacked_t* currentStaticModel;
int dsStreamVert;
qboolean skyRenderedThisView; // flag for drawing sun
qboolean projection2D; // if qtrue, drawstretchpic doesn't need to change modes
byte color2D[4];
@ -1820,8 +1573,7 @@ typedef struct {
trRefEntity_t *currentEntity;
trRefEntity_t worldEntity; // point currentEntity at this when rendering world
int currentEntityNum;
int shiftedEntityNum; // currentEntityNum << QSORT_REFENTITYNUM_SHIFT
int shiftedIsStatic;
int shiftedEntityNum; // currentEntityNum << QSORT_REFENTITYNUM_SHIFT
model_t *currentModel;
//
@ -1850,10 +1602,7 @@ typedef struct {
float identityLight; // 1.0 / ( 1 << overbrightBits )
int identityLightByte; // identityLight * 255
int overbrightBits; // r_overbrightBits->integer, but set to 0 if no hw gamma
int overbrightShift;
float overbrightMult;
int needsLightScale;
int overbrightBits; // r_overbrightBits->integer, but set to 0 if no hw gamma
orientationr_t or; // for current entity
@ -1907,22 +1656,9 @@ typedef struct {
float triangleTable[FUNCTABLE_SIZE];
float sawToothTable[FUNCTABLE_SIZE];
float inverseSawToothTable[FUNCTABLE_SIZE];
float fogTable[FOG_TABLE_SIZE];
spherel_t sSunLight;
spherel_t sLights[1532];
int numSLights;
int rendererhandle;
qboolean shadersParsed;
int frame_skel_index;
int skel_index[1024];
fontheader_t* pFontDebugStrings;
float fogTable[FOG_TABLE_SIZE];
} trGlobals_t;
#ifdef __cplusplus
extern "C" {
#endif
extern backEndState_t backEnd;
extern trGlobals_t tr;
extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init
@ -2088,46 +1824,7 @@ extern cvar_t *r_simpleMipMaps;
extern cvar_t *r_showImages;
extern cvar_t *r_debugSort;
extern cvar_t* r_printShaders;
extern cvar_t* r_staticlod;
extern cvar_t* r_lodscale;
extern cvar_t* r_lodcap;
extern cvar_t* r_lodviewmodelcap;
extern cvar_t* r_uselod;
extern cvar_t* lod_LOD;
extern cvar_t* lod_minLOD;
extern cvar_t* lod_maxLOD;
extern cvar_t* lod_LOD_slider;
extern cvar_t* lod_curve_0_val;
extern cvar_t* lod_curve_1_val;
extern cvar_t* lod_curve_2_val;
extern cvar_t* lod_curve_3_val;
extern cvar_t* lod_curve_4_val;
extern cvar_t* lod_edit_0;
extern cvar_t* lod_edit_1;
extern cvar_t* lod_edit_2;
extern cvar_t* lod_edit_3;
extern cvar_t* lod_edit_4;
extern cvar_t* lod_curve_0_slider;
extern cvar_t* lod_curve_1_slider;
extern cvar_t* lod_curve_2_slider;
extern cvar_t* lod_curve_3_slider;
extern cvar_t* lod_curve_4_slider;
extern cvar_t* lod_pitch_val;
extern cvar_t* lod_zee_val;
extern cvar_t* lod_mesh;
extern cvar_t* lod_meshname;
extern cvar_t* lod_tikiname;
extern cvar_t* lod_metric;
extern cvar_t* lod_tris;
extern cvar_t* lod_position;
extern cvar_t* lod_save;
extern cvar_t* lod_tool;
extern cvar_t* r_numdebuglines;
extern cvar_t* r_showSkeleton;
extern cvar_t *r_printShaders;
extern cvar_t *r_marksOnTriangleMeshes;
@ -2161,8 +1858,6 @@ static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader)
void R_SwapBuffers( int );
void R_DebugCircle(const vec3_t org, float radius, float r, float g, float b, float alpha, qboolean horizontal);
void R_DebugLine(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha);
void R_RenderView( viewParms_t *parms );
void R_RenderDlightCubemaps(const refdef_t *fd);
void R_RenderPshadowMaps(const refdef_t *fd);
@ -2201,7 +1896,6 @@ int R_CullLocalPointAndRadius( const vec3_t origin, float radius );
void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum);
void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or );
void R_RotateForStaticModel(cStaticModelUnpacked_t* SM, const viewParms_t* viewParms, orientationr_t* or );
/*
** GL wrapper/helper functions
@ -2253,24 +1947,12 @@ void GL_Cull( int cullType );
#define GLS_DEFAULT GLS_DEPTHMASK_TRUE
void Draw_SetColor(const vec4_t rgba);
void Draw_StretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader);
void Draw_TilePic(float x, float y, float w, float h, qhandle_t hShader);
void Draw_TilePicOffset(float x, float y, float w, float h, qhandle_t hShader, int offsetX, int offsetY);
void Draw_TrianglePic(const vec2_t vPoints[3], const vec2_t vTexCoords[3], qhandle_t hShader);
void DrawBox(float x, float y, float w, float h);
void AddBox(float x, float y, float w, float h);
void Set2DWindow(int x, int y, int w, int h, float left, float right, float bottom, float top, float n, float f);
void RE_Scissor(int x, int y, int width, int height);
void DrawLineLoop(const vec2_t* points, int count, int stipple_factor, int stipple_mask);
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);
void RE_BeginFrame( stereoFrame_t stereoFrame );
void RE_BeginRegistration( glconfig_t *glconfig );
void RE_LoadWorldMap(const char* mapname);
void RE_PrintBSPFileSizes(void);
int RE_MapVersion(void);
void RE_LoadWorldMap( const char *mapname );
void RE_SetWorldVisData( const byte *vis );
qhandle_t RE_RegisterModel( const char *name );
qhandle_t RE_RegisterSkin( const char *name );
@ -2408,8 +2090,7 @@ WORLD MAP
============================================================
*/
void R_AddBrushModelSurfaces(trRefEntity_t* e);
void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs);
void R_AddBrushModelSurfaces( trRefEntity_t *e );
void R_AddWorldSurfaces( void );
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 );
@ -2437,13 +2118,10 @@ LIGHTS
*/
void R_DlightBmodel( bmodel_t *bmodel );
void R_GetLightingForDecal(vec3_t vLight, vec3_t vFacing, vec3_t vOrigin);
void R_GetLightingForSmoke(vec3_t vLight, vec3_t vOrigin);
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent );
void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or );
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );
int R_LightDirForPoint(vec3_t point, vec3_t lightDir, vec3_t normal, world_t* world);
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights);
int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world );
int R_CubemapForPoint( vec3_t point );
@ -2499,9 +2177,6 @@ MARKERS, POLYGON PROJECTION ON WORLD POLYGONS
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );
void R_MarkFragmentsForInlineModel(clipHandle_t bmodel, const vec3_t angles, const vec3_t origin, int numPoints,
const vec3_t* points, const vec3_t projection, int maxPoints, vec3_t pointBuffer,
int maxFragments, markFragment_t* fragmentBuffer, float radiusSquared);
/*
============================================================
@ -2575,10 +2250,7 @@ SCENE GENERATION
void R_InitNextFrame( void );
void RE_ClearScene( void );
void RE_AddRefEntityToScene(const refEntity_t* ent);
void RE_AddRefSpriteToScene(const refEntity_t* ent);
void RE_AddTerrainMarkToScene(int iTerrainIndex, qhandle_t hShader, int numVerts, const polyVert_t* verts, int renderfx);
refEntity_t* RE_GetRenderEntity(int entityNumber);
void RE_AddRefEntityToScene( const refEntity_t *ent );
void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num );
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b );
void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b );
@ -2613,76 +2285,15 @@ ANIMATED MODELS
=============================================================
*/
void R_MakeAnimModel(model_t* model);
void R_AddAnimSurfaces(trRefEntity_t* ent);
/*
=============================================================
SPRITE
=============================================================
*/
sprite_t* SPR_RegisterSprite(const char* name);
void RB_DrawSprite(const refSprite_t* spr);
/*
=============================================================
TIKI
=============================================================
*/
void RE_FreeModels(void);
qhandle_t RE_SpawnEffectModel(const char* szModel, vec3_t vPos, vec3_t* axis);
qhandle_t RE_RegisterServerModel(const char* name);
void RE_UnregisterServerModel(qhandle_t hModel);
orientation_t RE_TIKI_Orientation(refEntity_t* model, int tagnum);
qboolean RE_TIKI_IsOnGround(refEntity_t* model, int tagnum, float threshold);
float R_ModelRadius(qhandle_t handle);
void R_ModelBounds(qhandle_t handle, vec3_t mins, vec3_t maxs);
dtiki_t* R_Model_GetHandle(qhandle_t handle);
float R_GetRadius(refEntity_t* model);
void R_GetFrame(refEntity_t* model, struct skelAnimFrame_s* newFrame);
void RE_ForceUpdatePose(refEntity_t* model);
void RE_SetFrameNumber(int frameNumber);
void R_UpdatePoseInternal(refEntity_t* model);
void RB_SkelMesh(skelSurfaceGame_t* sf);
void RB_StaticMesh(staticSurface_t* staticSurf);
/*
=============================================================
FONT
=============================================================
*/
fontheader_t* R_LoadFont(const char* name);
void R_DrawString(const fontheader_t* font, const char* text, float x, float y, int maxlen, qboolean bVirtualScreen);
float R_GetFontHeight(const fontheader_t* font);
float R_GetFontStringWidth(const fontheader_t* font, const char* s);
/*
=============================================================
SWIPE
=============================================================
*/
void RB_DrawSwipeSurface(surfaceType_t* pswipe);
void RE_SwipeBegin(float thistime, float life, qhandle_t shader);
void RE_SwipeEnd();
/*
=============================================================
UTIL
=============================================================
*/
int RE_GetShaderHeight(qhandle_t hShader);
int RE_GetShaderWidth(qhandle_t hShader);
void R_MDRAddAnimSurfaces( trRefEntity_t *ent );
void RB_MDRSurfaceAnim( mdrSurface_t *surface );
qboolean R_LoadIQM (model_t *mod, void *buffer, int filesize, const char *name );
void R_AddIQMSurfaces( trRefEntity_t *ent );
void RB_IQMSurfaceAnim( surfaceType_t *surface );
void RB_IQMSurfaceAnimVao( srfVaoIQModel_t *surface );
int R_IQMLerpTag( orientation_t *tag, iqmData_t *data,
int startFrame, int endFrame,
float frac, const char *tagName );
/*
=============================================================
@ -2717,10 +2328,6 @@ RENDERER BACK END FUNCTIONS
void RB_ExecuteRenderCommands( const void *data );
#ifdef __cplusplus
}
#endif
/*
=============================================================
@ -2857,10 +2464,7 @@ typedef struct {
dlight_t dlights[MAX_DLIGHTS];
trRefEntity_t entities[MAX_REFENTITIES];
srfPoly_t *polys;//[MAX_POLYS];
polyVert_t* polyVerts;//[MAX_POLYVERTS];
refSprite_t sprites[2048];
cStaticModelUnpacked_t* staticModels;
byte* staticModelData;
polyVert_t *polyVerts;//[MAX_POLYVERTS];
pshadow_t pshadows[MAX_CALC_PSHADOWS];
renderCommandList_t commands;
} backEndData_t;
@ -2872,8 +2476,7 @@ extern backEndData_t *backEndData; // the second one may not be allocated
void *R_GetCommandBuffer( int bytes );
void RB_ExecuteRenderCommands(const void* data);
void R_SavePerformanceCounters(void);
void RB_ExecuteRenderCommands( const void *data );
void R_IssuePendingRenderCommands( void );
@ -2884,6 +2487,7 @@ void R_AddPostProcessCmd (void);
void RE_SetColor( const float *rgba );
void RE_StretchPic ( float x, float y, float w, float h,
float s1, float t1, float s2, float t2, qhandle_t hShader );
void RE_BeginFrame( stereoFrame_t stereoFrame );
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
void RE_SaveJPG(char * filename, int quality, int image_width, int image_height,
unsigned char *image_buffer, int padding);
@ -2892,3 +2496,5 @@ size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
void RE_TakeVideoFrame( int width, int height,
byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
#endif //TR_LOCAL_H

View file

@ -1094,7 +1094,24 @@ qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum,
VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] );
// optionally rotate
if ( e->e.skinNum ) {
if ( e->e.oldframe ) {
// if a speed is specified
if ( e->e.frame ) {
// continuous rotate
d = (tr.refdef.time/1000.0f) * e->e.frame;
VectorCopy( camera->axis[1], transformed );
RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
} else {
// bobbing rotate, with skinNum being the rotation offset
d = sin( tr.refdef.time * 0.003f );
d = e->e.skinNum + d * 4;
VectorCopy( camera->axis[1], transformed );
RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
}
}
else if ( e->e.skinNum ) {
d = e->e.skinNum;
VectorCopy( camera->axis[1], transformed );
RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
@ -1353,6 +1370,10 @@ int R_SpriteFogNum( trRefEntity_t *ent ) {
return 0;
}
if ( ent->e.renderfx & RF_CROSSHAIR ) {
return 0;
}
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) {
@ -1556,6 +1577,9 @@ static void R_AddEntitySurface (int entityNum)
break; // don't draw anything
case RT_SPRITE:
case RT_BEAM:
case RT_LIGHTNING:
case RT_RAIL_CORE:
case RT_RAIL_RINGS:
// self blood sprites, talk balloons, etc should not be drawn in the primary
// view. We can't just do this check for all entities, because md3
// entities may still want to cast shadows from them
@ -1575,6 +1599,15 @@ static void R_AddEntitySurface (int entityNum)
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0, 0 /*cubeMap*/ );
} else {
switch ( tr.currentModel->type ) {
case MOD_MESH:
R_AddMD3Surfaces( ent );
break;
case MOD_MDR:
R_MDRAddAnimSurfaces( ent );
break;
case MOD_IQM:
R_AddIQMSurfaces( ent );
break;
case MOD_BRUSH:
R_AddBrushModelSurfaces( ent );
break;
@ -1834,7 +1867,7 @@ void R_RenderPshadowMaps(const refdef_t *fd)
{
trRefEntity_t *ent = &tr.refdef.entities[i];
if((ent->e.renderfx & (RF_FIRST_PERSON)))
if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW)))
continue;
//if((ent->e.renderfx & RF_THIRD_PERSON))
@ -1859,6 +1892,37 @@ void R_RenderPshadowMaps(const refdef_t *fd)
switch (model->type)
{
case MOD_MESH:
{
mdvFrame_t *frame = &model->mdv[0]->frames[ent->e.frame];
radius = frame->radius * scale;
}
break;
case MOD_MDR:
{
// FIXME: never actually tested this
mdrHeader_t *header = model->modelData;
int frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
mdrFrame_t *frame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
radius = frame->radius;
}
break;
case MOD_IQM:
{
// FIXME: never actually tested this
iqmData_t *data = model->modelData;
vec3_t diag;
float *framebounds;
framebounds = data->bounds + 6*ent->e.frame;
VectorSubtract( framebounds+3, framebounds, diag );
radius = 0.5f * VectorLength( diag );
}
break;
default:
break;
}

417
code/renderergl2/tr_mesh.c Normal file
View file

@ -0,0 +1,417 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_mesh.c: triangle model functions
#include "tr_local.h"
static float ProjectRadius( float r, vec3_t location )
{
float pr;
float dist;
float c;
vec3_t p;
float projected[4];
c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin );
dist = DotProduct( tr.viewParms.or.axis[0], location ) - c;
if ( dist <= 0 )
return 0;
p[0] = 0;
p[1] = fabs( r );
p[2] = -dist;
projected[0] = p[0] * tr.viewParms.projectionMatrix[0] +
p[1] * tr.viewParms.projectionMatrix[4] +
p[2] * tr.viewParms.projectionMatrix[8] +
tr.viewParms.projectionMatrix[12];
projected[1] = p[0] * tr.viewParms.projectionMatrix[1] +
p[1] * tr.viewParms.projectionMatrix[5] +
p[2] * tr.viewParms.projectionMatrix[9] +
tr.viewParms.projectionMatrix[13];
projected[2] = p[0] * tr.viewParms.projectionMatrix[2] +
p[1] * tr.viewParms.projectionMatrix[6] +
p[2] * tr.viewParms.projectionMatrix[10] +
tr.viewParms.projectionMatrix[14];
projected[3] = p[0] * tr.viewParms.projectionMatrix[3] +
p[1] * tr.viewParms.projectionMatrix[7] +
p[2] * tr.viewParms.projectionMatrix[11] +
tr.viewParms.projectionMatrix[15];
pr = projected[1] / projected[3];
if ( pr > 1.0f )
pr = 1.0f;
return pr;
}
/*
=============
R_CullModel
=============
*/
static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
vec3_t bounds[2];
mdvFrame_t *oldFrame, *newFrame;
int i;
// compute frame pointers
newFrame = model->frames + ent->e.frame;
oldFrame = model->frames + ent->e.oldframe;
// cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes )
{
if ( ent->e.frame == ent->e.oldframe )
{
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
case CULL_IN:
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_sphere_cull_md3_clip++;
break;
}
}
else
{
int sphereCull, sphereCullB;
sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
if ( newFrame == oldFrame ) {
sphereCullB = sphereCull;
} else {
sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
}
if ( sphereCull == sphereCullB )
{
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
}
else if ( sphereCull == CULL_IN )
{
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
}
else
{
tr.pc.c_sphere_cull_md3_clip++;
}
}
}
}
// calculate a bounding box in the current coordinate system
for (i = 0 ; i < 3 ; i++) {
bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
}
switch ( R_CullLocalBox( bounds ) )
{
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
return CULL_CLIP;
case CULL_OUT:
default:
tr.pc.c_box_cull_md3_out++;
return CULL_OUT;
}
}
/*
=================
R_ComputeLOD
=================
*/
int R_ComputeLOD( trRefEntity_t *ent ) {
float radius;
float flod, lodscale;
float projectedRadius;
mdvFrame_t *frame;
mdrHeader_t *mdr;
mdrFrame_t *mdrframe;
int lod;
if ( tr.currentModel->numLods < 2 )
{
// model has only 1 LOD level, skip computations and bias
lod = 0;
}
else
{
// multiple LODs exist, so compute projected bounding sphere
// and use that as a criteria for selecting LOD
if(tr.currentModel->type == MOD_MDR)
{
int frameSize;
mdr = (mdrHeader_t *) tr.currentModel->modelData;
frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]);
}
else
{
//frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
frame = tr.currentModel->mdv[0]->frames;
frame += ent->e.frame;
radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
}
if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
{
lodscale = r_lodscale->value;
if (lodscale > 20) lodscale = 20;
flod = 1.0f - projectedRadius * lodscale;
}
else
{
// object intersects near view plane, e.g. view weapon
flod = 0;
}
flod *= tr.currentModel->numLods;
lod = ri.ftol(flod);
if ( lod < 0 )
{
lod = 0;
}
else if ( lod >= tr.currentModel->numLods )
{
lod = tr.currentModel->numLods - 1;
}
}
lod += r_lodbias->integer;
if ( lod >= tr.currentModel->numLods )
lod = tr.currentModel->numLods - 1;
if ( lod < 0 )
lod = 0;
return lod;
}
/*
=================
R_ComputeFogNum
=================
*/
int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
int i, j;
fog_t *fog;
mdvFrame_t *mdvFrame;
vec3_t localOrigin;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
}
// FIXME: non-normalized axis issues
mdvFrame = model->frames + ent->e.frame;
VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) {
if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
break;
}
if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
break;
}
}
if ( j == 3 ) {
return i;
}
}
return 0;
}
/*
=================
R_AddMD3Surfaces
=================
*/
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
int i;
mdvModel_t *model = NULL;
mdvSurface_t *surface = NULL;
shader_t *shader = NULL;
int cull;
int lod;
int fogNum;
int cubemapIndex;
qboolean personalModel;
// don't add third_person objects if not in a portal
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal
|| (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)));
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
}
//
// Validate the frames so there is no chance of a crash.
// This will write directly into the entity structure, so
// when the surfaces are rendered, they don't need to be
// range checked again.
//
if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.frame < 0)
|| (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.oldframe < 0) ) {
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame,
tr.currentModel->name );
ent->e.frame = 0;
ent->e.oldframe = 0;
}
//
// compute LOD
//
lod = R_ComputeLOD( ent );
model = tr.currentModel->mdv[lod];
//
// cull the entire model if merged bounding box of both frames
// is outside the view frustum.
//
cull = R_CullModel ( model, ent );
if ( cull == CULL_OUT ) {
return;
}
//
// set up lighting now that we know we aren't culled
//
if ( !personalModel || r_shadows->integer > 1 ) {
R_SetupEntityLighting( &tr.refdef, ent );
}
//
// see if we are in a fog volume
//
fogNum = R_ComputeFogNum( model, ent );
cubemapIndex = R_CubemapForPoint(ent->e.origin);
//
// draw all surfaces
//
surface = model->surfaces;
for ( i = 0 ; i < model->numSurfaces ; i++ ) {
if ( ent->e.customShader ) {
shader = R_GetShaderByHandle( ent->e.customShader );
} else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
skin_t *skin;
int j;
skin = R_GetSkinByHandle( ent->e.customSkin );
// match the surface name to something in the skin file
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
shader = skin->surfaces[j].shader;
break;
}
}
if (shader == tr.defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name);
}
else if (shader->defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
}
} else if ( surface->numShaderIndexes <= 0 ) {
shader = tr.defaultShader;
} else {
shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
}
// we will add shadows even if the main object isn't visible in the view
// stencil shadows can't do personal models unless I polyhedron clip
if ( !personalModel
&& r_shadows->integer == 2
&& fogNum == 0
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
&& shader->sort == SS_OPAQUE ) {
R_AddDrawSurf( (void *)&model->vaoSurfaces[i], tr.shadowShader, 0, qfalse, qfalse, 0 );
}
// projection shadows work fine with personal models
if ( r_shadows->integer == 3
&& fogNum == 0
&& (ent->e.renderfx & RF_SHADOW_PLANE )
&& shader->sort == SS_OPAQUE ) {
R_AddDrawSurf( (void *)&model->vaoSurfaces[i], tr.projectionShadowShader, 0, qfalse, qfalse, 0 );
}
// don't add third_person objects if not viewing through a portal
if ( !personalModel ) {
R_AddDrawSurf((void *)&model->vaoSurfaces[i], shader, fogNum, qfalse, qfalse, cubemapIndex );
}
surface++;
}
}

1418
code/renderergl2/tr_model.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -286,6 +286,8 @@ void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, flo
void RE_BeginScene(const refdef_t *fd)
{
Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
tr.refdef.x = fd->x;
tr.refdef.y = fd->y;
tr.refdef.width = fd->width;

View file

@ -64,6 +64,13 @@ R_BindAnimatedImageToTMU
static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
int64_t index;
if ( bundle->isVideoMap ) {
ri.CIN_RunCinematic(bundle->videoMapHandle);
ri.CIN_UploadCinematic(bundle->videoMapHandle);
GL_BindToTMU(tr.scratchImage[bundle->videoMapHandle], tmu);
return;
}
if ( bundle->numImageAnimations <= 1 ) {
GL_BindToTMU( bundle->image[0], tmu);
return;

View file

@ -788,6 +788,22 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
totalImages, MAX_IMAGE_ANIMATIONS, shader.name );
}
}
else if ( !Q_stricmp( token, "videoMap" ) )
{
token = COM_ParseExt( text, qfalse );
if ( !token[0] )
{
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMap' keyword in shader '%s'\n", shader.name );
return qfalse;
}
stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader));
if (stage->bundle[0].videoMapHandle != -1) {
stage->bundle[0].isVideoMap = qtrue;
stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle];
} else {
ri.Printf( PRINT_WARNING, "WARNING: could not load '%s' for 'videoMap' keyword in shader '%s'\n", token, shader.name );
}
}
//
// alphafunc <func>
//
@ -2744,7 +2760,7 @@ static shader_t *GeneratePermanentShader( void ) {
return tr.defaultShader;
}
newShader = ri.Hunk_Alloc( sizeof( shader_t ) );
newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low );
*newShader = shader;
@ -2766,12 +2782,12 @@ static shader_t *GeneratePermanentShader( void ) {
if ( !stages[i].active ) {
break;
}
newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ) );
newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low );
*newShader->stages[i] = stages[i];
for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size );
newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low );
Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size );
}
}
@ -3654,7 +3670,7 @@ static void ScanAndLoadShaderFiles( void )
long sum = 0, summand;
// scan for shader files
shaderFiles = ri.FS_ListFiles( "scripts", ".shader", qfalse, &numShaderFiles );
shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles );
if ( !shaderFiles || !numShaderFiles )
{
@ -3736,7 +3752,7 @@ static void ScanAndLoadShaderFiles( void )
}
// build single large buffer
s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2 );
s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2, h_low );
s_shaderText[ 0 ] = '\0';
textEnd = s_shaderText;
@ -3776,7 +3792,7 @@ static void ScanAndLoadShaderFiles( void )
size += MAX_SHADERTEXT_HASH;
hashMem = ri.Hunk_Alloc( size * sizeof(char *) );
hashMem = ri.Hunk_Alloc( size * sizeof(char *), h_low );
for (i = 0; i < MAX_SHADERTEXT_HASH; i++) {
shaderTextHashTable[i] = (char **) hashMem;

View file

@ -284,3 +284,50 @@ void RB_ShadowFinish( void ) {
qglDisable( GL_STENCIL_TEST );
#endif
}
/*
=================
RB_ProjectionShadowDeform
=================
*/
void RB_ProjectionShadowDeform( void ) {
float *xyz;
int i;
float h;
vec3_t ground;
vec3_t light;
float groundDist;
float d;
vec3_t lightDir;
xyz = ( float * ) tess.xyz;
ground[0] = backEnd.or.axis[0][2];
ground[1] = backEnd.or.axis[1][2];
ground[2] = backEnd.or.axis[2][2];
groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
VectorCopy( backEnd.currentEntity->modelLightDir, lightDir );
d = DotProduct( lightDir, ground );
// don't let the shadows get too long or go negative
if ( d < 0.5 ) {
VectorMA( lightDir, (0.5 - d), ground, lightDir );
d = DotProduct( lightDir, ground );
}
d = 1.0 / d;
light[0] = lightDir[0] * d;
light[1] = lightDir[1] * d;
light[2] = lightDir[2] * d;
for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
h = DotProduct( xyz, ground ) + groundDist;
xyz[0] -= light[0] * h;
xyz[1] -= light[1] * h;
xyz[2] -= light[2] * h;
}
}

View file

@ -643,10 +643,10 @@ static void FillCloudBox( const shader_t *shader, int stage )
continue;
}
sky_mins_subd[0] = ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS);
sky_mins_subd[1] = ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS);
sky_maxs_subd[0] = ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS);
sky_maxs_subd[1] = ftol(sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS);
sky_mins_subd[0] = ri.ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS);
sky_mins_subd[1] = ri.ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS);
sky_maxs_subd[0] = ri.ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS);
sky_maxs_subd[1] = ri.ftol(sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS);
if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;

View file

@ -1,31 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_sphere_shade.cpp -- sphere shade
#include "tr_local.h"
int R_GatherLightSources(const vec3_t vPos, vec3_t* pvLightPos, vec3_t* pvLightIntensity, int iMaxLights)
{
// FIXME: unimplemented
return 0;
}

View file

@ -1,468 +0,0 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_staticmodels.cpp -- static model rendering
#include "tr_local.h"
#include "tiki.h"
#define MAX_STATIC_MODELS_SURFS 8192
int g_nStaticSurfaces;
staticSurface_t g_staticSurfaces[ MAX_STATIC_MODELS_SURFS ];
qboolean g_bInfostaticmodels;
/*
==============
R_InitStaticModels
==============
*/
void R_InitStaticModels( void ) {
cStaticModelUnpacked_t *pSM;
char szTemp[ 1024 ];
bool exists;
skelBoneCache_t bones[ 128 ];
float radius;
int i, j, k, l;
g_bInfostaticmodels = qfalse;
if( tr.overbrightShift )
{
for( i = 0; i < tr.world->numStaticModelData; i++ )
{
int r, g, b;
r = ( int )( ( float )tr.world->staticModelData[ i * 4 ] * tr.overbrightMult );
g = ( int )( ( float )tr.world->staticModelData[ i * 4 + 1 ] * tr.overbrightMult );
b = ( int )( ( float )tr.world->staticModelData[ i * 4 + 2 ] * tr.overbrightMult );
if( ( r | g | b ) & 0xFFFFFF00 )
{
float t;
unsigned long long rgb;
rgb = ( g + ( ~( ( unsigned long long )( r - g ) >> 32 ) & ( r - g ) ) - b );
t = 255.0 / ( float )( b + ( ~( rgb & 0x00000000FFFFFFFF ) & rgb ) );
r = ( int )( ( float )r * t );
g = ( int )( ( float )g * t );
b = ( int )( ( float )b * t );
}
tr.world->staticModelData[ i * 4 ] = r;
tr.world->staticModelData[ i * 4 + 1 ] = g;
tr.world->staticModelData[ i * 4 + 2 ] = b;
}
}
for( i = 0; i < tr.world->numStaticModels; i++ )
{
vec3_t mins, maxs;
pSM = &tr.world->staticModels[ i ];
pSM->bRendered = qfalse;
AngleVectorsLeft( pSM->angles, pSM->axis[ 0 ], pSM->axis[ 1 ], pSM->axis[ 2 ] );
if( !strnicmp( pSM->model, "models", 6 ) ) {
strcpy( szTemp, pSM->model );
} else {
sprintf( szTemp, "models/%s", pSM->model );
}
FS_CanonicalFilename( szTemp );
exists = TIKI_FindTiki( szTemp ) != NULL;
pSM->tiki = TIKI_RegisterTiki( szTemp );
if( !pSM->tiki ) {
ri.Printf( PRINT_WARNING, "^~^~^: Warning: Cannot Load Static Model %s\n", szTemp );
continue;
}
pSM->radius = TIKI_GlobalRadius( pSM->tiki );
//
// register shaders
//
for( j = 0; j < pSM->tiki->num_surfaces; j++ )
{
dtikisurface_t *surf = &pSM->tiki->surfaces[ j ];
for( k = 0; k < surf->numskins; k++ )
{
if( surf->shader[ k ][ 0 ] ) {
shader_t *sh = R_FindShader( surf->shader[ k ], -1, ( surf->flags & TIKI_SURF_SKIN1 ) );
surf->hShader[ k ] = sh->index;
} else {
surf->hShader[ k ] = NULL;
}
}
}
// prepare the skeleton frame for the static model
TIKI_GetSkelAnimFrame( pSM->tiki, bones, &radius, &mins, &maxs );
pSM->cull_radius = radius * pSM->tiki->load_scale * pSM->scale;
// Suggestion:
// It would be cool to have animated static model in the future
if( !exists )
{
for( j = 0; j < pSM->tiki->numMeshes; j++ )
{
skelHeaderGame_t *skelmodel = TIKI_GetSkel( pSM->tiki->mesh[ j ] );
skelSurfaceGame_t *surf;
if( !skelmodel ) {
ri.Printf( PRINT_WARNING, "^~^~^: Warning: Missing mesh in Static Model %s\n", skelmodel->name );
continue;
}
surf = skelmodel->pSurfaces;
for( k = 0; k < skelmodel->numSurfaces; k++, surf = surf->pNext )
{
byte *buf;
byte *p;
skelWeight_t *weight;
skeletorVertex_t *vert;
if( surf->pStaticXyz ) {
continue;
}
// allocate static vectors
p = buf = ( byte * )ri.TIKI_Alloc( ( sizeof( vec4_t ) + sizeof( vec4_t ) + sizeof( vec2_t ) * 2 ) * surf->numVerts );
surf->pStaticXyz = ( vec4_t * )p;
p += sizeof( vec4_t ) * surf->numVerts;
surf->pStaticNormal = ( vec4_t * )p;
p += sizeof( vec4_t ) * surf->numVerts;
surf->pStaticTexCoords = ( vec2_t ( * )[ 2 ] )p;
vert = surf->pVerts;
for( l = 0; l < surf->numVerts; l++ )
{
int channel;
skelBoneCache_t *bone;
weight = ( skelWeight_t * )( ( byte * )vert + sizeof( skeletorVertex_t ) );
if( j > 0 ) {
channel = pSM->tiki->m_boneList.GetLocalFromGlobal( skelmodel->pBones[ weight->boneIndex ].channel );
} else {
channel = weight->boneIndex;
}
bone = &bones[ channel ];
surf->pStaticXyz[ l ][ 0 ] = ( ( weight->offset[ 0 ] * bone->matrix[ 0 ][ 0 ]
+ weight->offset[ 1 ] * bone->matrix[ 1 ][ 0 ]
+ weight->offset[ 2 ] * bone->matrix[ 2 ][ 0 ] )
+ bone->offset[ 0 ] ) * weight->boneWeight;
surf->pStaticXyz[ l ][ 1 ] = ( ( weight->offset[ 0 ] * bone->matrix[ 0 ][ 1 ]
+ weight->offset[ 1 ] * bone->matrix[ 1 ][ 1 ]
+ weight->offset[ 2 ] * bone->matrix[ 2 ][ 1 ] )
+ bone->offset[ 1 ] ) * weight->boneWeight;
surf->pStaticXyz[ l ][ 2 ] = ( ( weight->offset[ 0 ] * bone->matrix[ 0 ][ 2 ]
+ weight->offset[ 1 ] * bone->matrix[ 1 ][ 2 ]
+ weight->offset[ 2 ] * bone->matrix[ 2 ][ 2 ] )
+ bone->offset[ 2 ] ) * weight->boneWeight;
surf->pStaticNormal[ l ][ 0 ] = vert->normal[ 0 ] * bone->matrix[ 0 ][ 0 ]
+ vert->normal[ 1 ] * bone->matrix[ 1 ][ 0 ]
+ vert->normal[ 2 ] * bone->matrix[ 2 ][ 0 ];
surf->pStaticNormal[ l ][ 1 ] = vert->normal[ 0 ] * bone->matrix[ 0 ][ 1 ]
+ vert->normal[ 1 ] * bone->matrix[ 1 ][ 1 ]
+ vert->normal[ 2 ] * bone->matrix[ 2 ][ 1 ];
surf->pStaticNormal[ l ][ 2 ] = vert->normal[ 0 ] * bone->matrix[ 0 ][ 2 ]
+ vert->normal[ 1 ] * bone->matrix[ 1 ][ 2 ]
+ vert->normal[ 2 ] * bone->matrix[ 2 ][ 2 ];
surf->pStaticTexCoords[ l ][ 0 ][ 0 ] = vert->texCoords[ 0 ];
surf->pStaticTexCoords[ l ][ 0 ][ 1 ] = vert->texCoords[ 1 ];
surf->pStaticTexCoords[ l ][ 1 ][ 0 ] = vert->texCoords[ 0 ];
surf->pStaticTexCoords[ l ][ 1 ][ 1 ] = vert->texCoords[ 1 ];
vert = ( skeletorVertex_t * )( ( byte * )vert + sizeof( skeletorVertex_t ) + sizeof( skeletorMorph_t ) * vert->numMorphs + sizeof( skelWeight_t ) * vert->numWeights );
}
}
}
}
}
tr.refdef.numStaticModels = tr.world->numStaticModels;
tr.refdef.staticModels = tr.world->staticModels;
tr.refdef.numStaticModelData = tr.world->numStaticModelData;
tr.refdef.staticModelData = tr.world->staticModelData;
}
/*
==============
R_CullStaticModel
==============
*/
static int R_CullStaticModel( dtiki_t *tiki, float fScale, const vec3_t vLocalOrg ) {
vec3_t bounds[ 2 ];
int i;
int cull;
for( i = 0; i < 3; i++ )
{
bounds[ 0 ][ i ] = vLocalOrg[ i ] + tiki->a->mins[ i ] * fScale;
bounds[ 1 ][ i ] = vLocalOrg[ i ] + tiki->a->maxs[ i ] * fScale;
}
cull = R_CullLocalBox( bounds );
// FIXME: r_showcull
switch( cull )
{
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
break;
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
break;
case CULL_OUT:
tr.pc.c_box_cull_md3_out++;
break;
}
return cull;
}
/*
==============
R_AddStaticModelSurfaces
==============
*/
void R_AddStaticModelSurfaces( void ) {
cStaticModelUnpacked_t *SM;
int i, j;
int ofsStaticData;
int iRadiusCull;
dtiki_t *tiki;
float tiki_scale;
vec3_t tiki_localorigin;
vec3_t tiki_worldorigin;
if( !tr.world->numStaticModels ) {
return;
}
tr.shiftedIsStatic = 1;
for( i = 0; i < tr.world->numStaticModels; i++ )
{
SM = &tr.world->staticModels[ i ];
//if( SM->visCount != tr.visCounts[ tr.visIndex ] ) {
// continue;
//}
tiki = SM->tiki;
if( !tiki ) {
continue;
}
tr.currentEntityNum = i;
tr.shiftedEntityNum = i << QSORT_REFENTITYNUM_SHIFT;
R_RotateForStaticModel( SM, &tr.viewParms, &tr.or );
ofsStaticData = 0;
// get the world position
tiki_scale = tiki->load_scale * SM->scale;
VectorScale( tiki->load_origin, tiki_scale, tiki_localorigin );
R_LocalPointToWorld( tiki_localorigin, tiki_worldorigin );
iRadiusCull = R_CullPointAndRadius( tiki_worldorigin, SM->cull_radius );
// FIXME: r_showcull
if( iRadiusCull != 2 && ( iRadiusCull != 1 || R_CullStaticModel( SM->tiki, tiki_scale, tiki_localorigin ) ) )
{
dtikisurface_t *dsurf;
// FIXME: Calc LOD
if( tr.viewParms.isPortal )
{
//R_CalcLod( tiki_worldorigin, SM->cull_radius / SM->scale );
SM->lodpercentage[ 1 ] = SM->cull_radius / SM->scale;
}
else
{
//R_CalcLod( tiki_worldorigin, SM->cull_radius / SM->scale );
SM->lodpercentage[ 0 ] = SM->cull_radius / SM->scale;
}
//
// draw all meshes
//
dsurf = tiki->surfaces;
for( int mesh = 0; mesh < tiki->numMeshes; mesh++ )
{
skelHeaderGame_t *skelmodel = TIKI_GetSkel( tiki->mesh[ mesh ] );
skelSurfaceGame_t *surface;
shader_t *shader;
if( !skelmodel ) {
continue;
}
//
// draw all surfaces
//
surface = skelmodel->pSurfaces;
for( j = 0; j < skelmodel->numSurfaces; j++, surface = surface->pNext, dsurf++ )
{
if( g_nStaticSurfaces >= MAX_STATIC_MODELS_SURFS )
{
ri.Printf( PRINT_DEVELOPER, "^~^~^ ERROR: MAX_STATIC_MODELS_SURFS exceeded - surface of '%s' skipped\n", tiki->a->name );
continue;
}
g_staticSurfaces[ g_nStaticSurfaces ].ident = SF_TIKI_STATIC;
g_staticSurfaces[ g_nStaticSurfaces ].ofsStaticData = ofsStaticData;
g_staticSurfaces[ g_nStaticSurfaces ].surface = surface;
g_staticSurfaces[ g_nStaticSurfaces ].meshNum = mesh;
shader = tr.shaders[ dsurf->hShader[ 0 ] ];
SM->bRendered = qtrue;
R_AddDrawSurf( ( surfaceType_t * )&g_staticSurfaces[ g_nStaticSurfaces ], shader, 0, 0, 0, 0 );
g_nStaticSurfaces++;
ofsStaticData += surface->numVerts;
}
}
}
}
tr.shiftedIsStatic = 0;
}
/*
=============
RB_StaticMesh
=============
*/
void RB_StaticMesh( staticSurface_t *staticSurf ) {
int i, j;
dtiki_t *tiki;
skelSurfaceGame_t *surf;
int meshNum;
skelHeaderGame_t *skelmodel;
int render_count;
skelIndex_t *collapse_map;
skelIndex_t *triangles;
int indexes;
int baseIndex, baseVertex;
short collapse[ 1000 ];
tiki = backEnd.currentStaticModel->tiki;
surf = staticSurf->surface;
assert(surf->pStaticXyz);
meshNum = staticSurf->meshNum;
skelmodel = TIKI_GetSkel(tiki->mesh[meshNum]);
// FIXME: LOD
render_count = surf->numVerts;
if (tess.numVertexes + render_count >= TIKI_MAX_VERTEXES ||
tess.numIndexes + surf->numTriangles >= TIKI_MAX_TRIANGLES * 3) {
RB_CHECKOVERFLOW(render_count, surf->numTriangles);
}
collapse_map = surf->pCollapse;
triangles = surf->pTriangles;
indexes = surf->numTriangles * 3;
baseIndex = tess.numIndexes;
baseVertex = tess.numVertexes;
tess.numVertexes += render_count;
if (render_count == surf->numVerts)
{
for (j = 0; j < indexes; j++) {
tess.indexes[baseIndex + j] = baseVertex + triangles[j];
}
tess.numIndexes += indexes;
}
else
{
for (i = 0; i < render_count; i++) {
collapse[i] = i;
}
for (i = 0; i < surf->numVerts; i++) {
collapse[i] = collapse[collapse_map[i]];
}
for (j = 0; j < indexes; j += 3)
{
if (collapse[triangles[j]] == collapse[triangles[j + 1]] ||
collapse[triangles[j + 1]] == collapse[triangles[j + 2]] ||
collapse[triangles[j + 2]] == collapse[triangles[j]])
{
break;
}
tess.indexes[baseIndex + j] = baseVertex + collapse[triangles[j]];
tess.indexes[baseIndex + j + 1] = baseVertex + collapse[triangles[j + 1]];
tess.indexes[baseIndex + j + 2] = baseVertex + collapse[triangles[j + 2]];
}
tess.numIndexes += j;
}
for (j = 0; j < render_count; j++) {
Vector4Copy(surf->pStaticXyz[j], tess.xyz[baseVertex + j]);
Vector4Copy(surf->pStaticNormal[j], tess.normal[baseVertex + j]);
tess.texCoords[baseVertex + j][0] = surf->pStaticTexCoords[j][0][0];
tess.texCoords[baseVertex + j][1] = surf->pStaticTexCoords[j][0][1];
}
if (backEndData->staticModels) {
color4ub_t* in = (color4ub_t*)&backEndData->staticModelData[backEnd.currentStaticModel->firstVertexData + staticSurf->ofsStaticData];
for (i = 0; i < render_count; i++, in++)
{
tess.color[baseVertex + i][0] = (*in)[0] * 257;
tess.color[baseVertex + i][0] = (*in)[1] * 257;
tess.color[baseVertex + i][0] = (*in)[2] * 257;
tess.color[baseVertex + i][0] = 65535;
}
}
else {
for (i = 0; i < render_count; i++) {
tess.color[baseVertex + i][0] = 65535;
tess.color[baseVertex + i][1] = 65535;
tess.color[baseVertex + i][2] = 65535;
tess.color[baseVertex + i][3] = 65535;
}
}
}

View file

@ -447,9 +447,6 @@ static qboolean RB_SurfaceVaoCached(int numVerts, srfVert_t *verts, int numIndex
return qtrue;
}
void RB_SurfaceMarkFragment(srfMarkFragment_t* p) {
// FIXME: unimplemented
}
/*
=============
@ -555,6 +552,337 @@ static void RB_SurfaceBeam( void )
tess.firstIndex = 0;
}
//================================================================================
static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth )
{
float spanWidth2;
int vbase;
float t = len / 256.0f;
RB_CheckVao(tess.vao);
RB_CHECKOVERFLOW( 4, 6 );
vbase = tess.numVertexes;
spanWidth2 = -spanWidth;
// FIXME: use quad stamp?
VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0] = 0;
tess.texCoords[tess.numVertexes][1] = 0;
tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25f * 257.0f;
tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25f * 257.0f;
tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25f * 257.0f;
tess.numVertexes++;
VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0] = 0;
tess.texCoords[tess.numVertexes][1] = 1;
tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257;
tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257;
tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257;
tess.numVertexes++;
VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0] = t;
tess.texCoords[tess.numVertexes][1] = 0;
tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257;
tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257;
tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257;
tess.numVertexes++;
VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0] = t;
tess.texCoords[tess.numVertexes][1] = 1;
tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257;
tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257;
tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257;
tess.numVertexes++;
tess.indexes[tess.numIndexes++] = vbase;
tess.indexes[tess.numIndexes++] = vbase + 1;
tess.indexes[tess.numIndexes++] = vbase + 2;
tess.indexes[tess.numIndexes++] = vbase + 2;
tess.indexes[tess.numIndexes++] = vbase + 1;
tess.indexes[tess.numIndexes++] = vbase + 3;
}
static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up )
{
int i;
vec3_t pos[4];
vec3_t v;
int spanWidth = r_railWidth->integer;
float c, s;
float scale;
if ( numSegs > 1 )
numSegs--;
if ( !numSegs )
return;
scale = 0.25;
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] );
}
}
RB_CheckVao(tess.vao);
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] = (j < 2);
tess.texCoords[tess.numVertexes][1] = (j && j != 3);
tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257;
tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257;
tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257;
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
*/
static 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
*/
static 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
*/
static 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 );
}
}
static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
{
float *outXyz;
int16_t *outNormal, *outTangent;
mdvVertex_t *newVerts;
int vertNum;
newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
outTangent = tess.tangent[tess.numVertexes];
if (backlerp == 0)
{
//
// just copy the vertexes
//
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
VectorCopy(newVerts->xyz, outXyz);
VectorCopy4(newVerts->normal, outNormal);
VectorCopy4(newVerts->tangent, outTangent);
newVerts++;
outXyz += 4;
outNormal += 4;
outTangent += 4;
}
}
else
{
//
// interpolate and copy the vertex and normal
//
mdvVertex_t *oldVerts;
oldVerts = surf->verts + backEnd.currentEntity->e.oldframe * surf->numVerts;
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
VectorLerp(newVerts->xyz, oldVerts->xyz, backlerp, outXyz);
outNormal[0] = (int16_t)(newVerts->normal[0] * (1.0f - backlerp) + oldVerts->normal[0] * backlerp);
outNormal[1] = (int16_t)(newVerts->normal[1] * (1.0f - backlerp) + oldVerts->normal[1] * backlerp);
outNormal[2] = (int16_t)(newVerts->normal[2] * (1.0f - backlerp) + oldVerts->normal[2] * backlerp);
outNormal[3] = 0;
outTangent[0] = (int16_t)(newVerts->tangent[0] * (1.0f - backlerp) + oldVerts->tangent[0] * backlerp);
outTangent[1] = (int16_t)(newVerts->tangent[1] * (1.0f - backlerp) + oldVerts->tangent[1] * backlerp);
outTangent[2] = (int16_t)(newVerts->tangent[2] * (1.0f - backlerp) + oldVerts->tangent[2] * backlerp);
outTangent[3] = newVerts->tangent[3];
newVerts++;
oldVerts++;
outXyz += 4;
outNormal += 4;
outTangent += 4;
}
}
}
/*
=============
RB_SurfaceMesh
=============
*/
static void RB_SurfaceMesh(mdvSurface_t *surface) {
int j;
float backlerp;
mdvSt_t *texCoords;
int Bob, Doug;
int numVerts;
if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
backlerp = 0;
} else {
backlerp = backEnd.currentEntity->e.backlerp;
}
RB_CheckVao(tess.vao);
RB_CHECKOVERFLOW( surface->numVerts, surface->numIndexes );
LerpMeshVertexes (surface, backlerp);
Bob = tess.numIndexes;
Doug = tess.numVertexes;
for (j = 0 ; j < surface->numIndexes ; j++) {
tess.indexes[Bob + j] = Doug + surface->indexes[j];
}
tess.numIndexes += surface->numIndexes;
texCoords = surface->st;
numVerts = surface->numVerts;
for ( j = 0; j < numVerts; j++ ) {
tess.texCoords[Doug + j][0] = texCoords[j].st[0];
tess.texCoords[Doug + j][1] = texCoords[j].st[1];
// FIXME: fill in lightmapST for completeness?
}
tess.numVertexes += surface->numVerts;
}
/*
==============
RB_SurfaceFace
@ -853,6 +1181,15 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) {
case RT_BEAM:
RB_SurfaceBeam();
break;
case RT_RAIL_CORE:
RB_SurfaceRailCore();
break;
case RT_RAIL_RINGS:
RB_SurfaceRailRings();
break;
case RT_LIGHTNING:
RB_SurfaceLightningBolt();
break;
default:
RB_SurfaceAxis();
break;
@ -902,7 +1239,7 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface)
refEnt = &backEnd.currentEntity->e;
glState.vertexAttribsInterpolation = (refEnt->wasframe == refEnt->frameInfo[0].index) ? 0.0f : refEnt->actionWeight;
glState.vertexAttribsInterpolation = (refEnt->oldframe == refEnt->frame) ? 0.0f : refEnt->backlerp;
if (surface->mdvModel->numFrames > 1)
{
@ -916,7 +1253,7 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface)
qglBindBuffer(GL_ARRAY_BUFFER, surface->vao->vertexesVBO);
}
frameOffset = refEnt->wasframe * surface->vao->frameSize;
frameOffset = refEnt->frame * surface->vao->frameSize;
attribIndex = ATTR_INDEX_POSITION;
vAtb = &surface->vao->attribs[attribIndex];
@ -930,7 +1267,7 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface)
vAtb = &surface->vao->attribs[attribIndex];
qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset));
frameOffset = refEnt->wasframe * surface->vao->frameSize;
frameOffset = refEnt->oldframe * surface->vao->frameSize;
attribIndex = ATTR_INDEX_POSITION2;
vAtb = &surface->vao->attribs[attribIndex];
@ -962,29 +1299,19 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface)
static void RB_SurfaceSkip( void *surf ) {
}
void RB_DrawTerrainTris(srfTerrain_t* p) {
// FIXME: unimplemented
}
void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void*) = {
(void(*)(void*))RB_SurfaceBad, // SF_BAD,
(void(*)(void*))RB_SurfaceSkip, // SF_SKIP,
(void(*)(void*))RB_SurfaceFace, // SF_FACE,
(void(*)(void*))RB_SurfaceGrid, // SF_GRID,
(void(*)(void*))RB_SurfacePolychain, // SF_POLY,
(void(*)(void*))RB_SurfaceMarkFragment, // SF_MARK_FRAG
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))NULL, // SF_DISPLAY_LIST
(void(*)(void*))RB_SkelMesh, // SF_TIKI_SKEL
(void(*)(void*))RB_StaticMesh, // SF_TIKI_STATIC
(void(*)(void*))RB_DrawSwipeSurface, // SF_SWIPE
(void(*)(void*))RB_DrawSprite, // SF_SPRITE
(void(*)(void*))RB_DrawTerrainTris, // SF_TERRAIN_PATCH
(void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES,
NULL,
NULL,
NULL,
NULL,
NULL
void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceBad, // SF_BAD,
(void(*)(void*))RB_SurfaceSkip, // SF_SKIP,
(void(*)(void*))RB_SurfaceFace, // SF_FACE,
(void(*)(void*))RB_SurfaceGrid, // SF_GRID,
(void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES,
(void(*)(void*))RB_SurfacePolychain, // SF_POLY,
(void(*)(void*))RB_SurfaceMesh, // SF_MDV,
(void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR,
(void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM,
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))RB_SurfaceVaoMdvMesh, // SF_VAO_MDVMESH
(void(*)(void*))RB_IQMSurfaceAnimVao, // SF_VAO_IQM
};

View file

@ -1,44 +0,0 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_swipe.cpp -- swipe rendering
#include "tr_local.h"
void RB_DrawSwipeSurface(surfaceType_t* pswipe) {
// FIXME: unimplemented
}
void RE_SwipeBegin(float thistime, float life, qhandle_t shader)
{
// FIXME: unimplemented
}
void RE_SwipePoint(vec3_t point1, vec3_t point2, float time)
{
// FIXME: unimplemented
}
void RE_SwipeEnd()
{
// FIXME: unimplemented
}

View file

@ -1,259 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_util.c -- renderer utility
#include "tr_local.h"
static vec4_t cntColor;
static float cntSt[ 2 ];
/*
===============
RB_StreamBegin
===============
*/
void RB_StreamBegin( shader_t *shader ) {
RB_BeginSurface( shader, 0, 0 );
}
/*
===============
RB_StreamEnd
===============
*/
void RB_StreamEnd( void ) {
int i;
if( tess.numVertexes <= 2 ) {
RB_EndSurface();
return;
}
tess.indexes[ 0 ] = 0;
tess.indexes[ 1 ] = 1;
tess.indexes[ 2 ] = 2;
for( i = 0; i < tess.numVertexes - 2; i++ ) {
tess.indexes[ i * 3 + 0 ] = ( i & 1 ) + i;
tess.indexes[ i * 3 + 1 ] = i - ( ( i & 1 ) - 1 );
tess.indexes[ i * 3 + 2 ] = i + 2;
tess.numIndexes += 3;
}
RB_EndSurface();
}
/*
===============
RB_StreamBeginDrawSurf
===============
*/
void RB_StreamBeginDrawSurf( void ) {
backEnd.dsStreamVert = tess.numVertexes;
}
/*
===============
RB_StreamEndDrawSurf
===============
*/
void RB_StreamEndDrawSurf( void ) {
int numverts;
int i;
if( tess.numVertexes - backEnd.dsStreamVert <= 2 ) {
tess.numVertexes = backEnd.dsStreamVert;
return;
}
numverts = tess.numVertexes - backEnd.dsStreamVert - 2;
for( i = 0; i < numverts; i++ ) {
tess.indexes[ i + tess.numIndexes ] = ( i & 1 ) + i + backEnd.dsStreamVert;
tess.indexes[ i + tess.numIndexes + 1 ] = i + backEnd.dsStreamVert - ( ( i & 1 ) - 1 );
tess.indexes[ i + tess.numIndexes + 2 ] = i + backEnd.dsStreamVert + 2;
tess.numIndexes += 3;
}
}
/*
===============
addTriangle
===============
*/
static void addTriangle( void ) {
tess.texCoords[ tess.numVertexes ][ 0 ] = cntSt[ 0 ];
tess.texCoords[ tess.numVertexes ][ 1 ] = cntSt[ 1 ];
tess.color[ tess.numVertexes ][ 0 ] = cntColor[ 0 ];
tess.color[ tess.numVertexes ][ 1 ] = cntColor[ 1 ];
tess.color[ tess.numVertexes ][ 2 ] = cntColor[ 2 ];
tess.color[ tess.numVertexes ][ 3 ] = cntColor[ 3 ];
tess.numVertexes++;
}
/*
===============
RB_Vertex3fv
===============
*/
void RB_Vertex3fv( vec3_t v ) {
VectorCopy( v, tess.xyz[ tess.numVertexes ] );
addTriangle();
}
/*
===============
RB_Vertex3f
===============
*/
void RB_Vertex3f( vec_t x, vec_t y, vec_t z ) {
tess.xyz[ tess.numVertexes ][ 0 ] = x;
tess.xyz[ tess.numVertexes ][ 1 ] = y;
tess.xyz[ tess.numVertexes ][ 2 ] = z;
addTriangle();
}
/*
===============
RB_Vertex2f
===============
*/
void RB_Vertex2f( vec_t x, vec_t y ) {
RB_Vertex3f( x, y, 0 );
}
/*
===============
RB_Color4f
===============
*/
void RB_Color4f( vec_t r, vec_t g, vec_t b, vec_t a ) {
cntColor[ 0 ] = r;
cntColor[ 1 ] = g;
cntColor[ 2 ] = b;
cntColor[ 3 ] = a;
}
/*
===============
RB_Color3f
===============
*/
void RB_Color3f( vec_t r, vec_t g, vec_t b ) {
RB_Color4f( r, g, b, 1.0 );
}
/*
===============
RB_Color3fv
===============
*/
void RB_Color3fv( vec3_t col ) {
RB_Color3f( col[ 0 ], col[ 1 ], col[ 2 ] );
}
/*
===============
RB_Color4bv
===============
*/
void RB_Color4bv( unsigned char *colors ) {
cntColor[ 0 ] = colors[ 0 ] * 255.0;
cntColor[ 1 ] = colors[ 1 ] * 255.0;
cntColor[ 2 ] = colors[ 2 ] * 255.0;
cntColor[ 3 ] = colors[ 3 ] * 255.0;
}
/*
===============
RB_Texcoord2f
===============
*/
void RB_Texcoord2f( float s, float t ) {
cntSt[ 0 ] = s;
cntSt[ 1 ] = t;
}
/*
===============
RB_Texcoord2fv
===============
*/
void RB_Texcoord2fv( vec2_t st ) {
cntSt[ 0 ] = st[ 0 ];
cntSt[ 1 ] = st[ 1 ];
}
static int Numbers[ 12 ][ 8 ];
static float Lines[ 13 ][ 4 ];
/*
===============
R_DrawDebugNumber
===============
*/
void R_DrawDebugNumber( const vec3_t org, float number, float scale, float r, float g, float b, int precision ) {
// FIXME: unimplemented
}
/*
===============
R_DebugRotatedBBox
===============
*/
void R_DebugRotatedBBox( const vec3_t org, vec3_t ang, vec3_t mins, vec3_t maxs, float r, float g, float b, float alpha ) {
}
/*
===============
RE_GetShaderWidth
===============
*/
int RE_GetShaderWidth( qhandle_t hShader ) {
shader_t *shader;
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
} else {
shader = tr.defaultShader;
}
return shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadWidth;
}
/*
===============
RE_GetShaderHeight
===============
*/
int RE_GetShaderHeight( qhandle_t hShader ) {
shader_t *shader;
if( hShader ) {
shader = R_GetShaderByHandle( hShader );
}
else {
shader = tr.defaultShader;
}
return shader->stages[ 0 ]->bundle[ 0 ].image[ 0 ]->uploadHeight;
}

View file

@ -130,7 +130,7 @@ vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *ind
R_IssuePendingRenderCommands();
vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao));
vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
tr.numVaos++;
memset(vao, 0, sizeof(*vao));
@ -198,7 +198,7 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int num
R_IssuePendingRenderCommands();
vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao));
vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
tr.numVaos++;
memset(vao, 0, sizeof(*vao));

View file

@ -393,10 +393,6 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
=============================================================
*/
void R_GetInlineModelBounds(int iIndex, vec3_t vMins, vec3_t vMaxs)
{
// FIXME: unimplemented
}
/*
================
@ -632,6 +628,25 @@ static const byte *R_ClusterPVS (int cluster) {
return tr.world->vis + cluster * tr.world->clusterBytes;
}
/*
=================
R_inPVS
=================
*/
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ) {
mnode_t *leaf;
byte *vis;
leaf = R_PointInLeaf( p1 );
vis = ri.CM_ClusterPVS( leaf->cluster ); // why not R_ClusterPVS ??
leaf = R_PointInLeaf( p2 );
if ( !(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) {
return qfalse;
}
return qtrue;
}
/*
===============
R_MarkLeaves