13 Oct 2008
This commit is contained in:
parent
c735574f4c
commit
92c5a0e536
|
@ -1454,7 +1454,7 @@ extern int numVertsIlluminated;
|
|||
extern int numRawLightmaps;
|
||||
extern rawLightmap_t *rawLightmaps;
|
||||
|
||||
bool PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
|
||||
bool BspPlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
|
||||
bool RadSampleImage( byte *pixels, int width, int height, float st[2], float color[4] );
|
||||
|
||||
#endif//BSPLIB_H
|
|
@ -291,7 +291,7 @@ static int MakeDecalProjector( bsp_shader_t *si, vec4_t projection, float distan
|
|||
dp->radius2 = dp->radius * dp->radius;
|
||||
|
||||
// make the front plane
|
||||
if( !PlaneFromPoints( dp->planes[0], dv[0]->point, dv[1]->point, dv[2]->point ))
|
||||
if( !BspPlaneFromPoints( dp->planes[0], dv[0]->point, dv[1]->point, dv[2]->point ))
|
||||
return -1;
|
||||
|
||||
// make the back plane
|
||||
|
@ -304,7 +304,7 @@ static int MakeDecalProjector( bsp_shader_t *si, vec4_t projection, float distan
|
|||
{
|
||||
j = (i + 1) % numVerts;
|
||||
VectorMA( dv[i]->point, distance, projection, xyz );
|
||||
if( !PlaneFromPoints( dp->planes[i+2], dv[j]->point, dv[i]->point, xyz ) )
|
||||
if( !BspPlaneFromPoints( dp->planes[i+2], dv[j]->point, dv[i]->point, xyz ) )
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ void ProcessDecals( void )
|
|||
|
||||
// planar? (nuking this optimization as it doesn't work on non-rectangular quads)
|
||||
plane[0] = 0.0f; // stupid msvc
|
||||
if( 0 && PlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point ) &&
|
||||
if( 0 && BspPlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point ) &&
|
||||
fabs( DotProduct( dv[1]->point, plane ) - plane[3] ) <= PLANAR_EPSILON )
|
||||
{
|
||||
// make a quad projector
|
||||
|
@ -464,7 +464,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, drawsurf_t *ds, windi
|
|||
VectorAdd( w->p[i], entityOrigin, w->p[i] );
|
||||
|
||||
// make a plane from the winding
|
||||
if( !PlaneFromPoints( plane, w->p[0], w->p[1], w->p[2] ))
|
||||
if( !BspPlaneFromPoints( plane, w->p[0], w->p[1], w->p[2] ))
|
||||
{
|
||||
FreeWinding( w );
|
||||
return;
|
||||
|
|
|
@ -248,13 +248,13 @@ int MapPlaneFromPoints( vec3_t *p )
|
|||
|
||||
/*
|
||||
=====================
|
||||
PlaneFromPoints
|
||||
BspPlaneFromPoints
|
||||
|
||||
Returns false if the triangle is degenrate.
|
||||
The normal will point out of the clock for clockwise ordered points
|
||||
=====================
|
||||
*/
|
||||
bool PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c )
|
||||
bool BspPlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c )
|
||||
{
|
||||
vec3_t d1, d2;
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ void InsertModel( const char *name, int body, int seq, float frame, matrix4x4 tr
|
|||
normal = pe->StudioGetNormal( surface, i );
|
||||
VectorCopy( normal, dv->normal );
|
||||
|
||||
// FIXME: may be need Matrix4x4_TransposeRotate ???
|
||||
Matrix4x4_Rotate( nTransform, dv->normal, dv->normal );
|
||||
// FIXME: need to transpose ???
|
||||
Matrix4x4_Transform3x3( nTransform, dv->normal, dv->normal );
|
||||
VectorNormalize( dv->normal );
|
||||
|
||||
// added support for explicit shader texcoord generation
|
||||
|
@ -167,7 +167,7 @@ void InsertModel( const char *name, int body, int seq, float frame, matrix4x4 tr
|
|||
}
|
||||
|
||||
// make plane for triangle
|
||||
if( PlaneFromPoints( plane, points[0], points[1], points[2] ))
|
||||
if( BspPlaneFromPoints( plane, points[0], points[1], points[2] ))
|
||||
{
|
||||
// regenerate back points
|
||||
for( j = 0; j < 3; j++ )
|
||||
|
@ -199,10 +199,10 @@ void InsertModel( const char *name, int body, int seq, float frame, matrix4x4 tr
|
|||
VectorScale( nadir, 0.3333333333333f, nadir );
|
||||
VectorMA( nadir, -2.0f, plane, nadir );
|
||||
|
||||
/* make 3 more planes */
|
||||
if( PlaneFromPoints( pa, points[2], points[1], backs[1] ) &&
|
||||
PlaneFromPoints( pb, points[1], points[0], backs[0] ) &&
|
||||
PlaneFromPoints( pc, points[0], points[2], backs[2] ))
|
||||
// make 3 more planes
|
||||
if( BspPlaneFromPoints( pa, points[2], points[1], backs[1] ) &&
|
||||
BspPlaneFromPoints( pb, points[1], points[0], backs[0] ) &&
|
||||
BspPlaneFromPoints( pc, points[0], points[2], backs[2] ))
|
||||
{
|
||||
// build a brush
|
||||
buildBrush = AllocBrush( 48 );
|
||||
|
|
|
@ -623,7 +623,7 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, bsp_shader_t
|
|||
dv[2] = &mesh->verts[pw[r+2]];
|
||||
dv[3] = &mesh->verts[pw[r+3]];
|
||||
|
||||
planar = PlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point );
|
||||
planar = BspPlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point );
|
||||
if( planar )
|
||||
{
|
||||
dist = DotProduct( dv[1]->point, plane ) - plane[3];
|
||||
|
|
|
@ -592,7 +592,7 @@ static bool MapTriangle( rawLightmap_t *lm, surfaceInfo_t *info, dvertex_t *dv[3
|
|||
VectorCopy( lm->plane, plane );
|
||||
plane[3] = lm->plane[3];
|
||||
}
|
||||
else if( !PlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point ))
|
||||
else if( !BspPlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point ))
|
||||
return false;
|
||||
|
||||
// check to see if we need to calculate texture->world tangent vectors
|
||||
|
@ -738,7 +738,7 @@ static bool MapQuad( rawLightmap_t *lm, surfaceInfo_t *info, dvertex_t *dv[4] )
|
|||
VectorCopy( lm->plane, plane );
|
||||
plane[3] = lm->plane[3];
|
||||
}
|
||||
else if( !PlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point ))
|
||||
else if( !BspPlaneFromPoints( plane, dv[0]->point, dv[1]->point, dv[2]->point ))
|
||||
return false;
|
||||
|
||||
// 4th point must fall on the plane
|
||||
|
|
|
@ -481,7 +481,7 @@ static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum )
|
|||
// create winding plane if necessary, filtering out bogus windings as well
|
||||
if( nodeNum == headNodeNum )
|
||||
{
|
||||
if( !PlaneFromPoints( tw->plane, tw->v[0].point, tw->v[1].point, tw->v[2].point ) )
|
||||
if( !BspPlaneFromPoints( tw->plane, tw->v[0].point, tw->v[1].point, tw->v[2].point ))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ int FindMetaTriangle( metaTriangle_t *src, dvertex_t *a, dvertex_t *b, dvertex_t
|
|||
{
|
||||
// calculate a plane from the triangle's points (and bail if a plane can't be constructed)
|
||||
src->planeNum = -1;
|
||||
if( PlaneFromPoints( src->plane, a->point, b->point, c->point ) == false )
|
||||
if( BspPlaneFromPoints( src->plane, a->point, b->point, c->point ) == false )
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1177,7 +1177,7 @@ static void SubdivideFoliageTriangle_r( drawsurf_t *ds, foliage_t *foliage, dver
|
|||
if( numFoliageInstances >= MAX_FOLIAGE_INSTANCES )
|
||||
return;
|
||||
|
||||
if( !PlaneFromPoints( plane, tri[0]->point, tri[1]->point, tri[2]->point ))
|
||||
if( !BspPlaneFromPoints( plane, tri[0]->point, tri[1]->point, tri[2]->point ))
|
||||
return;
|
||||
if( plane[2] < 0.5f ) return;
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ typedef struct
|
|||
vec3_t *pos[MAXSTUDIOSRCBONES];
|
||||
vec3_t *rot[MAXSTUDIOSRCBONES];
|
||||
int numanim[MAXSTUDIOSRCBONES][6];
|
||||
mstudioanimvalue_t *anim[MAXSTUDIOSRCBONES][6];
|
||||
dstudioanimvalue_t *anim[MAXSTUDIOSRCBONES][6];
|
||||
} s_animation_t;
|
||||
|
||||
typedef struct
|
||||
|
|
107
common/studio.c
107
common/studio.c
|
@ -6,6 +6,9 @@
|
|||
#include "mdllib.h"
|
||||
#include "matrixlib.h"
|
||||
|
||||
#undef ALIGN
|
||||
#define ALIGN( a ) a = (byte *)((int)((byte *)a + 3) & ~ 3)
|
||||
|
||||
bool cdset;
|
||||
bool ignore_errors;
|
||||
|
||||
|
@ -79,8 +82,8 @@ string sourcetexture[64];
|
|||
string mirrored[MAXSTUDIOSRCBONES];
|
||||
|
||||
s_mesh_t *pmesh;
|
||||
studiohdr_t *phdr;
|
||||
studioseqhdr_t *pseqhdr;
|
||||
dstudiohdr_t *phdr;
|
||||
dstudioseqhdr_t *pseqhdr;
|
||||
s_sequencegroup_t sequencegroup;
|
||||
s_trianglevert_t (*triangles)[3];
|
||||
s_model_t *model[MAXSTUDIOMODELS];
|
||||
|
@ -104,13 +107,13 @@ WriteBoneInfo
|
|||
void WriteBoneInfo( void )
|
||||
{
|
||||
int i, j;
|
||||
mstudiobone_t *pbone;
|
||||
mstudiobonecontroller_t *pbonecontroller;
|
||||
mstudioattachment_t *pattachment;
|
||||
mstudiobbox_t *pbbox;
|
||||
dstudiobone_t *pbone;
|
||||
dstudiobonecontroller_t *pbonecontroller;
|
||||
dstudioattachment_t *pattachment;
|
||||
dstudiobbox_t *pbbox;
|
||||
|
||||
// save bone info
|
||||
pbone = (mstudiobone_t *)pData;
|
||||
pbone = (dstudiobone_t *)pData;
|
||||
phdr->numbones = numbones;
|
||||
phdr->boneindex = (pData - pStart);
|
||||
|
||||
|
@ -133,7 +136,7 @@ void WriteBoneInfo( void )
|
|||
pbone[i].scale[5] = bonetable[i].rotscale[2];
|
||||
}
|
||||
|
||||
pData += numbones * sizeof( mstudiobone_t );
|
||||
pData += numbones * sizeof( dstudiobone_t );
|
||||
ALIGN( pData );
|
||||
|
||||
// map bonecontroller to bones
|
||||
|
@ -173,7 +176,7 @@ void WriteBoneInfo( void )
|
|||
}
|
||||
|
||||
// save bonecontroller info
|
||||
pbonecontroller = (mstudiobonecontroller_t *)pData;
|
||||
pbonecontroller = (dstudiobonecontroller_t *)pData;
|
||||
phdr->numbonecontrollers = numbonecontrollers;
|
||||
phdr->bonecontrollerindex = (pData - pStart);
|
||||
|
||||
|
@ -186,11 +189,11 @@ void WriteBoneInfo( void )
|
|||
pbonecontroller[i].end = bonecontroller[i].end;
|
||||
}
|
||||
|
||||
pData += numbonecontrollers * sizeof( mstudiobonecontroller_t );
|
||||
pData += numbonecontrollers * sizeof( dstudiobonecontroller_t );
|
||||
ALIGN( pData );
|
||||
|
||||
// save attachment info
|
||||
pattachment = (mstudioattachment_t *)pData;
|
||||
pattachment = (dstudioattachment_t *)pData;
|
||||
phdr->numattachments = numattachments;
|
||||
phdr->attachmentindex = (pData - pStart);
|
||||
|
||||
|
@ -200,11 +203,11 @@ void WriteBoneInfo( void )
|
|||
VectorCopy( attachment[i].org, pattachment[i].org );
|
||||
}
|
||||
|
||||
pData += numattachments * sizeof( mstudioattachment_t );
|
||||
pData += numattachments * sizeof( dstudioattachment_t );
|
||||
ALIGN( pData );
|
||||
|
||||
// save bbox info
|
||||
pbbox = (mstudiobbox_t *)pData;
|
||||
pbbox = (dstudiobbox_t *)pData;
|
||||
phdr->numhitboxes = numhitboxes;
|
||||
phdr->hitboxindex = (pData - pStart);
|
||||
|
||||
|
@ -216,7 +219,7 @@ void WriteBoneInfo( void )
|
|||
VectorCopy( hitbox[i].bmax, pbbox[i].bbmax );
|
||||
}
|
||||
|
||||
pData += numhitboxes * sizeof( mstudiobbox_t );
|
||||
pData += numhitboxes * sizeof( dstudiobbox_t );
|
||||
ALIGN( pData );
|
||||
}
|
||||
|
||||
|
@ -229,20 +232,20 @@ void WriteSequenceInfo( void )
|
|||
{
|
||||
int i, j;
|
||||
|
||||
mstudioseqgroup_t *pseqgroup;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
mstudioseqdesc_t *pbaseseqdesc;
|
||||
mstudioevent_t *pevent;
|
||||
mstudiopivot_t *ppivot;
|
||||
dstudioseqgroup_t *pseqgroup;
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
dstudioseqdesc_t *pbaseseqdesc;
|
||||
dstudioevent_t *pevent;
|
||||
dstudiopivot_t *ppivot;
|
||||
byte *ptransition;
|
||||
|
||||
|
||||
// save sequence info
|
||||
pseqdesc = (mstudioseqdesc_t *)pData;
|
||||
pseqdesc = (dstudioseqdesc_t *)pData;
|
||||
pbaseseqdesc = pseqdesc;
|
||||
phdr->numseq = numseq;
|
||||
phdr->seqindex = (pData - pStart);
|
||||
pData += numseq * sizeof( mstudioseqdesc_t );
|
||||
pData += numseq * sizeof( dstudioseqdesc_t );
|
||||
|
||||
for (i = 0; i < numseq; i++, pseqdesc++)
|
||||
{
|
||||
|
@ -279,10 +282,10 @@ void WriteSequenceInfo( void )
|
|||
totalseconds += sequence[i]->numframes / sequence[i]->fps;
|
||||
|
||||
// save events
|
||||
pevent = (mstudioevent_t *)pData;
|
||||
pevent = (dstudioevent_t *)pData;
|
||||
pseqdesc->numevents = sequence[i]->numevents;
|
||||
pseqdesc->eventindex = (pData - pStart);
|
||||
pData += pseqdesc->numevents * sizeof( mstudioevent_t );
|
||||
pData += pseqdesc->numevents * sizeof( dstudioevent_t );
|
||||
|
||||
for (j = 0; j < sequence[i]->numevents; j++)
|
||||
{
|
||||
|
@ -294,10 +297,10 @@ void WriteSequenceInfo( void )
|
|||
ALIGN( pData );
|
||||
|
||||
// save pivots
|
||||
ppivot = (mstudiopivot_t *)pData;
|
||||
ppivot = (dstudiopivot_t *)pData;
|
||||
pseqdesc->numpivots = sequence[i]->numpivots;
|
||||
pseqdesc->pivotindex = (pData - pStart);
|
||||
pData += pseqdesc->numpivots * sizeof( mstudiopivot_t );
|
||||
pData += pseqdesc->numpivots * sizeof( dstudiopivot_t );
|
||||
|
||||
for (j = 0; j < sequence[i]->numpivots; j++)
|
||||
{
|
||||
|
@ -310,10 +313,10 @@ void WriteSequenceInfo( void )
|
|||
}
|
||||
|
||||
// save sequence group info
|
||||
pseqgroup = (mstudioseqgroup_t *)pData;
|
||||
pseqgroup = (dstudioseqgroup_t *)pData;
|
||||
phdr->numseqgroups = 1;
|
||||
phdr->seqgroupindex = (pData - pStart);
|
||||
pData += sizeof( mstudioseqgroup_t );
|
||||
pData += sizeof( dstudioseqgroup_t );
|
||||
|
||||
ALIGN( pData );
|
||||
|
||||
|
@ -341,20 +344,20 @@ byte *WriteAnimations( byte *pData, byte *pStart, int group )
|
|||
{
|
||||
int i, j, k, q, n;
|
||||
|
||||
mstudioanim_t *panim;
|
||||
mstudioanimvalue_t *panimvalue;
|
||||
dstudioanim_t *panim;
|
||||
dstudioanimvalue_t *panimvalue;
|
||||
|
||||
for (i = 0; i < numseq; i++)
|
||||
{
|
||||
if (sequence[i]->seqgroup == group)
|
||||
{
|
||||
// save animations
|
||||
panim = (mstudioanim_t *)pData;
|
||||
panim = (dstudioanim_t *)pData;
|
||||
sequence[i]->animindex = (pData - pStart);
|
||||
pData += sequence[i]->numblends * numbones * sizeof( mstudioanim_t );
|
||||
pData += sequence[i]->numblends * numbones * sizeof( dstudioanim_t );
|
||||
ALIGN( pData );
|
||||
|
||||
panimvalue = (mstudioanimvalue_t *)pData;
|
||||
panimvalue = (dstudioanimvalue_t *)pData;
|
||||
for (q = 0; q < sequence[i]->numblends; q++)
|
||||
{
|
||||
// save animation value info
|
||||
|
@ -396,15 +399,15 @@ WriteTextures
|
|||
*/
|
||||
void WriteTextures( void )
|
||||
{
|
||||
mstudiotexture_t *ptexture;
|
||||
dstudiotexture_t *ptexture;
|
||||
short *pref;
|
||||
int i, j;
|
||||
|
||||
// save bone info
|
||||
ptexture = (mstudiotexture_t *)pData;
|
||||
ptexture = (dstudiotexture_t *)pData;
|
||||
phdr->numtextures = numtextures;
|
||||
phdr->textureindex = (pData - pStart);
|
||||
pData += numtextures * sizeof( mstudiotexture_t );
|
||||
pData += numtextures * sizeof( dstudiotexture_t );
|
||||
ALIGN( pData );
|
||||
|
||||
phdr->skinindex = (pData - pStart);
|
||||
|
@ -447,24 +450,24 @@ WriteModel
|
|||
*/
|
||||
void WriteModel( void )
|
||||
{
|
||||
mstudiobodyparts_t *pbodypart;
|
||||
mstudiomodel_t *pmodel;
|
||||
dstudiobodyparts_t *pbodypart;
|
||||
dstudiomodel_t *pmodel;
|
||||
byte *pbone;
|
||||
vec3_t *pvert;
|
||||
vec3_t *pnorm;
|
||||
mstudiomesh_t *pmesh;
|
||||
dstudiomesh_t *pmesh;
|
||||
s_trianglevert_t *psrctri;
|
||||
int i, j, k, cur;
|
||||
int total_tris = 0;
|
||||
int total_strips = 0;
|
||||
|
||||
pbodypart = (mstudiobodyparts_t *)pData;
|
||||
pbodypart = (dstudiobodyparts_t *)pData;
|
||||
phdr->numbodyparts = numbodyparts;
|
||||
phdr->bodypartindex = (pData - pStart);
|
||||
pData += numbodyparts * sizeof( mstudiobodyparts_t );
|
||||
pData += numbodyparts * sizeof( dstudiobodyparts_t );
|
||||
|
||||
pmodel = (mstudiomodel_t *)pData;
|
||||
pData += nummodels * sizeof( mstudiomodel_t );
|
||||
pmodel = (dstudiomodel_t *)pData;
|
||||
pData += nummodels * sizeof( dstudiomodel_t );
|
||||
|
||||
for (i = 0, j = 0; i < numbodyparts; i++)
|
||||
{
|
||||
|
@ -543,10 +546,10 @@ void WriteModel( void )
|
|||
cur = (int)pData;
|
||||
|
||||
// save mesh info
|
||||
pmesh = (mstudiomesh_t *)pData;
|
||||
pmesh = (dstudiomesh_t *)pData;
|
||||
pmodel[i].nummesh = model[i]->nummesh;
|
||||
pmodel[i].meshindex = (pData - pStart);
|
||||
pData += pmodel[i].nummesh * sizeof( mstudiomesh_t );
|
||||
pData += pmodel[i].nummesh * sizeof( dstudiomesh_t );
|
||||
|
||||
ALIGN( pData );
|
||||
|
||||
|
@ -604,11 +607,11 @@ void WriteMDLFile( void )
|
|||
com.snprintf( texname, MAX_STRING, "%sT.mdl", modeloutname );
|
||||
Msg( "writing %s:\n", texname );
|
||||
|
||||
phdr = (studiohdr_t *)pStart;
|
||||
phdr = (dstudiohdr_t *)pStart;
|
||||
phdr->ident = IDSTUDIOHEADER;
|
||||
phdr->version = STUDIO_VERSION;
|
||||
|
||||
pData = (byte *)phdr + sizeof( studiohdr_t );
|
||||
pData = (byte *)phdr + sizeof( dstudiohdr_t );
|
||||
|
||||
WriteTextures( );
|
||||
|
||||
|
@ -627,7 +630,7 @@ void WriteMDLFile( void )
|
|||
Msg ("---------------------\n");
|
||||
Msg ("writing %s:\n", modeloutname);
|
||||
|
||||
phdr = (studiohdr_t *)pStart;
|
||||
phdr = (dstudiohdr_t *)pStart;
|
||||
phdr->ident = IDSTUDIOHEADER;
|
||||
phdr->version = STUDIO_VERSION;
|
||||
com.strncpy( phdr->name, modeloutname, 64 );
|
||||
|
@ -639,7 +642,7 @@ void WriteMDLFile( void )
|
|||
VectorCopy( cbox[1], phdr->bbmax );
|
||||
|
||||
phdr->flags = gflags;
|
||||
pData = (byte *)phdr + sizeof( studiohdr_t );
|
||||
pData = (byte *)phdr + sizeof( dstudiohdr_t );
|
||||
|
||||
WriteBoneInfo();
|
||||
Msg("bones %6d bytes (%d)\n", pData - pStart - total, numbones );
|
||||
|
@ -1148,9 +1151,9 @@ void SimplifyModel( void )
|
|||
{
|
||||
for (k = 0; k < 6; k++)
|
||||
{
|
||||
mstudioanimvalue_t *pcount, *pvalue;
|
||||
dstudioanimvalue_t *pcount, *pvalue;
|
||||
short value[MAXSTUDIOANIMATIONS];
|
||||
mstudioanimvalue_t data[MAXSTUDIOANIMATIONS];
|
||||
dstudioanimvalue_t data[MAXSTUDIOANIMATIONS];
|
||||
float v;
|
||||
|
||||
for (n = 0; n < sequence[i]->numframes; n++)
|
||||
|
@ -1230,8 +1233,8 @@ void SimplifyModel( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
sequence[i]->panim[q]->anim[j][k] = Kalloc( (pvalue - data) * sizeof( mstudioanimvalue_t ));
|
||||
memmove( sequence[i]->panim[q]->anim[j][k], data, (pvalue - data) * sizeof( mstudioanimvalue_t ));
|
||||
sequence[i]->panim[q]->anim[j][k] = Kalloc( (pvalue - data) * sizeof( dstudioanimvalue_t ));
|
||||
memmove( sequence[i]->panim[q]->anim[j][k], data, (pvalue - data) * sizeof( dstudioanimvalue_t ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ typedef struct wavefile_s
|
|||
#define BSP_ONLYRAD 0x04
|
||||
#define BSP_FULLCOMPILE 0x08
|
||||
|
||||
#define ALIGN( a ) a = (byte *)((int)((byte *)a + 3) & ~ 3)
|
||||
|
||||
extern unsigned __int64 __g_ProfilerStart;
|
||||
extern unsigned __int64 __g_ProfilerEnd;
|
||||
extern unsigned __int64 __g_ProfilerEnd2;
|
||||
|
|
|
@ -71,5 +71,5 @@ if exist vsound\vsound.plg del /f /q vsound\vsound.plg
|
|||
echo Build succeeded!
|
||||
echo Please wait. Xash is now loading
|
||||
cd D:\Xash3D\
|
||||
quake.exe -game tmpQuArK -log -debug -dev 3 +map dm7
|
||||
quake.exe -game tmpQuArK -log -debug -dev 5 +map skytest
|
||||
:done
|
|
@ -198,7 +198,7 @@ void SCR_TimeRefresh_f( void )
|
|||
if( Cmd_Argc() == 2 )
|
||||
{
|
||||
// run without page flipping
|
||||
re->BeginFrame();
|
||||
re->BeginFrame( false );
|
||||
for( i = 0; i < 128; i++ )
|
||||
{
|
||||
cl.refdef.viewangles[1] = i/128.0 * 360.0f;
|
||||
|
@ -212,7 +212,7 @@ void SCR_TimeRefresh_f( void )
|
|||
{
|
||||
cl.refdef.viewangles[1] = i/128.0 * 360.0f;
|
||||
|
||||
re->BeginFrame();
|
||||
re->BeginFrame( false );
|
||||
re->RenderFrame(&cl.refdef);
|
||||
re->EndFrame();
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ StudioEvent
|
|||
Event callback for studio models
|
||||
====================
|
||||
*/
|
||||
void CL_StudioEvent ( mstudioevent_t *event, entity_state_t *ent )
|
||||
void CL_StudioEvent ( dstudioevent_t *event, entity_state_t *ent )
|
||||
{
|
||||
// setup args
|
||||
PRVM_G_FLOAT(OFS_PARM0) = (float)event->event;
|
||||
|
|
|
@ -191,7 +191,7 @@ bool V_PreRender( void )
|
|||
// too early
|
||||
if( !re ) return false;
|
||||
|
||||
re->BeginFrame();
|
||||
re->BeginFrame( false );
|
||||
SCR_FillRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, g_color_table[0] );
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -543,7 +543,7 @@ void CL_AddLoopingSounds( void );
|
|||
cdlight_t *CL_AllocDlight (int key);
|
||||
void CL_AddParticles (void);
|
||||
void CL_ClearEffects( void );
|
||||
void CL_StudioEvent( mstudioevent_t *event, entity_state_t *ent );
|
||||
void CL_StudioEvent( dstudioevent_t *event, entity_state_t *ent );
|
||||
entity_state_t *CL_GetEdictByIndex( int index );
|
||||
entity_state_t *CL_GetLocalPlayer( void );
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ bool Cmd_CheckName( const char *name )
|
|||
{
|
||||
if(!com.stricmp(Cmd_Argv( 0 ), name ))
|
||||
return true;
|
||||
if(!com.stricmp(Cmd_Argv(0), va("\\%s", name )))
|
||||
if(!com.stricmp(Cmd_Argv( 0 ), va("\\%s", name )))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -252,9 +252,9 @@ bool Cmd_GetDemoList( const char *s, char *completedname, int length )
|
|||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetSourceList
|
||||
Cmd_GetProgsList
|
||||
|
||||
Prints or complete vm source folder name
|
||||
Prints or complete vm progs name
|
||||
=====================================
|
||||
*/
|
||||
bool Cmd_GetProgsList( const char *s, char *completedname, int length )
|
||||
|
@ -296,9 +296,9 @@ bool Cmd_GetProgsList( const char *s, char *completedname, int length )
|
|||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetProgsList
|
||||
Cmd_GetSourceList
|
||||
|
||||
Prints or complete vm progs name
|
||||
Prints or complete vm source folder name
|
||||
=====================================
|
||||
*/
|
||||
bool Cmd_GetSourceList( const char *s, char *completedname, int length )
|
||||
|
@ -621,7 +621,7 @@ bool Cmd_CheckMapsList( void )
|
|||
else if(!com.strcmp(com_token, "classname" ))
|
||||
{
|
||||
Com_ParseToken( &data, true );
|
||||
if(!com.strcmp(com_token, "info_player_deatchmatch"))
|
||||
if(!com.strcmp(com_token, "info_player_deathmatch"))
|
||||
num_spawnpoints++;
|
||||
else if(!com.strcmp(com_token, "info_player_start"))
|
||||
num_spawnpoints++;
|
||||
|
|
|
@ -237,7 +237,7 @@ void VM_EdictError( void )
|
|||
PRVM_ED_Print( ed );
|
||||
PRVM_ED_Free( ed );
|
||||
}
|
||||
else PRVM_ERROR ("VM_objecterror: pev not defined !");
|
||||
else PRVM_ERROR( "VM_objecterror: pev not defined !\n" );
|
||||
Msg("%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), s );
|
||||
}
|
||||
|
||||
|
@ -784,7 +784,7 @@ void localsound( string sample )
|
|||
*/
|
||||
void VM_localsound( void )
|
||||
{
|
||||
const char *s;
|
||||
string s;
|
||||
|
||||
if(!VM_ValidateArgs( "localsound", 1 ))
|
||||
return;
|
||||
|
@ -792,15 +792,15 @@ void VM_localsound( void )
|
|||
// OpenAL without update cause errors
|
||||
if( cls.state == ca_connecting || cls.state == ca_connected )
|
||||
return;
|
||||
s = PRVM_G_STRING( OFS_PARM0 );
|
||||
com.strncpy( s, PRVM_G_STRING( OFS_PARM0 ), MAX_STRING );
|
||||
|
||||
if(!S_StartLocalSound(s))
|
||||
if(!S_StartLocalSound( s ))
|
||||
{
|
||||
VM_Warning("localsound: can't play %s!\n", s );
|
||||
PRVM_G_FLOAT(OFS_RETURN) = 0;
|
||||
PRVM_G_FLOAT(OFS_RETURN) = false;
|
||||
return;
|
||||
}
|
||||
PRVM_G_FLOAT(OFS_RETURN) = 1;
|
||||
PRVM_G_FLOAT(OFS_RETURN) = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -886,14 +886,14 @@ void VM_NextEdict( void )
|
|||
=================
|
||||
VM_copyentity
|
||||
|
||||
void copyentity( entity src, entity dst )
|
||||
void entcpy( entity src, entity dst )
|
||||
=================
|
||||
*/
|
||||
void VM_CopyEdict( void )
|
||||
{
|
||||
edict_t *in, *out;
|
||||
|
||||
if(!VM_ValidateArgs( "copyentity", 1 ))
|
||||
if(!VM_ValidateArgs( "entcpy", 1 ))
|
||||
return;
|
||||
|
||||
in = PRVM_G_EDICT(OFS_PARM0);
|
||||
|
@ -1038,7 +1038,7 @@ void VM_FS_Close( void )
|
|||
|
||||
if(!VM_ValidateArgs( "fclose", 2 )) return;
|
||||
handle = VM_GetFileHandle((int)PRVM_G_FLOAT( OFS_PARM0 ));
|
||||
if(!handle) return;
|
||||
if( !handle ) return;
|
||||
|
||||
FS_Close(VFS_Close( handle ));
|
||||
}
|
||||
|
@ -1069,7 +1069,7 @@ void VM_FS_Gets( void )
|
|||
=========
|
||||
VM_FS_Puts
|
||||
|
||||
string fputs( float handle )
|
||||
void fputs( float handle, ... )
|
||||
=========
|
||||
*/
|
||||
void VM_FS_Puts( void )
|
||||
|
@ -1077,9 +1077,8 @@ void VM_FS_Puts( void )
|
|||
vfile_t *handle;
|
||||
const char *s;
|
||||
|
||||
if(!VM_ValidateArgs( "fputs", 1 )) return;
|
||||
handle = VM_GetFileHandle((int)PRVM_G_FLOAT( OFS_PARM0 ));
|
||||
if(!handle) return;
|
||||
if( !handle ) return;
|
||||
|
||||
s = VM_VarArgs( 1 );
|
||||
VFS_Print( handle, s );
|
||||
|
@ -1104,7 +1103,7 @@ void VM_precache_pic( void )
|
|||
return;
|
||||
|
||||
VM_ValidateString(PRVM_G_STRING(OFS_PARM0));
|
||||
if(re->PrecacheImage((char *)PRVM_G_STRING(OFS_PARM0)))
|
||||
if(re->PrecacheImage(PRVM_G_STRING( OFS_PARM0 )))
|
||||
PRVM_G_FLOAT(OFS_RETURN) = true;
|
||||
else PRVM_G_FLOAT(OFS_RETURN) = false;
|
||||
}
|
||||
|
@ -1261,7 +1260,7 @@ void VM_drawmodel( void )
|
|||
sequence = (int)PRVM_G_FLOAT(OFS_PARM5);
|
||||
|
||||
VM_ValidateString(PRVM_G_STRING(OFS_PARM2));
|
||||
memset( &ent, 0, sizeof( ent ));
|
||||
Mem_Set( &ent, 0, sizeof( ent ));
|
||||
|
||||
SCR_AdjustSize( &pos[0], &pos[1], &size[0], &size[1] );
|
||||
rect.x = pos[0]; rect.y = pos[1]; rect.width = size[0]; rect.height = size[1];
|
||||
|
@ -1616,7 +1615,7 @@ NULL, // #40 -- reserved --
|
|||
VM_SpawnEdict, // #41 entity spawn( void )
|
||||
VM_RemoveEdict, // #42 void remove( entity ent )
|
||||
VM_NextEdict, // #43 entity nextent( entity ent )
|
||||
VM_CopyEdict, // #44 void copyentity( entity src, entity dst )
|
||||
VM_CopyEdict, // #44 void entcpy( entity src, entity dst )
|
||||
NULL, // #45 -- reserved --
|
||||
NULL, // #46 -- reserved --
|
||||
NULL, // #47 -- reserved --
|
||||
|
|
|
@ -625,7 +625,7 @@ void PF_stopcredits( void )
|
|||
=========
|
||||
PF_creditsactive
|
||||
|
||||
void creditsactive( void )
|
||||
float creditsactive( void )
|
||||
=========
|
||||
*/
|
||||
void PF_creditsactive( void )
|
||||
|
|
|
@ -625,7 +625,7 @@ void _MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t
|
|||
// plus sizeof(short) (head number). If message equal null_message_size
|
||||
// we will be ignore it
|
||||
if(!force && (( msg->cursize - buff_size ) == null_msg_size ))
|
||||
msg->cursize = buff_size; // kill message
|
||||
msg->cursize = buff_size; // kill empty message
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -77,6 +77,7 @@ void Host_InitRender( void )
|
|||
ri.api_size = sizeof(render_imp_t);
|
||||
|
||||
// studio callbacks
|
||||
ri.CalcFov = V_CalcFov;
|
||||
ri.StudioEvent = CL_StudioEvent;
|
||||
ri.ShowCollision = pe->DrawCollision;
|
||||
ri.GetClientEdict = CL_GetEdictByIndex;
|
||||
|
|
|
@ -31,15 +31,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define MAX_ENT_CLUSTERS 16
|
||||
#define DF_NO_FRIENDLY_FIRE 0x00000001 //FIXME: move to server.dat
|
||||
|
||||
// content masks
|
||||
#define MASK_SOLID (CONTENTS_SOLID)
|
||||
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_BODY)
|
||||
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_BODY)
|
||||
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
|
||||
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
|
||||
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
|
||||
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_CORPSE)
|
||||
|
||||
// classic quake flags
|
||||
#define SPAWNFLAG_NOT_EASY 0x00000100
|
||||
#define SPAWNFLAG_NOT_MEDIUM 0x00000200
|
||||
|
@ -382,7 +373,7 @@ float SV_AngleMod( float ideal, float current, float speed );
|
|||
//
|
||||
cmodel_t *SV_GetModelPtr( edict_t *ent );
|
||||
float *SV_GetModelVerts( sv_edict_t *ent, int *numvertices );
|
||||
int SV_StudioExtractBbox( studiohdr_t *phdr, int sequence, float *mins, float *maxs );
|
||||
int SV_StudioExtractBbox( dstudiohdr_t *phdr, int sequence, float *mins, float *maxs );
|
||||
bool SV_CreateMeshBuffer( edict_t *in, cmodel_t *out );
|
||||
|
||||
//
|
||||
|
|
|
@ -151,7 +151,7 @@ void SV_SetMassCentre( edict_t *ent )
|
|||
pe->SetMassCentre( ent->priv.sv->physbody, ent->progs.sv->m_pcentre );
|
||||
}
|
||||
|
||||
void SV_SetModel (edict_t *ent, const char *name)
|
||||
void SV_SetModel( edict_t *ent, const char *name )
|
||||
{
|
||||
int i;
|
||||
cmodel_t *mod;
|
||||
|
@ -170,6 +170,7 @@ void SV_SetModel (edict_t *ent, const char *name)
|
|||
angles[1] = ent->progs.sv->angles[1];
|
||||
angles[2] = ent->progs.sv->angles[2] + 90.0f;
|
||||
|
||||
// FIXME: replace with Matrix3x3_FromAngles
|
||||
AngleVectors( angles, ent->progs.sv->m_pmatrix[0], ent->progs.sv->m_pmatrix[1], ent->progs.sv->m_pmatrix[2] );
|
||||
VectorCopy( ent->progs.sv->origin, ent->progs.sv->m_pmatrix[3] );
|
||||
ConvertPositionToPhysic( ent->progs.sv->m_pmatrix[3] );
|
||||
|
@ -469,6 +470,7 @@ void Sav_LoadLocals( wfile_t *l )
|
|||
PRVM_ED_Read( s_table, entnum, fields, numpairs );
|
||||
entnum++;
|
||||
}
|
||||
VFS_Close( h );
|
||||
prog->num_edicts = entnum;
|
||||
}
|
||||
|
||||
|
@ -1603,8 +1605,8 @@ float LookupActivity( string model, float activity )
|
|||
void PF_lookupactivity( void )
|
||||
{
|
||||
cmodel_t *mod;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
studiohdr_t *pstudiohdr;
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
dstudiohdr_t *pstudiohdr;
|
||||
int i, seq = -1;
|
||||
int activity, weighttotal = 0;
|
||||
|
||||
|
@ -1614,10 +1616,10 @@ void PF_lookupactivity( void )
|
|||
|
||||
mod = pe->RegisterModel(PRVM_G_STRING(OFS_PARM0));
|
||||
if( !mod ) return;
|
||||
pstudiohdr = (studiohdr_t *)mod->extradata;
|
||||
pstudiohdr = (dstudiohdr_t *)mod->extradata;
|
||||
if( !pstudiohdr ) return;
|
||||
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
|
||||
activity = (int)PRVM_G_FLOAT(OFS_PARM1);
|
||||
|
||||
for( i = 0; i < pstudiohdr->numseq; i++)
|
||||
|
@ -1642,7 +1644,7 @@ vector GetEyePosition( string model )
|
|||
void PF_geteyepos( void )
|
||||
{
|
||||
cmodel_t *mod;
|
||||
studiohdr_t *pstudiohdr;
|
||||
dstudiohdr_t *pstudiohdr;
|
||||
|
||||
if(!VM_ValidateArgs( "GetEyePosition", 1 )) return;
|
||||
VM_ValidateString(PRVM_G_STRING(OFS_PARM0));
|
||||
|
@ -1650,7 +1652,7 @@ void PF_geteyepos( void )
|
|||
|
||||
mod = pe->RegisterModel(PRVM_G_STRING(OFS_PARM0));
|
||||
if( !mod ) return;
|
||||
pstudiohdr = (studiohdr_t *)mod->extradata;
|
||||
pstudiohdr = (dstudiohdr_t *)mod->extradata;
|
||||
if( !pstudiohdr ) return;
|
||||
|
||||
VectorCopy( pstudiohdr->eyeposition, PRVM_G_VECTOR(OFS_RETURN));
|
||||
|
@ -1666,8 +1668,8 @@ float LookupSequence( string model, string label )
|
|||
void PF_lookupsequence( void )
|
||||
{
|
||||
cmodel_t *mod;
|
||||
studiohdr_t *pstudiohdr;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
dstudiohdr_t *pstudiohdr;
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
int i;
|
||||
|
||||
if(!VM_ValidateArgs( "LookupSequence", 2 )) return;
|
||||
|
@ -1677,10 +1679,10 @@ void PF_lookupsequence( void )
|
|||
|
||||
mod = pe->RegisterModel(PRVM_G_STRING(OFS_PARM0));
|
||||
if( !mod ) return;
|
||||
pstudiohdr = (studiohdr_t *)mod->extradata;
|
||||
pstudiohdr = (dstudiohdr_t *)mod->extradata;
|
||||
if( !pstudiohdr ) return;
|
||||
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
|
||||
for( i = 0; i < pstudiohdr->numseq; i++ )
|
||||
{
|
||||
if(!com.stricmp( pseqdesc[i].label, PRVM_G_STRING(OFS_PARM1)))
|
||||
|
@ -1702,8 +1704,8 @@ void PF_getsequenceinfo( void )
|
|||
{
|
||||
cmodel_t *mod;
|
||||
edict_t *ent;
|
||||
studiohdr_t *pstudiohdr;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
dstudiohdr_t *pstudiohdr;
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
int sequence;
|
||||
|
||||
if(!VM_ValidateArgs( "GetSequenceInfo", 2 )) return;
|
||||
|
@ -1714,7 +1716,7 @@ void PF_getsequenceinfo( void )
|
|||
ent = PRVM_PROG_TO_EDICT( prog->globals.sv->pev );
|
||||
mod = pe->RegisterModel(PRVM_G_STRING(OFS_PARM0));
|
||||
if( !mod ) return;
|
||||
pstudiohdr = (studiohdr_t *)mod->extradata;
|
||||
pstudiohdr = (dstudiohdr_t *)mod->extradata;
|
||||
if( !pstudiohdr ) return;
|
||||
|
||||
if( sequence >= pstudiohdr->numseq )
|
||||
|
@ -1724,7 +1726,7 @@ void PF_getsequenceinfo( void )
|
|||
return;
|
||||
}
|
||||
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
|
||||
if( pseqdesc->numframes > 1 )
|
||||
{
|
||||
ent->progs.sv->m_flFrameRate = 256.0 * (pseqdesc->fps / (pseqdesc->numframes - 1));
|
||||
|
@ -1750,8 +1752,8 @@ void PF_getsequenceflags( void )
|
|||
{
|
||||
cmodel_t *mod;
|
||||
edict_t *ent;
|
||||
studiohdr_t *pstudiohdr;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
dstudiohdr_t *pstudiohdr;
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
int sequence;
|
||||
|
||||
if(!VM_ValidateArgs( "GetSequenceFlags", 2 )) return;
|
||||
|
@ -1762,11 +1764,11 @@ void PF_getsequenceflags( void )
|
|||
ent = PRVM_PROG_TO_EDICT( prog->globals.sv->pev );
|
||||
mod = pe->RegisterModel(PRVM_G_STRING(OFS_PARM0));
|
||||
if( !mod ) return;
|
||||
pstudiohdr = (studiohdr_t *)mod->extradata;
|
||||
pstudiohdr = (dstudiohdr_t *)mod->extradata;
|
||||
if( !pstudiohdr ) return;
|
||||
if( sequence >= pstudiohdr->numseq ) return;
|
||||
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
|
||||
PRVM_G_FLOAT(OFS_RETURN) = (float )pseqdesc->flags;
|
||||
}
|
||||
|
||||
|
|
|
@ -3114,9 +3114,9 @@ file_t *VFS_Close( vfile_t *file )
|
|||
char out[8192]; // chunk size
|
||||
z_stream strm = {file->buff, file->length, 0, out, sizeof(out), 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0 };
|
||||
|
||||
if(!file) return NULL;
|
||||
if( !file ) return NULL;
|
||||
|
||||
if(file->mode == O_WRONLY)
|
||||
if( file->mode == O_WRONLY && file->handle )
|
||||
{
|
||||
if( file->compress ) // deflate before writing
|
||||
{
|
||||
|
@ -3130,8 +3130,7 @@ file_t *VFS_Close( vfile_t *file )
|
|||
FS_Write( file->handle, out, sizeof(out) - strm.avail_out );
|
||||
deflateEnd( &strm );
|
||||
}
|
||||
else if( file->handle )
|
||||
FS_Write(file->handle, file->buff, (file->length + 3) & ~3); // align
|
||||
else FS_Write(file->handle, file->buff, (file->length + 3) & ~3); // align
|
||||
}
|
||||
handle = file->handle; // keep real handle
|
||||
|
||||
|
@ -3180,7 +3179,7 @@ static char W_TypeFromExt( const char *lumpname )
|
|||
const char *ext = FS_FileExtension( lumpname );
|
||||
wadtype_t *type;
|
||||
|
||||
// we not known aboyt filetype, so match only by filename
|
||||
// we not known about filetype, so match only by filename
|
||||
if(!com_strcmp( ext, "*" ) || !com_strcmp( ext, "" ))
|
||||
return TYPE_ANY;
|
||||
|
||||
|
@ -3196,7 +3195,7 @@ static const char *W_ExtFromType( char lumptype )
|
|||
{
|
||||
wadtype_t *type;
|
||||
|
||||
// we not known aboyt filetype, so match only by filename
|
||||
// we not known about filetype, so match only by filename
|
||||
if( lumptype == TYPE_NONE || lumptype == TYPE_ANY )
|
||||
return "";
|
||||
|
||||
|
|
|
@ -436,6 +436,7 @@ extern byte *fs_mempool;
|
|||
bool Image_AddMipmapToPack( const byte *in, int width, int height, bool expand );
|
||||
void Image_RoundDimensions( int *scaled_width, int *scaled_height );
|
||||
byte *Image_ResampleInternal( const void *indata, int inwidth, int inheight, int outwidth, int outheight, int intype );
|
||||
byte *Image_FlipInternal( const byte *in, int inwidth, int inheight, int intype, int adjust_flags );
|
||||
void Image_FreeImage( rgbdata_t *pack );
|
||||
void Image_Save( const char *filename, rgbdata_t *pix );
|
||||
rgbdata_t *Image_Load(const char *filename, const byte *buffer, size_t buffsize );
|
||||
|
|
|
@ -25,7 +25,45 @@ int cubemap_width, cubemap_height;
|
|||
int cubemap_num_sides; // how mach sides is loaded
|
||||
byte *image_cubemap; // cubemap pack
|
||||
uint base_image_type; // shared image type for all mipmaps or cubemap sides
|
||||
const char *suf[6] = { "ft", "bk", "rt", "lf", "up", "dn" };
|
||||
|
||||
typedef struct suffix_s
|
||||
{
|
||||
const char *suf;
|
||||
uint flags;
|
||||
} suffix_t;
|
||||
|
||||
typedef struct cubepack_s
|
||||
{
|
||||
const char *name; // package name
|
||||
const suffix_t *type;
|
||||
} cubepack_t;
|
||||
|
||||
static suffix_t skybox_3ds[6] =
|
||||
{
|
||||
{ "ft", IMAGE_FLIP_X },
|
||||
{ "bk", IMAGE_FLIP_Y },
|
||||
{ "rt", IMAGE_FLIP_I },
|
||||
{ "lf", IMAGE_FLIP_X|IMAGE_FLIP_Y|IMAGE_FLIP_I }, // rotate at 270°
|
||||
{ "up", IMAGE_FLIP_I },
|
||||
{ "dn", IMAGE_FLIP_I },
|
||||
};
|
||||
|
||||
static suffix_t cubemap_px[6] =
|
||||
{
|
||||
{ "px", 0 },
|
||||
{ "nx", 0 },
|
||||
{ "py", 0 },
|
||||
{ "ny", 0 },
|
||||
{ "pz", 0 },
|
||||
{ "nz", 0 },
|
||||
};
|
||||
|
||||
static cubepack_t load_cubemap[] =
|
||||
{
|
||||
{ "3D Studio", skybox_3ds },
|
||||
{ "Cubemap 1", cubemap_px },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
typedef struct loadformat_s
|
||||
{
|
||||
|
@ -180,12 +218,12 @@ rgbdata_t *ImagePack( void )
|
|||
return pack;
|
||||
}
|
||||
|
||||
bool FS_AddImageToPack( const char *name )
|
||||
bool FS_AddSideToPack( const char *name, int adjust_flags )
|
||||
{
|
||||
byte *resampled;
|
||||
byte *resampled, *flipped;
|
||||
|
||||
// first image have suffix "ft" and set average size for all cubemap sides!
|
||||
if(!image_cubemap)
|
||||
// first cubemap\skybox side set base dimenisons for all follow sides!
|
||||
if( !image_cubemap )
|
||||
{
|
||||
cubemap_width = image_width;
|
||||
cubemap_height = image_height;
|
||||
|
@ -194,11 +232,16 @@ bool FS_AddImageToPack( const char *name )
|
|||
image_size = cubemap_width * cubemap_height * 4; // keep constant size, render.dll expecting it
|
||||
|
||||
// mixing dds format with any existing ?
|
||||
if(image_type != base_image_type) return false;
|
||||
if( image_type != base_image_type ) return false;
|
||||
|
||||
// flip image if needed
|
||||
flipped = Image_FlipInternal( image_rgba, image_width, image_height, base_image_type, adjust_flags );
|
||||
if( !flipped ) return false; // try to reasmple dxt?
|
||||
if( flipped != image_rgba ) Mem_Move( Sys.imagepool, &image_rgba, flipped, image_size ); // update buffer
|
||||
|
||||
// resampling image if needed
|
||||
resampled = Image_ResampleInternal((uint *)image_rgba, image_width, image_height, cubemap_width, cubemap_height, base_image_type );
|
||||
if(!resampled) return false; // try to reasmple dxt?
|
||||
if( !resampled ) return false; // try to reasmple dxt?
|
||||
if( resampled != image_rgba ) Mem_Move( Sys.imagepool, &image_rgba, resampled, image_size ); // update buffer
|
||||
|
||||
image_cubemap = Mem_Realloc( Sys.imagepool, image_cubemap, image_ptr + image_size );
|
||||
|
@ -236,7 +279,7 @@ bool FS_AddMipmapToPack( const byte *in, int width, int height, bool expand )
|
|||
return true;
|
||||
}
|
||||
|
||||
void Image_ConvertToRGBA( rgbdata_t *pic )
|
||||
static void Image_ConvertTo( int outformat, rgbdata_t *pic )
|
||||
{
|
||||
int j, texels;
|
||||
byte *in, *out, *buffer;
|
||||
|
@ -252,11 +295,28 @@ void Image_ConvertToRGBA( rgbdata_t *pic )
|
|||
MsgDev( D_ERROR, "Image_ConvertToRGBA: indexed image doesn't have palette\n" );
|
||||
return;
|
||||
}
|
||||
if( pic->type == PF_RGBA_32 || pic->type == PF_ABGR_64 )
|
||||
return; // nothing to process
|
||||
|
||||
switch( outformat )
|
||||
{
|
||||
case PF_RGBA_32:
|
||||
switch( pic->type )
|
||||
{
|
||||
case PF_RGBA_32:
|
||||
case PF_ABGR_64:
|
||||
return; // nothing to process
|
||||
default: break;
|
||||
}
|
||||
case PF_RGB_24:
|
||||
switch( pic->type )
|
||||
{
|
||||
case PF_RGB_24:
|
||||
return; // nothing to porcess
|
||||
default: break;
|
||||
}
|
||||
default: return; // unsupported mode
|
||||
}
|
||||
|
||||
texels = pic->width * pic->height;
|
||||
buffer = Mem_Alloc( Sys.imagepool, texels * 4 );
|
||||
buffer = Mem_Alloc( Sys.imagepool, texels * PFDesc[outformat].bpp );
|
||||
in = pic->buffer;
|
||||
out = buffer;
|
||||
|
||||
|
@ -266,9 +326,21 @@ void Image_ConvertToRGBA( rgbdata_t *pic )
|
|||
case PF_DXT3:
|
||||
case PF_DXT5:
|
||||
result = Image_DecompressDXTC( &pic );
|
||||
in = pic->buffer;
|
||||
switch( outformat )
|
||||
{
|
||||
case PF_RGB_24: // RGBA_32 to RGB_24
|
||||
for( j = 0; j < texels; j++, in += 4, out += 3 )
|
||||
{
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
}
|
||||
break;
|
||||
case PF_RGBA_32: break;
|
||||
}
|
||||
break;
|
||||
case PF_RGB_24:
|
||||
//
|
||||
case PF_RGB_24: // RGB_24 to RGBA_32
|
||||
for( j = 0; j < texels; j++, in += 3, out += 4 )
|
||||
{
|
||||
out[0] = in[0];
|
||||
|
@ -278,31 +350,67 @@ void Image_ConvertToRGBA( rgbdata_t *pic )
|
|||
}
|
||||
result = true;
|
||||
break;
|
||||
case PF_RGBA_32: // RGBA_32 to RGB_24
|
||||
for( j = 0; j < texels; j++, in += 4, out += 3 )
|
||||
{
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
case PF_INDEXED_24:
|
||||
// FIXME: make flag IMAGE_HAS_INDEXALPHA for decals ?
|
||||
if( pic->flags & IMAGE_HAS_ALPHA )
|
||||
Image_GetPaletteLMP( pic->palette, LUMP_TRANSPARENT );
|
||||
{
|
||||
if( pic->flags & IMAGE_COLORINDEX )
|
||||
Image_GetPaletteLMP( pic->palette, LUMP_DECAL );
|
||||
else Image_GetPaletteLMP( pic->palette, LUMP_TRANSPARENT );
|
||||
}
|
||||
else Image_GetPaletteLMP( pic->palette, LUMP_NORMAL );
|
||||
// intentional falltrough
|
||||
case PF_INDEXED_32:
|
||||
d_currentpal = ( uint *)pic->palette;
|
||||
result = Image_Copy8bitRGBA( pic->buffer, buffer, texels );
|
||||
in = pic->buffer;
|
||||
switch( outformat )
|
||||
{
|
||||
case PF_RGB_24: // RGBA_32 to RGB_24
|
||||
for( j = 0; j < texels; j++, in += 4, out += 3 )
|
||||
{
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
}
|
||||
break;
|
||||
case PF_RGBA_32: break;
|
||||
}
|
||||
break;
|
||||
default: break; // unsupported format
|
||||
}
|
||||
|
||||
if( result )
|
||||
{
|
||||
MsgDev( D_NOTE, "Image_ConvertToRGBA: from %s to RGBA 32\n", PFDesc[pic->type].name );
|
||||
pic->type = PF_RGBA_32; // sucessfully converted
|
||||
MsgDev( D_NOTE, "Image_ConvertTo%s: from %s\n", PFDesc[outformat].name, PFDesc[pic->type].name );
|
||||
pic->type = outformat; // sucessfully converted
|
||||
pic->size = texels * PFDesc[outformat].bpp; // merge size
|
||||
Mem_Free( pic->buffer );
|
||||
pic->buffer = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
MsgDev( D_WARN, "Image_ConvertToRGBA: can't convert from %s to RGBA 32\n", PFDesc[pic->type].name );
|
||||
MsgDev( D_WARN, "Image_ConvertTo%s: can't convert from %s\n", PFDesc[outformat].name, PFDesc[pic->type].name );
|
||||
Mem_Free( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
void Image_ConvertToRGB( rgbdata_t *pic )
|
||||
{
|
||||
Image_ConvertTo( PF_RGB_24, pic );
|
||||
}
|
||||
|
||||
void Image_ConvertToRGBA( rgbdata_t *pic )
|
||||
{
|
||||
Image_ConvertTo( PF_RGBA_32, pic );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -315,10 +423,11 @@ loading and unpack to rgba any known image
|
|||
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t buffsize )
|
||||
{
|
||||
const char *ext = FS_FileExtension( filename );
|
||||
char path[128], loadname[128], texname[128];
|
||||
string path, loadname, texname, sidename;
|
||||
loadformat_t *format, *desired_formats = load_formats0;
|
||||
bool anyformat = !com_stricmp(ext, "") ? true : false;
|
||||
int i, filesize = 0;
|
||||
cubepack_t *cubemap;
|
||||
byte *f;
|
||||
|
||||
#if 0 // don't try to be very clever
|
||||
|
@ -331,11 +440,11 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t buffsi
|
|||
case HOST_VIEWER:
|
||||
switch( img_oldformats->integer )
|
||||
{
|
||||
case 0: desired_formats = load_formats0; break; // tga, dds
|
||||
case 0: desired_formats = load_formats0; break; // tga, dds, png
|
||||
case 1: desired_formats = load_formats1; break; // tga, dds, jpg, png, mip
|
||||
case 2: desired_formats = load_formats2; break; // tga, dds, jpg, png, mip, bmp, pcx, wal, lmp
|
||||
case 3: desired_formats = load_formats3; break; // tga, dds, jpg, png, mip, bmp, pcx, wal, lmp, flat, pal
|
||||
default: desired_formats = load_formats0; break; // tga, dds
|
||||
default: desired_formats = load_formats0; break; // tga, dds, png
|
||||
}
|
||||
break;
|
||||
case HOST_SPRITE:
|
||||
|
@ -366,7 +475,7 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t buffsi
|
|||
if(!anyformat) MsgDev(D_NOTE, "Note: %s will be loading only with ext .%s\n", loadname, ext );
|
||||
|
||||
// now try all the formats in the selected list
|
||||
for( format = desired_formats; format && format->formatstring; format++)
|
||||
for( format = desired_formats; format && format->formatstring; format++ )
|
||||
{
|
||||
if( anyformat || !com_stricmp(ext, format->ext ))
|
||||
{
|
||||
|
@ -376,49 +485,66 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t buffsi
|
|||
{
|
||||
// this name will be used only for tell user about problems
|
||||
FS_FileBase( path, texname );
|
||||
if( format->loadfunc(texname, f, filesize ))
|
||||
if( format->loadfunc( texname, f, filesize ))
|
||||
{
|
||||
Mem_Free(f); // release buffer
|
||||
Mem_Free( f ); // release buffer
|
||||
return ImagePack(); // loaded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// maybe it skybox or cubemap ?
|
||||
for( i = 0; i < 6; i++ )
|
||||
// check all cubemap sides with package suffix
|
||||
for( cubemap = load_cubemap; cubemap && cubemap->type; cubemap++ )
|
||||
{
|
||||
for( format = desired_formats; format && format->formatstring; format++ )
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( anyformat || !com_stricmp(ext, format->ext ))
|
||||
// for support mixed cubemaps e.g. sky_ft.jpg, sky_rt.tga, sky_bk.png
|
||||
// NOTE: all loaders must keep sides in one format for all sides
|
||||
for( format = desired_formats; format && format->formatstring; format++ )
|
||||
{
|
||||
com_sprintf( path, format->formatstring, loadname, suf[i], format->ext );
|
||||
f = FS_LoadFile( path, &filesize );
|
||||
if(f && filesize > 0)
|
||||
if( anyformat || !com_stricmp(ext, format->ext ))
|
||||
{
|
||||
// this name will be used only for tell user about problems
|
||||
FS_FileBase( path, texname );
|
||||
if( format->loadfunc(texname, f, filesize ))
|
||||
com_sprintf( path, format->formatstring, loadname, cubemap->type[i].suf, format->ext );
|
||||
f = FS_LoadFile( path, &filesize );
|
||||
if( f && filesize > 0 )
|
||||
{
|
||||
if(FS_AddImageToPack(va("%s%s.%s", loadname, suf[i], format->ext)))
|
||||
break; // loaded
|
||||
// this name will be used only for tell user about problems
|
||||
FS_FileBase( path, texname );
|
||||
if( format->loadfunc( texname, f, filesize ))
|
||||
{
|
||||
com_snprintf( sidename, MAX_STRING, "%s%s.%s", loadname, cubemap->type[i].suf, format->ext );
|
||||
if( FS_AddSideToPack( sidename, cubemap->type[i].flags )) // process flags to flip some sides
|
||||
break; // loaded
|
||||
}
|
||||
Mem_Free( f );
|
||||
}
|
||||
Mem_Free(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( cubemap_num_sides != i + 1 ) // check side
|
||||
{
|
||||
// first side not found, probably it's not cubemap
|
||||
// it contain info about image_type and dimensions, don't generate black cubemaps
|
||||
if(!image_cubemap) break;
|
||||
MsgDev(D_ERROR, "FS_LoadImage: couldn't load (%s%s.%s), create black image\n",loadname,suf[i],ext );
|
||||
|
||||
// Mem_Alloc already filled memblock with 0x00, no need to do it again
|
||||
image_cubemap = Mem_Realloc( Sys.imagepool, image_cubemap, image_ptr + image_size );
|
||||
image_ptr += image_size; // move to next
|
||||
cubemap_num_sides++; // merge counter
|
||||
if( cubemap_num_sides != i + 1 ) // check side
|
||||
{
|
||||
// first side not found, probably it's not cubemap
|
||||
// it contain info about image_type and dimensions, don't generate black cubemaps
|
||||
if( !image_cubemap ) break;
|
||||
MsgDev(D_ERROR, "FS_LoadImage: couldn't load (%s%s.%s), create black image\n", loadname, cubemap->type[i].suf );
|
||||
|
||||
// Mem_Alloc already filled memblock with 0x00, no need to do it again
|
||||
image_cubemap = Mem_Realloc( Sys.imagepool, image_cubemap, image_ptr + image_size );
|
||||
image_ptr += image_size; // move to next
|
||||
cubemap_num_sides++; // merge counter
|
||||
}
|
||||
}
|
||||
|
||||
// make sure what all sides is loaded
|
||||
if( cubemap_num_sides != 6 )
|
||||
{
|
||||
// unexpected errors ?
|
||||
if( image_cubemap )
|
||||
Mem_Free( image_cubemap );
|
||||
Image_Reset();
|
||||
}
|
||||
else break; // all done
|
||||
}
|
||||
|
||||
if( image_cubemap ) return ImagePack(); // now it's cubemap pack
|
||||
|
|
|
@ -135,10 +135,11 @@ bool Image_ValidSize( const char *name )
|
|||
|
||||
bool Image_LumpValidSize( const char *name )
|
||||
{
|
||||
if( image_width > 640 || image_height > 640 || image_width <= 0 || image_height <= 0 )
|
||||
// WorldCraft limitation
|
||||
if( image_width > 1024 || image_height > 1024 || image_width <= 0 || image_height <= 0 )
|
||||
{
|
||||
if(!com_stristr( name, "#internal" )) // internal errors are silent
|
||||
MsgDev(D_WARN, "Image_LumpValidSize: (%s) dims out of range[%dx%d]\n", name, image_width,image_height );
|
||||
MsgDev( D_WARN, "Image_LumpValidSize: (%s) dims out of range[%dx%d]\n", name, image_width, image_height );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -816,7 +817,8 @@ bool Image_Resample( rgbdata_t **image, int width, int height, bool free_baseima
|
|||
|
||||
// if image was resampled
|
||||
MsgDev( D_NOTE, "Resample image from[%d x %d] to [%d x %d]\n", pix->width, pix->height, w, h );
|
||||
if( free_baseimage ) Mem_Free( pix->buffer ); // free original image buffer
|
||||
// render dump screenshots into static buffer, so we never release it here
|
||||
if( free_baseimage ) Mem_Free( pix->buffer );
|
||||
|
||||
// change image params
|
||||
pix->buffer = out;
|
||||
|
@ -829,55 +831,70 @@ bool Image_Resample( rgbdata_t **image, int width, int height, bool free_baseima
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Image_Process( rgbdata_t **pix, int adjust_type, bool free_baseimage )
|
||||
/*
|
||||
================
|
||||
R_FlipTexture
|
||||
================
|
||||
*/
|
||||
byte *Image_FlipInternal( const byte *in, int width, int height, int type, int adjust_flags )
|
||||
{
|
||||
int w, h, x, y, c, bpp;
|
||||
rgbdata_t *pic = *pix;
|
||||
byte *fout, *fin;
|
||||
uint line;
|
||||
|
||||
// check for buffers
|
||||
if(!pic || !pic->buffer) return false;
|
||||
int i, x, y;
|
||||
int samples = PFDesc[type].bpp;
|
||||
bool flip_x = ( adjust_flags & IMAGE_FLIP_X ) ? true : false;
|
||||
bool flip_y = ( adjust_flags & IMAGE_FLIP_Y ) ? true : false;
|
||||
bool flip_i = ( adjust_flags & IMAGE_FLIP_I ) ? true : false;
|
||||
int row_inc = ( flip_y ? -samples : samples ) * width;
|
||||
int col_inc = ( flip_x ? -samples : samples );
|
||||
int row_ofs = ( flip_y ? ( height - 1 ) * width * samples : 0 );
|
||||
int col_ofs = ( flip_x ? ( width - 1 ) * samples : 0 );
|
||||
const byte *p, *line;
|
||||
byte *out;
|
||||
|
||||
// check for support formats
|
||||
switch( pic->type )
|
||||
// nothing to process
|
||||
if( !adjust_flags ) return (byte *)in;
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case PF_INDEXED_24:
|
||||
case PF_INDEXED_32:
|
||||
case PF_RGB_24:
|
||||
case PF_RGBA_32:
|
||||
out = Mem_Alloc( Sys.imagepool, width * height * samples );
|
||||
break;
|
||||
default:
|
||||
MsgDev(D_ERROR, "Image_Process: can't processing format %s\n", PFDesc[pic->type].name );
|
||||
return false;
|
||||
MsgDev( D_WARN, "Image_Flip: unsupported format %s\n", PFDesc[type].name );
|
||||
return (byte *)in;
|
||||
}
|
||||
|
||||
bpp = PFDesc[pic->type].bpp;
|
||||
w = pic->width;
|
||||
h = pic->height;
|
||||
line = pic->width * bpp;
|
||||
fin = pic->buffer;
|
||||
fout = Mem_Alloc( Sys.imagepool, w * h * bpp );
|
||||
|
||||
switch( adjust_type )
|
||||
if( flip_i )
|
||||
{
|
||||
case IMAGE_FLIP_X:
|
||||
for( y = 0; y < h; y++ )
|
||||
for( x = w - 1; x >= 0; x-- )
|
||||
for( c = 0; c < bpp; c++, fin++ )
|
||||
fout[y*line+x*bpp+c] = *fin;
|
||||
break;
|
||||
case IMAGE_FLIP_Y:
|
||||
for( y = h - 1; y >= 0; y-- )
|
||||
for( x = 0; x < w; x++ )
|
||||
for( c = 0; c < bpp; c++, fin++ )
|
||||
fout[y*line+x*bpp+c] = *fin;
|
||||
break;
|
||||
default:
|
||||
MsgDev(D_ERROR, "Image_Process: unknown transformation %d\n", adjust_type );
|
||||
break;
|
||||
for( x = 0, line = in + col_ofs; x < width; x++, line += col_inc )
|
||||
for( y = 0, p = line + row_ofs; y < height; y++, p += row_inc, out += samples )
|
||||
for( i = 0; i < samples; i++ )
|
||||
out[i] = p[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for( y = 0, line = in + row_ofs; y < height; y++, line += row_inc )
|
||||
for( x = 0, p = line + col_ofs; x < width; x++, p += col_inc, out += samples )
|
||||
for( i = 0; i < samples; i++ )
|
||||
out[i] = p[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Image_Process( rgbdata_t **pix, int flags, bool free_baseimage )
|
||||
{
|
||||
rgbdata_t *pic = *pix;
|
||||
byte *fout;
|
||||
|
||||
// check for buffers
|
||||
if( !pic || !pic->buffer ) return false;
|
||||
|
||||
// can flip DXT without expanding to RGBA ? hmmm...
|
||||
fout = Image_FlipInternal( pic->buffer, pic->width, pic->height, pic->type, flags );
|
||||
|
||||
// render dump screenshots into static buffer, so we never release it here
|
||||
if( free_baseimage ) Mem_Free( pic->buffer );
|
||||
pic->buffer = fout;
|
||||
*pix = pic;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "byteorder.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#define TRANS_THRESHOLD 10
|
||||
|
||||
/*
|
||||
============
|
||||
Image_LoadPAL
|
||||
|
@ -56,7 +58,7 @@ bool Image_LoadWAL( const char *name, const byte *buffer, size_t filesize )
|
|||
image_width = LittleLong(wal.width);
|
||||
image_height = LittleLong(wal.height);
|
||||
for(i = 0; i < 4; i++) ofs[i] = LittleLong(wal.offsets[i]);
|
||||
if(!Image_ValidSize( name )) return false;
|
||||
if(!Image_LumpValidSize( name )) return false;
|
||||
|
||||
pixels = image_width * image_height;
|
||||
mipsize = (int)sizeof(wal) + ofs[0] + pixels;
|
||||
|
@ -152,7 +154,7 @@ bool Image_LoadFLT( const char *name, const byte *buffer, size_t filesize )
|
|||
|
||||
// yes it's really transparent texture
|
||||
// otherwise transparency it's product of lazy designers (or painters ?)
|
||||
if( trans_threshold > 10 ) image_flags |= IMAGE_HAS_ALPHA;
|
||||
if( trans_threshold > TRANS_THRESHOLD ) image_flags |= IMAGE_HAS_ALPHA;
|
||||
|
||||
image_type = PF_INDEXED_32; // scaled up to 32-bit
|
||||
Image_GetPaletteD1();
|
||||
|
@ -208,7 +210,7 @@ bool Image_LoadLMP( const char *name, const byte *buffer, size_t filesize )
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!Image_ValidSize( name )) return false;
|
||||
if(!Image_LumpValidSize( name )) return false;
|
||||
image_num_mips = 1;
|
||||
image_num_layers = 1;
|
||||
|
||||
|
@ -281,7 +283,11 @@ bool Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
|
|||
// qlumpy used this color for transparent textures, otherwise it's decals
|
||||
if(pal[255*3+0] == 0 && pal[255*3+1] == 0 && pal[255*3+2] == 255)
|
||||
rendermode = LUMP_TRANSPARENT;
|
||||
else rendermode = LUMP_DECAL;
|
||||
else
|
||||
{
|
||||
rendermode = LUMP_DECAL;
|
||||
image_flags |= IMAGE_COLORINDEX;
|
||||
}
|
||||
image_flags |= IMAGE_HAS_ALPHA;
|
||||
}
|
||||
else rendermode = LUMP_NORMAL;
|
||||
|
@ -299,7 +305,7 @@ bool Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!Image_ValidSize( name )) return false;
|
||||
if(!Image_LumpValidSize( name )) return false;
|
||||
Image_GetPaletteLMP( pal, rendermode );
|
||||
image_type = PF_INDEXED_32; // scaled up to 32 bit
|
||||
return FS_AddMipmapToPack( fin, image_width, image_height, false );
|
||||
|
|
|
@ -312,6 +312,7 @@ bool FS_WriteFile (const char *filename, const void *data, fs_offset_t len);
|
|||
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t buffsize );
|
||||
void FS_SaveImage( const char *filename, rgbdata_t *pix );
|
||||
void FS_FreeImage( rgbdata_t *pack );
|
||||
void Image_ConvertToRGB( rgbdata_t *pic );
|
||||
void Image_ConvertToRGBA( rgbdata_t *pic );
|
||||
bool Image_Resample( rgbdata_t **image, int width, int height, bool free_baseimage );
|
||||
bool Image_Process( rgbdata_t **pix, int adjust_type, bool free_baseimage );
|
||||
|
|
|
@ -223,8 +223,8 @@ outta:
|
|||
|
||||
void _mem_set( void *dest, int set, size_t size, const char *filename, int fileline )
|
||||
{
|
||||
// FIXME: implement
|
||||
Sys_Error("_mem_set: not implemented (called at %s:%i)\n", filename, fileline );
|
||||
if( dest == NULL ) Sys_Error("Mem_Set: dest == NULL (called at %s:%i)\n", filename, fileline );
|
||||
memset( dest, set, size );
|
||||
}
|
||||
|
||||
void *_mem_alloc( byte *poolptr, size_t size, const char *filename, int fileline )
|
||||
|
|
|
@ -196,6 +196,7 @@ void Sys_GetStdAPI( void )
|
|||
com.FreeImage = FS_FreeImage; // free image buffer
|
||||
|
||||
// image manipulation
|
||||
com.ImageToRGB = Image_ConvertToRGB; // expand any image to PF_RGB_24
|
||||
com.ImageToRGBA = Image_ConvertToRGBA; // expand any image to PF_RGBA_32
|
||||
com.ImagePal32to24 = Image_ConvertPalTo24bit; // convert palette from 32 to 24 bit
|
||||
com.ResampleImage = Image_Resample; // resample image
|
||||
|
|
|
@ -208,9 +208,9 @@ typedef struct physic_s
|
|||
|
||||
typedef struct studio_s
|
||||
{
|
||||
studiohdr_t *hdr;
|
||||
mstudiomodel_t *submodel;
|
||||
mstudiobodyparts_t *bodypart;
|
||||
dstudiohdr_t *hdr;
|
||||
dstudiomodel_t *submodel;
|
||||
dstudiobodyparts_t *bodypart;
|
||||
matrix4x4 rotmatrix;
|
||||
matrix4x4 bones[MAXSTUDIOBONES];
|
||||
vec3_t vertices[MAXSTUDIOVERTS];
|
||||
|
|
|
@ -60,7 +60,7 @@ bool CM_ParseMaterial( void )
|
|||
|
||||
cm.num_materials++;
|
||||
|
||||
// material will be parsed sucessfully
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -955,10 +955,10 @@ STUDIO SHARED CMODELS
|
|||
|
||||
===============================================================================
|
||||
*/
|
||||
int CM_StudioExtractBbox( studiohdr_t *phdr, int sequence, float *mins, float *maxs )
|
||||
int CM_StudioExtractBbox( dstudiohdr_t *phdr, int sequence, float *mins, float *maxs )
|
||||
{
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
|
||||
|
||||
if(sequence == -1) return 0;
|
||||
VectorCopy( pseqdesc[sequence].bbmin, mins );
|
||||
|
@ -971,7 +971,7 @@ void CM_GetBodyCount( void )
|
|||
{
|
||||
if(studio.hdr)
|
||||
{
|
||||
studio.bodypart = (mstudiobodyparts_t *)((byte *)studio.hdr + studio.hdr->bodypartindex);
|
||||
studio.bodypart = (dstudiobodyparts_t *)((byte *)studio.hdr + studio.hdr->bodypartindex);
|
||||
studio.bodycount = studio.bodypart->nummodels;
|
||||
}
|
||||
else studio.bodycount = 0; // just reset it
|
||||
|
@ -982,7 +982,7 @@ void CM_GetBodyCount( void )
|
|||
CM_StudioCalcBoneQuaterion
|
||||
====================
|
||||
*/
|
||||
void CM_StudioCalcBoneQuaterion( mstudiobone_t *pbone, float *q )
|
||||
void CM_StudioCalcBoneQuaterion( dstudiobone_t *pbone, float *q )
|
||||
{
|
||||
int i;
|
||||
vec3_t angle1;
|
||||
|
@ -996,7 +996,7 @@ void CM_StudioCalcBoneQuaterion( mstudiobone_t *pbone, float *q )
|
|||
CM_StudioCalcBonePosition
|
||||
====================
|
||||
*/
|
||||
void CM_StudioCalcBonePosition( mstudiobone_t *pbone, float *pos )
|
||||
void CM_StudioCalcBonePosition( dstudiobone_t *pbone, float *pos )
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 3; i++) pos[i] = pbone->value[i];
|
||||
|
@ -1028,7 +1028,7 @@ void CM_StudioSetUpTransform ( void )
|
|||
|
||||
void CM_StudioCalcRotations ( float pos[][3], vec4_t *q )
|
||||
{
|
||||
mstudiobone_t *pbone = (mstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
|
||||
dstudiobone_t *pbone = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < studio.hdr->numbones; i++, pbone++ )
|
||||
|
@ -1046,13 +1046,13 @@ CM_StudioSetupBones
|
|||
void CM_StudioSetupBones( void )
|
||||
{
|
||||
int i;
|
||||
mstudiobone_t *pbones;
|
||||
dstudiobone_t *pbones;
|
||||
static float pos[MAXSTUDIOBONES][3];
|
||||
static vec4_t q[MAXSTUDIOBONES];
|
||||
matrix4x4 bonematrix;
|
||||
|
||||
CM_StudioCalcRotations( pos, q );
|
||||
pbones = (mstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
|
||||
pbones = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
|
||||
|
||||
for (i = 0; i < studio.hdr->numbones; i++)
|
||||
{
|
||||
|
@ -1067,16 +1067,16 @@ void CM_StudioSetupModel ( int bodypart, int body )
|
|||
int index;
|
||||
|
||||
if(bodypart > studio.hdr->numbodyparts) bodypart = 0;
|
||||
studio.bodypart = (mstudiobodyparts_t *)((byte *)studio.hdr + studio.hdr->bodypartindex) + bodypart;
|
||||
studio.bodypart = (dstudiobodyparts_t *)((byte *)studio.hdr + studio.hdr->bodypartindex) + bodypart;
|
||||
|
||||
index = body / studio.bodypart->base;
|
||||
index = index % studio.bodypart->nummodels;
|
||||
studio.submodel = (mstudiomodel_t *)((byte *)studio.hdr + studio.bodypart->modelindex) + index;
|
||||
studio.submodel = (dstudiomodel_t *)((byte *)studio.hdr + studio.bodypart->modelindex) + index;
|
||||
}
|
||||
|
||||
void CM_StudioAddMesh( int mesh )
|
||||
{
|
||||
mstudiomesh_t *pmesh = (mstudiomesh_t *)((byte *)studio.hdr + studio.submodel->meshindex) + mesh;
|
||||
dstudiomesh_t *pmesh = (dstudiomesh_t *)((byte *)studio.hdr + studio.submodel->meshindex) + mesh;
|
||||
short *ptricmds = (short *)((byte *)studio.hdr + pmesh->triindex);
|
||||
int i;
|
||||
|
||||
|
@ -1130,7 +1130,7 @@ void CM_CreateMeshBuffer( byte *buffer )
|
|||
int i, j;
|
||||
|
||||
// setup global pointers
|
||||
studio.hdr = (studiohdr_t *)buffer;
|
||||
studio.hdr = (dstudiohdr_t *)buffer;
|
||||
studio.m_pVerts = &studio.vertices[0];
|
||||
|
||||
CM_GetBodyCount();
|
||||
|
@ -1163,10 +1163,10 @@ void CM_CreateMeshBuffer( byte *buffer )
|
|||
|
||||
bool CM_StudioModel( byte *buffer, uint filesize )
|
||||
{
|
||||
studiohdr_t *phdr;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
dstudiohdr_t *phdr;
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
|
||||
phdr = (studiohdr_t *)buffer;
|
||||
phdr = (dstudiohdr_t *)buffer;
|
||||
if( phdr->version != STUDIO_VERSION )
|
||||
{
|
||||
MsgDev( D_ERROR, "CM_StudioModel: %s has wrong version number (%i should be %i)", phdr->name, phdr->version, STUDIO_VERSION);
|
||||
|
@ -1179,7 +1179,7 @@ bool CM_StudioModel( byte *buffer, uint filesize )
|
|||
Mem_Copy( loadmodel->extradata, buffer, filesize );
|
||||
|
||||
// calcualte bounding box
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
|
||||
VectorCopy( pseqdesc[0].bbmin, loadmodel->mins );
|
||||
VectorCopy( pseqdesc[0].bbmax, loadmodel->maxs );
|
||||
loadmodel->numframes = pseqdesc[0].numframes; // FIXME: get numframes from current sequence (not first)
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#define MAX_STRING 256
|
||||
#define MAX_SYSPATH 1024
|
||||
#define MAX_MSGLEN 32768 // max length of network message
|
||||
#define ALIGN __declspec( align( 16 ))
|
||||
#define EQUAL_EPSILON 0.001f
|
||||
|
||||
typedef enum{ false, true } bool;
|
||||
typedef unsigned char byte;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define TYPE_QPIC 66 // quake1 and hl pic (lmp_t)
|
||||
#define TYPE_MIPTEX2 67 // half-life (mip_t) previous was TYP_SOUND but never used in quake1
|
||||
#define TYPE_MIPTEX 68 // quake1 (mip_t)
|
||||
#define TYPE_BINDATA 69 // engine internal data
|
||||
#define TYPE_BINDATA 69 // engine internal data (map lumps, save lumps etc)
|
||||
#define TYPE_STRDATA 70 // big unterminated string (stringtable marked as TYPE_BINARYDATA)
|
||||
|
||||
#define TYPE_RAW 71 // unrecognized raw data
|
||||
|
@ -34,7 +34,21 @@
|
|||
#define RF_DEPTHHACK (1<<4) // for view weapon Z crunching
|
||||
#define RF_TRANSLUCENT (1<<5)
|
||||
#define RF_IR_VISIBLE (1<<6) // skin is an index in image_precache
|
||||
#define RF_HOLOGRAMM (1<<7)
|
||||
#define RF_HOLOGRAMM (1<<7) // studio hologramm effect (like hl1)
|
||||
#define RF_OCCLUSIONTEST (1<<8) // do occlusion test for this entity
|
||||
#define RF_PLANARSHADOW (1<<9) // force shadow to planar
|
||||
#define RF_NOSHADOW (1<<10) // disable shadow at all
|
||||
|
||||
// player_state_t->renderfx
|
||||
#define RDF_UNDERWATER (1<<0) // warp the screen as apropriate
|
||||
#define RDF_NOWORLDMODEL (1<<1) // used for player configuration screen
|
||||
#define RDF_BLOOM (1<<2) // light blooms
|
||||
#define RDF_OLDAREABITS (1<<3) // forces R_MarkLeaves() if not set
|
||||
#define RDF_PAIN (1<<4) // motion blur effects
|
||||
#define RDF_IRGOGGLES (1<<5) // infra red goggles effect
|
||||
#define RDF_PORTALINVIEW (1<<6) // cull entities using vis too because areabits are merged serverside
|
||||
#define RDF_SKYPORTALINVIEW (1<<7) // draw skyportal instead of regular sky
|
||||
#define RDF_NOFOVADJUSTMENT (1<<8) // do not adjust fov for widescreen
|
||||
|
||||
// entity_state_t->effects
|
||||
#define EF_BRIGHTFIELD (1<<0) // swirling cloud of particles
|
||||
|
@ -56,7 +70,6 @@
|
|||
#define CONTENTS_FOG (1<<4) // fog area or underwater volume
|
||||
#define CONTENTS_WINDOW (1<<5) // get rid of this
|
||||
|
||||
|
||||
// system contents
|
||||
#define CONTENTS_AREAPORTAL (1<<15)
|
||||
#define CONTENTS_ANTIPORTAL (1<<16)
|
||||
|
@ -74,6 +87,15 @@
|
|||
#define CONTENTS_LADDER (1<<27) // ladder in games
|
||||
#define CONTENTS_LIGHTGRID (1<<28) // lightgrid contents
|
||||
|
||||
// content masks
|
||||
#define MASK_SOLID (CONTENTS_SOLID)
|
||||
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_BODY)
|
||||
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_BODY)
|
||||
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
|
||||
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
|
||||
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
|
||||
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_CORPSE)
|
||||
|
||||
// surface flags
|
||||
#define SURF_NODAMAGE (1<<0) // never give falling damage
|
||||
#define SURF_SLICK (1<<1) // effects game physics
|
||||
|
@ -93,7 +115,7 @@
|
|||
#define SURF_ALPHA (1<<15) // alpha surface (e.g. grates, trees)
|
||||
#define SURF_BLEND (1<<16) // blended surface (e.g. windows)
|
||||
#define SURF_ADDITIVE (1<<17) // additive surface (studio skins)
|
||||
|
||||
#define SURF_NONSOLID (1<<18) // not solid surface
|
||||
|
||||
#define SURF_VERTEXLIT (SURF_POINTLIGHT|SURF_NOLIGHTMAP)
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
|
||||
#define METERS_PER_INCH 0.0254f
|
||||
#define EQUAL_EPSILON 0.001f
|
||||
#define STOP_EPSILON 0.1f
|
||||
#define ON_EPSILON 0.1f
|
||||
#define Z_NEAR 4.0f
|
||||
|
||||
#define ANGLE2CHAR(x) ((int)((x)*256/360) & 255)
|
||||
#define CHAR2ANGLE(x) ((x)*(360.0/256))
|
||||
|
@ -39,6 +39,7 @@
|
|||
#define nanmask (255<<23)
|
||||
|
||||
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
|
||||
#define rint(x) (( x ) < 0 ? ((int)(( x ) - 0.5f )) : ((int)(( x ) + 0.5f )))
|
||||
#define RANDOM_LONG(MIN, MAX) ((rand() & 32767) * (((MAX)-(MIN)) * (1.0f / 32767.0f)) + (MIN))
|
||||
#define RANDOM_FLOAT(MIN,MAX) (((float)rand() / RAND_MAX) * ((MAX)-(MIN)) + (MIN))
|
||||
|
||||
|
@ -59,6 +60,7 @@
|
|||
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
|
||||
#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
|
||||
#define VectorAverage(a,b,o) ((o)[0]=((a)[0]+(b)[0])*0.5,(o)[1]=((a)[1]+(b)[1])*0.5,(o)[2]=((a)[2]+(b)[2])*0.5)
|
||||
#define Vector2Set(v, x, y) ((v)[0]=(x),(v)[1]=(y))
|
||||
#define VectorSet(v, x, y, z) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z))
|
||||
#define Vector4Set(v, x, y, z, w) {v[0] = x; v[1] = y; v[2] = z; v[3] = w;}
|
||||
#define VectorClear(x) ((x)[0]=(x)[1]=(x)[2]=0)
|
||||
|
@ -240,7 +242,7 @@ _inline void ClearBounds (vec3_t mins, vec3_t maxs)
|
|||
maxs[0] = maxs[1] = maxs[2] = -99999;
|
||||
}
|
||||
|
||||
_inline void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
|
||||
_inline void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
int i;
|
||||
vec_t val;
|
||||
|
@ -586,6 +588,25 @@ _inline void PlaneClassify( cplane_t *p )
|
|||
if (p->normal[2] < 0) p->signbits |= 4;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
PlaneFromPoints
|
||||
=================
|
||||
*/
|
||||
_inline void PlaneFromPoints( vec3_t verts[3], cplane_t *plane )
|
||||
{
|
||||
vec3_t v1, v2;
|
||||
|
||||
VectorSubtract( verts[1], verts[0], v1 );
|
||||
VectorSubtract( verts[2], verts[0], v2 );
|
||||
CrossProduct( v2, v1, plane->normal );
|
||||
VectorNormalize( plane->normal );
|
||||
plane->dist = DotProduct( verts[0], plane->normal );
|
||||
|
||||
// FIXME: need to classify ?
|
||||
// PlaneClassify( plane );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BoundsIntersect
|
||||
|
@ -622,7 +643,7 @@ BoxOnPlaneSide (engine fast version)
|
|||
Returns SIDE_FRONT, SIDE_BACK, or SIDE_ON
|
||||
==============
|
||||
*/
|
||||
_inline int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, cplane_t *p )
|
||||
_inline int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const cplane_t *p )
|
||||
{
|
||||
if (p->type < 3) return ((emaxs[p->type] >= p->dist) | ((emins[p->type] < p->dist) << 1));
|
||||
switch(p->signbits)
|
||||
|
|
|
@ -6,12 +6,264 @@
|
|||
#define BASEMATRIX_H
|
||||
|
||||
#include <math.h>
|
||||
//#define OPENGL_STYLE //TODO: enable OpenGL style someday
|
||||
//#define OPENGL_STYLE // TODO: enable OpenGL style someday
|
||||
#define RHAND_STYLE // right hand style euler engles
|
||||
|
||||
/*
|
||||
Quake engine tranformation matrix
|
||||
Quake OpenGL other changes
|
||||
{ 0, 0,-1, 0, }, [ROLL] [PITCH] also put Z going up
|
||||
{-1, 0, 0, 0, }, [PITCH] [YAW] also put Z going up
|
||||
{ 0, 1, 0, 0, }, [YAW] [ROLL]
|
||||
{ 0, 0, 0, 1, }, [ORIGIN] [ORIGIN]
|
||||
*/
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (float)3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
Matrix3x3 operations
|
||||
matrix3x3 always keep in opengl style
|
||||
========================================================================
|
||||
*/
|
||||
#define Matrix3x3_LoadIdentity( mat ) Matrix3x3_Copy( mat, matrix3x3_identity )
|
||||
|
||||
static const matrix3x3 matrix3x3_identity =
|
||||
{
|
||||
{ 1, 0, 0 }, // PITCH [forward]
|
||||
{ 0, 1, 0 }, // YAW [right]
|
||||
{ 0, 0, 1 }, // ROLL [up]
|
||||
};
|
||||
|
||||
_inline void Matrix3x3_Copy( matrix3x3 out, const matrix3x3 in )
|
||||
{
|
||||
// FIXME: replace with Mem_Copy
|
||||
memcpy( out, in, sizeof( matrix3x3 ));
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_FromNormal( const vec3_t normal, matrix3x3 out )
|
||||
{
|
||||
out[0][0] = normal[0];
|
||||
out[0][1] = normal[1];
|
||||
out[0][2] = normal[2];
|
||||
|
||||
if( normal[0] || normal[1] )
|
||||
{
|
||||
double length;
|
||||
|
||||
out[1][0] = normal[1];
|
||||
out[1][1] = -normal[0];
|
||||
out[1][2] = 0;
|
||||
|
||||
length = out[1][0] * out[1][0] + out[1][1] * out[1][1] + out[1][2] * out[1][2];
|
||||
if( length != 0.0f )
|
||||
{
|
||||
double ilength;
|
||||
ilength = 1.0f / sqrt( length );
|
||||
out[1][0] *= ilength;
|
||||
out[1][1] *= ilength;
|
||||
out[1][2] *= ilength;
|
||||
}
|
||||
|
||||
out[2][0] = out[0][1] * out[1][2] - out[0][2] * out[1][1];
|
||||
out[2][1] = out[0][2] * out[1][0] - out[0][0] * out[1][2];
|
||||
out[2][2] = out[0][0] * out[1][1] - out[0][1] * out[1][0];
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// set identity
|
||||
out[1][0] = 1.0f;
|
||||
out[1][1] = 0.0f;
|
||||
out[1][2] = 0.0f;
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 1.0f;
|
||||
out[2][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_FromAngles( const vec3_t angles, matrix3x3 out )
|
||||
{
|
||||
double sp, sy, sr, cp, cy, cr;
|
||||
double angle;
|
||||
|
||||
angle = DEG2RAD(angles[PITCH]);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = DEG2RAD(angles[YAW]);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = DEG2RAD(angles[ROLL]);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
out[0][0] = cp*cy;
|
||||
out[0][1] = cp*sy;
|
||||
out[0][2] = -sp;
|
||||
out[1][0] = sr*sp*cy+cr*-sy;
|
||||
out[1][1] = sr*sp*sy+cr*cy;
|
||||
out[1][2] = sr*cp;
|
||||
out[2][0] = cr*sp*cy+-sr*-sy;
|
||||
out[2][1] = cr*sp*sy+-sr*cy;
|
||||
out[2][2] = cr*cp;
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_ToAngles( const matrix3x3 matrix, vec3_t out )
|
||||
{
|
||||
double pitch, cpitch, yaw, roll;
|
||||
|
||||
pitch = -asin( matrix[0][2] );
|
||||
cpitch = cos( pitch );
|
||||
|
||||
if( fabs( cpitch ) > EQUAL_EPSILON ) // gimball lock?
|
||||
{
|
||||
cpitch = 1.0f / cpitch;
|
||||
pitch = RAD2DEG( pitch );
|
||||
#ifdef RHAND_STYLE
|
||||
yaw = RAD2DEG( atan2( matrix[0][1] * cpitch, matrix[0][0] * cpitch ));
|
||||
#else
|
||||
yaw = RAD2DEG( atan2((-1)*-matrix[0][1] * cpitch, matrix[0][0] * cpitch ));
|
||||
#endif
|
||||
roll = RAD2DEG( atan2( -matrix[1][2] * cpitch, matrix[2][2] * cpitch ));
|
||||
}
|
||||
else
|
||||
{
|
||||
pitch = matrix[0][2] > 0 ? -90.0f : 90.0f;
|
||||
yaw = RAD2DEG( atan2( matrix[1][0], -matrix[1][1] ));
|
||||
#ifdef RHAND_STYLE
|
||||
roll = 180;
|
||||
#else
|
||||
roll = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
out[PITCH] = pitch;
|
||||
out[YAW] = yaw;
|
||||
out[ROLL] = roll;
|
||||
}
|
||||
|
||||
_inline bool Matrix3x3_Compare( const matrix3x3 mat1, const matrix3x3 mat2 )
|
||||
{
|
||||
if( mat1[0][0] != mat2[0][0] || mat1[0][1] != mat2[0][1] || mat1[0][2] != mat2[0][2] )
|
||||
return false;
|
||||
if( mat1[1][0] != mat2[1][0] || mat1[1][1] != mat2[1][1] || mat1[1][2] != mat2[1][2] )
|
||||
return false;
|
||||
if( mat1[2][0] != mat2[2][0] || mat1[2][1] != mat2[2][1] || mat1[2][2] != mat2[2][2] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_Transpose( matrix3x3 out, const matrix3x3 in )
|
||||
{
|
||||
out[0][0] = in[0][0];
|
||||
out[1][0] = in[0][1];
|
||||
out[2][0] = in[0][2];
|
||||
out[0][1] = in[1][0];
|
||||
out[1][1] = in[1][1];
|
||||
out[2][1] = in[1][2];
|
||||
out[0][2] = in[2][0];
|
||||
out[1][2] = in[2][1];
|
||||
out[2][2] = in[2][2];
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_Transform( matrix3x3 in, const float v[3], float out[3] )
|
||||
{
|
||||
out[0] = in[0][0] * v[0] + in[0][1] * v[1] + in[0][2] * v[2];
|
||||
out[1] = in[1][0] * v[0] + in[1][1] * v[1] + in[1][2] * v[2];
|
||||
out[2] = in[2][0] * v[0] + in[2][1] * v[1] + in[2][2] * v[2];
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_CreateRotate( matrix3x3 out, float angle, float x, float y, float z )
|
||||
{
|
||||
double len, c, s;
|
||||
|
||||
len = x * x + y * y + z * z;
|
||||
if( len != 0.0f ) len = 1.0f / sqrt( len );
|
||||
x *= len;
|
||||
y *= len;
|
||||
z *= len;
|
||||
|
||||
angle = DEG2RAD( angle );
|
||||
c = cos( angle );
|
||||
s = sin( angle );
|
||||
|
||||
out[0][0] = x * x + c * (1 - x * x);
|
||||
out[0][1] = x * y * (1 - c) + z * s;
|
||||
out[0][2] = x * z * (1 - c) - y * s;
|
||||
out[1][0] = x * y * (1 - c) - z * s;
|
||||
out[1][1] = y * y + c * (1 - y * y);
|
||||
out[1][2] = y * z * (1 - c) + x * s;
|
||||
out[2][0] = x * z * (1 - c) + y * s;
|
||||
out[2][1] = y * z * (1 - c) - x * s;
|
||||
out[2][2] = z * z + c * (1 - z * z);
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_Concat( matrix3x3 out, const matrix3x3 in1, const matrix3x3 in2 )
|
||||
{
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
|
||||
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
|
||||
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||
}
|
||||
|
||||
_inline void Matrix3x3_FromPoints( const vec3_t v1, const vec3_t v2, const vec3_t v3, matrix3x3 out )
|
||||
{
|
||||
float d;
|
||||
|
||||
out[2][0] = (v1[1] - v2[1]) * (v3[2] - v2[2]) - (v1[2] - v2[2]) * (v3[1] - v2[1]);
|
||||
out[2][1] = (v1[2] - v2[2]) * (v3[0] - v2[0]) - (v1[0] - v2[0]) * (v3[2] - v2[2]);
|
||||
out[2][2] = (v1[0] - v2[0]) * (v3[1] - v2[1]) - (v1[1] - v2[1]) * (v3[0] - v2[0]);
|
||||
d = rsqrt( out[2][0] * out[2][0] + out[2][1] * out[2][1] + out[2][2] * out[2][2]);
|
||||
|
||||
out[2][0] *= d;
|
||||
out[2][1] *= d;
|
||||
out[2][2] *= d;
|
||||
|
||||
// this rotate and negate guarantees a vector not colinear with the original
|
||||
out[1][0] = out[2][2];
|
||||
out[1][1] = -out[2][0];
|
||||
out[1][2] = out[2][1];
|
||||
d = -( out[1][0] * out[2][0] + out[1][1] * out[2][1] + out[1][2] * out[2][2] );
|
||||
|
||||
out[1][0] = out[1][0] + d * out[2][0];
|
||||
out[1][1] = out[1][1] + d * out[2][1];
|
||||
out[1][2] = out[1][2] + d * out[2][2];
|
||||
d = rsqrt( out[1][0] * out[1][0] + out[1][1] * out[1][1] + out[1][2] * out[1][2]);
|
||||
|
||||
out[1][0] *= d;
|
||||
out[1][1] *= d;
|
||||
out[1][2] *= d;
|
||||
out[0][0] = out[1][1] * out[2][2] - out[1][2] * out[2][1];
|
||||
out[0][1] = out[1][2] * out[2][0] - out[1][0] * out[2][2];
|
||||
out[0][2] = out[1][0] * out[2][1] - out[1][1] * out[2][0];
|
||||
}
|
||||
|
||||
|
||||
// FIXME: optimize
|
||||
_inline void Matrix3x3_ConcatRotate( matrix3x3 out, double angle, double x, double y, double z )
|
||||
{
|
||||
matrix3x3 base, temp;
|
||||
|
||||
Matrix3x3_Copy( base, out );
|
||||
Matrix3x3_CreateRotate( temp, angle, x, y, z );
|
||||
Matrix3x3_Concat( out, base, temp );
|
||||
}
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
Matrix4x4 operations
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
#define Matrix4x4_LoadIdentity( mat ) Matrix4x4_Copy( mat, identitymatrix )
|
||||
|
||||
static const matrix4x4 identitymatrix =
|
||||
|
@ -22,33 +274,20 @@ static const matrix4x4 identitymatrix =
|
|||
{ 0, 0, 0, 1 }, // ORIGIN
|
||||
};
|
||||
|
||||
// quake engine tranformation matrix
|
||||
static const matrix4x4 r_base_matrix =
|
||||
{ // Quake OpenGL other changes
|
||||
{ 0, 0,-1, 0, }, // ROLL [PITCH] also put Z going up
|
||||
{-1, 0, 0, 0, }, // PITCH [YAW] also put Z going up
|
||||
{ 0, 1, 0, 0, }, // YAW [ROLL]
|
||||
{ 0, 0, 0, 1, },
|
||||
static const matrix4x4 matrix4x4_halfidentity =
|
||||
{
|
||||
{ 0.5, 0.0, 0.0, 0.0 }, // PITCH
|
||||
{ 0.0, 0.5, 0.0, 0.0 }, // YAW
|
||||
{ 0.0, 0.0, 0.5, 0.0 }, // ROLL
|
||||
{ 0.5, 0.5, 0.5, 1.0 }, // ORIGIN
|
||||
};
|
||||
|
||||
_inline void Matrix4x4_Copy( matrix4x4 out, const matrix4x4 in )
|
||||
{
|
||||
// FIXME: replace with Mem_Copy
|
||||
memcpy( out, in, sizeof(matrix4x4));
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Transform( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0] + in[3][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1] + in[3][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2] + in[3][2];
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_TransformPoint( const matrix4x4 in, vec3_t point )
|
||||
{
|
||||
float out1, out2, out3;
|
||||
|
@ -84,32 +323,6 @@ _inline void Matrix4x4_TransformPoint( const matrix4x4 in, vec3_t point )
|
|||
point[2] = out3;
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Rotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_TransposeRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Transform3x3( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
|
@ -123,6 +336,33 @@ _inline void Matrix4x4_Transform3x3( const matrix4x4 in, const float v[3], float
|
|||
#endif
|
||||
}
|
||||
|
||||
// same as Matrix4x4_Transform3x3 but transpose matrix before
|
||||
_inline void Matrix4x4_Rotate3x3( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Transform( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0] + in[3][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1] + in[3][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2] + in[3][2];
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 )
|
||||
{
|
||||
// we only support uniform scaling, so assume the first row is enough
|
||||
|
@ -777,6 +1017,29 @@ _inline void Matrix4x4_FromArrayFloatGL( matrix4x4 out, const float in[16] )
|
|||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_ToMatrix3x3( matrix3x3 out, const matrix4x4 in )
|
||||
{
|
||||
out[0][0] = in[0][0];
|
||||
out[1][1] = in[1][1];
|
||||
out[2][2] = in[2][2];
|
||||
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][1] = in[1][0];
|
||||
out[0][2] = in[1][0];
|
||||
out[1][0] = in[0][1];
|
||||
out[1][2] = in[2][1];
|
||||
out[2][0] = in[0][2];
|
||||
out[2][1] = in[1][2];
|
||||
#else
|
||||
out[0][1] = in[0][1];
|
||||
out[0][2] = in[0][2];
|
||||
out[1][0] = in[1][0];
|
||||
out[1][2] = in[1][2];
|
||||
out[2][0] = in[2][0];
|
||||
out[2][1] = in[2][1];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline bool Matrix4x4_Invert_Full( matrix4x4 out, const matrix4x4 in1 )
|
||||
{
|
||||
float *temp;
|
||||
|
@ -1137,6 +1400,77 @@ _inline void Matrix4x4_OriginFromMatrix( const matrix4x4 in, float *out )
|
|||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Copy2D( matrix4x4 out, const matrix4x4 in )
|
||||
{
|
||||
out[0][0] = in[0][0];
|
||||
out[1][1] = in[1][1];
|
||||
out[0][1] = in[0][1];
|
||||
out[1][0] = in[1][0];
|
||||
out[3][0] = in[3][0];
|
||||
out[3][1] = in[3][1];
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Concat2D( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[1][0] * in2[0][1];
|
||||
out[0][1] = in1[0][1] * in2[0][0] + in1[1][1] * in2[0][1];
|
||||
out[1][0] = in1[0][0] * in2[1][0] + in1[1][0] * in2[1][1];
|
||||
out[1][1] = in1[0][1] * in2[1][0] + in1[1][1] * in2[1][1];
|
||||
out[3][0] = in1[0][0] * in2[3][0] + in1[1][0] * in2[3][1] + in1[3][0];
|
||||
out[3][1] = in1[0][1] * in2[3][0] + in1[1][1] * in2[3][1] + in1[3][1];
|
||||
#else
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1];
|
||||
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][3];
|
||||
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Scale2D( matrix4x4 out, vec_t x, vec_t y )
|
||||
{
|
||||
out[0][0] *= x;
|
||||
out[1][1] *= y;
|
||||
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][1] *= x;
|
||||
out[1][0] *= y;
|
||||
#else
|
||||
out[1][0] *= x;
|
||||
out[0][1] *= y;
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Translate2D( matrix4x4 out, vec_t x, vec_t y )
|
||||
{
|
||||
#ifdef OPENGL_STYLE
|
||||
out[3][0] += x;
|
||||
out[3][1] += y;
|
||||
#else
|
||||
out[0][3] += x;
|
||||
out[1][3] += y;
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_Stretch2D( matrix4x4 out, vec_t s, vec_t t )
|
||||
{
|
||||
out[0][0] *= s;
|
||||
out[1][1] *= s;
|
||||
#ifdef OPENGL_STYLE
|
||||
out[0][1] *= s;
|
||||
out[1][0] *= s;
|
||||
out[3][0] = s * out[3][0] + t;
|
||||
out[3][1] = s * out[3][1] + t;
|
||||
#else
|
||||
out[1][0] *= s;
|
||||
out[0][1] *= s;
|
||||
out[0][3] = s * out[0][3] + t;
|
||||
out[1][3] = s * out[1][3] + t;
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void Matrix4x4_ConcatScale( matrix4x4 out, double x )
|
||||
{
|
||||
matrix4x4 base, temp;
|
||||
|
|
|
@ -170,7 +170,7 @@ BRUSH MODELS
|
|||
#define LIGHTMAP_NAME "lm_%04d.png"
|
||||
#define LM_SIZE ( LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * LIGHTMAP_BITS )
|
||||
#define LM_SAMPLE_SIZE 16 // q1, q2, q3 default value (lightmap resoultion)
|
||||
#define LM_STYLES 4 // MAXLIGHTMAPS
|
||||
#define LM_STYLES 4 // MAXLIGHTMAPS, don't touch!
|
||||
#define LS_NORMAL 0x00
|
||||
#define LS_UNUSED 0xFE
|
||||
#define LS_NONE 0xFF
|
||||
|
@ -439,7 +439,7 @@ a internal virtual machine like as QuakeC, but it has more extensions
|
|||
typedef struct statement_s
|
||||
{
|
||||
dword op;
|
||||
long a,b,c;
|
||||
long a, b, c;
|
||||
} dstatement_t;
|
||||
|
||||
typedef struct ddef_s
|
||||
|
@ -447,7 +447,7 @@ typedef struct ddef_s
|
|||
dword type; // if DEF_SAVEGLOBAL bit is set
|
||||
// the variable needs to be saved in savegames
|
||||
dword ofs;
|
||||
int s_name;
|
||||
string_t s_name;
|
||||
} ddef_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -456,8 +456,8 @@ typedef struct
|
|||
int parm_start;
|
||||
int locals; // total ints of parms + locals
|
||||
int profile; // runtime
|
||||
int s_name;
|
||||
int s_file; // source file defined in
|
||||
string_t s_name;
|
||||
string_t s_file; // source file defined in
|
||||
int numparms;
|
||||
byte parm_size[MAX_PARMS];
|
||||
} dfunction_t;
|
||||
|
@ -635,7 +635,7 @@ typedef struct
|
|||
|
||||
int numtransitions; // animation node to animation node transition graph
|
||||
int transitionindex;
|
||||
} studiohdr_t;
|
||||
} dstudiohdr_t;
|
||||
|
||||
// header for demand loaded sequence group data
|
||||
typedef struct
|
||||
|
@ -645,7 +645,7 @@ typedef struct
|
|||
|
||||
char name[64];
|
||||
int length;
|
||||
} studioseqhdr_t;
|
||||
} dstudioseqhdr_t;
|
||||
|
||||
// bones
|
||||
typedef struct
|
||||
|
@ -656,7 +656,7 @@ typedef struct
|
|||
int bonecontroller[6]; // bone controller index, -1 == none
|
||||
float value[6]; // default DoF values
|
||||
float scale[6]; // scale for delta DoF values
|
||||
} mstudiobone_t;
|
||||
} dstudiobone_t;
|
||||
|
||||
// bone controllers
|
||||
typedef struct
|
||||
|
@ -667,7 +667,7 @@ typedef struct
|
|||
float end;
|
||||
int rest; // byte index value at rest
|
||||
int index; // 0-3 user set controller, 4 mouth
|
||||
} mstudiobonecontroller_t;
|
||||
} dstudiobonecontroller_t;
|
||||
|
||||
// intersection boxes
|
||||
typedef struct
|
||||
|
@ -676,7 +676,7 @@ typedef struct
|
|||
int group; // intersection group
|
||||
vec3_t bbmin; // bounding box
|
||||
vec3_t bbmax;
|
||||
} mstudiobbox_t;
|
||||
} dstudiobbox_t;
|
||||
|
||||
// demand loaded sequence groups
|
||||
typedef struct
|
||||
|
@ -685,7 +685,7 @@ typedef struct
|
|||
char name[64]; // file name
|
||||
void *cache; // cache index pointer (only in memory)
|
||||
int data; // hack for group 0
|
||||
} mstudioseqgroup_t;
|
||||
} dstudioseqgroup_t;
|
||||
|
||||
// sequence descriptions
|
||||
typedef struct
|
||||
|
@ -731,7 +731,7 @@ typedef struct
|
|||
int nodeflags; // transition rules
|
||||
|
||||
int nextseq; // auto advancing sequences
|
||||
} mstudioseqdesc_t;
|
||||
} dstudioseqdesc_t;
|
||||
|
||||
// events
|
||||
typedef struct
|
||||
|
@ -740,7 +740,7 @@ typedef struct
|
|||
int event;
|
||||
int type;
|
||||
char options[64];
|
||||
} mstudioevent_t;
|
||||
} dstudioevent_t;
|
||||
|
||||
// pivots
|
||||
typedef struct
|
||||
|
@ -748,7 +748,7 @@ typedef struct
|
|||
vec3_t org; // pivot point
|
||||
int start;
|
||||
int end;
|
||||
} mstudiopivot_t;
|
||||
} dstudiopivot_t;
|
||||
|
||||
// attachment
|
||||
typedef struct
|
||||
|
@ -758,12 +758,12 @@ typedef struct
|
|||
int bone;
|
||||
vec3_t org; // attachment point
|
||||
vec3_t vectors[3];
|
||||
} mstudioattachment_t;
|
||||
} dstudioattachment_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short offset[6];
|
||||
} mstudioanim_t;
|
||||
} dstudioanim_t;
|
||||
|
||||
// animation frames
|
||||
typedef union
|
||||
|
@ -774,8 +774,7 @@ typedef union
|
|||
byte total;
|
||||
} num;
|
||||
short value;
|
||||
} mstudioanimvalue_t;
|
||||
|
||||
} dstudioanimvalue_t;
|
||||
|
||||
// body part index
|
||||
typedef struct
|
||||
|
@ -784,8 +783,7 @@ typedef struct
|
|||
int nummodels;
|
||||
int base;
|
||||
int modelindex; // index into models array
|
||||
} mstudiobodyparts_t;
|
||||
|
||||
} dstudiobodyparts_t;
|
||||
|
||||
// skin info
|
||||
typedef struct
|
||||
|
@ -795,7 +793,7 @@ typedef struct
|
|||
int width;
|
||||
int height;
|
||||
int index;
|
||||
} mstudiotexture_t;
|
||||
} dstudiotexture_t;
|
||||
|
||||
// skin families
|
||||
// short index[skinfamilies][skinref] // skingroup info
|
||||
|
@ -820,7 +818,7 @@ typedef struct
|
|||
|
||||
int numgroups; // deformation groups
|
||||
int groupindex;
|
||||
} mstudiomodel_t;
|
||||
} dstudiomodel_t;
|
||||
|
||||
// meshes
|
||||
typedef struct
|
||||
|
@ -830,7 +828,7 @@ typedef struct
|
|||
int skinref;
|
||||
int numnorms; // per mesh normals
|
||||
int normindex; // normal vec3_t
|
||||
} mstudiomesh_t;
|
||||
} dstudiomesh_t;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
|
|
@ -84,6 +84,7 @@ typedef void (*xcommand_t) (void);
|
|||
|
||||
typedef enum
|
||||
{
|
||||
ED_INVALID = -1,
|
||||
ED_SPAWNED = 0, // this entity requris to set own type with SV_ClassifyEdict
|
||||
ED_STATIC, // this is a logic without model or entity with static model
|
||||
ED_AMBIENT, // this is entity emitted ambient sounds only
|
||||
|
@ -146,7 +147,7 @@ typedef struct model_state_s
|
|||
float animtime; // auto-animating time
|
||||
float framerate; // custom framerate, specified by QC
|
||||
int sequence; // animation sequence (0 - 255)
|
||||
int gaitsequence; // client\nps\bot gaitsequence
|
||||
int gaitsequence; // client\npc\bot gaitsequence
|
||||
int skin; // skin for studiomodels
|
||||
int body; // sub-model selection for studiomodels
|
||||
float blending[16]; // studio animation blending
|
||||
|
@ -366,11 +367,13 @@ static const bpc_desc_t PFDesc[] =
|
|||
#define IMAGE_GEN_MIPS 0x00000008 // must generate mips
|
||||
#define IMAGE_CUBEMAP_FLIP 0x00000010 // it's a cubemap with flipped sides( dds pack )
|
||||
#define IMAGE_ONLY_PALETTE 0x00000020 // image not valid, returns palette only
|
||||
#define IMAGE_COLORINDEX 0x00000040 // all colors in palette is gradients of last color (decals)
|
||||
|
||||
enum img_process
|
||||
{
|
||||
IMAGE_FLIP_X = 0,
|
||||
IMAGE_FLIP_Y,
|
||||
IMAGE_FLIP_X = 1,
|
||||
IMAGE_FLIP_Y = 2,
|
||||
IMAGE_FLIP_I = 4, // flip diagonal
|
||||
};
|
||||
|
||||
typedef struct rgbdata_s
|
||||
|
@ -573,6 +576,7 @@ typedef struct stdilib_api_s
|
|||
|
||||
// built-in imagelib functions
|
||||
rgbdata_t *(*LoadImage)( const char *path, const byte *buf, size_t filesize ); // return 8, 24 or 32 bit buffer with image info
|
||||
void (*ImageToRGB)( rgbdata_t *pic ); // expand any image to PF_RGB_24
|
||||
void (*ImageToRGBA)( rgbdata_t *pic ); // expand any image to PF_RGBA_32
|
||||
void (*SaveImage)( const char *filename, rgbdata_t *buffer ); // save image into specified format
|
||||
void (*FreeImage)( rgbdata_t *pack ); // free image buffer
|
||||
|
@ -679,7 +683,7 @@ typedef struct stdilib_api_s
|
|||
#define Mem_FreePool(pool) com.freepool(pool, __FILE__, __LINE__)
|
||||
#define Mem_EmptyPool(pool) com.clearpool(pool, __FILE__, __LINE__)
|
||||
#define Mem_Copy(dest, src, size ) com.memcpy(dest, src, size, __FILE__, __LINE__)
|
||||
#define Mem_Set(dest, val, size ) com.memcpy(dest, val, size, __FILE__, __LINE__)
|
||||
#define Mem_Set(dest, val, size ) com.memset(dest, val, size, __FILE__, __LINE__)
|
||||
#define Mem_Check() com.memcheck(__FILE__, __LINE__)
|
||||
#define Mem_CreateArray( p, s, n ) com.newarray( p, s, n, __FILE__, __LINE__)
|
||||
#define Mem_RemoveArray( array ) com.delarray( array, __FILE__, __LINE__)
|
||||
|
@ -849,6 +853,7 @@ imglib manager
|
|||
#define FS_LoadImage com.LoadImage
|
||||
#define FS_SaveImage com.SaveImage
|
||||
#define FS_FreeImage com.FreeImage
|
||||
#define Image_ExpandRGB com.ImageToRGB
|
||||
#define Image_ExpandRGBA com.ImageToRGBA
|
||||
#define Image_ConvertPalette com.ImagePal32to24
|
||||
#define Image_Resample com.ResampleImage
|
||||
|
@ -959,11 +964,6 @@ typedef struct cvar_s
|
|||
#define MAX_PARTICLES 32768 // pre one frame
|
||||
#define MAX_EDICTS 65535 // absolute limit that never be reached, (do not edit!)
|
||||
|
||||
// FIXME: player_state_t->renderfx
|
||||
#define RDF_NOWORLDMODEL (1<<0) // used for player configuration screen
|
||||
#define RDF_IRGOGGLES (1<<1)
|
||||
#define RDF_PAIN (1<<2)
|
||||
|
||||
// encoded bmodel mask
|
||||
#define SOLID_BMODEL 0xffffff
|
||||
|
||||
|
@ -1119,6 +1119,14 @@ typedef struct vrect_s
|
|||
int height;
|
||||
} vrect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float fov;
|
||||
float scale;
|
||||
vec3_t vieworg;
|
||||
vec3_t viewofs; // (map->size - player->vieworg) + viewofs
|
||||
} skyportal_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vrect_t rect; // screen rectangle
|
||||
|
@ -1128,6 +1136,9 @@ typedef struct
|
|||
vec3_t viewangles; // client angles
|
||||
float time; // time is used to shaders auto animate
|
||||
float oldtime; // oldtime using for lerping studio models
|
||||
skyportal_t skyportal; // env_sky settings
|
||||
float blend[4]; // q1\q2 legacy
|
||||
|
||||
uint rdflags; // client view effects: RDF_UNDERWATER, RDF_MOTIONBLUR, etc
|
||||
byte *areabits; // if not NULL, only areas with set bits will be drawn
|
||||
} refdef_t;
|
||||
|
@ -1220,7 +1231,7 @@ typedef struct render_exp_s
|
|||
bool (*AddLightStyle)( int stylenum, vec3_t color );
|
||||
void (*ClearScene)( void );
|
||||
|
||||
void (*BeginFrame)( void );
|
||||
void (*BeginFrame)( bool forceClear );
|
||||
void (*RenderFrame)( refdef_t *fd );
|
||||
void (*EndFrame)( void );
|
||||
|
||||
|
@ -1240,7 +1251,8 @@ typedef struct render_imp_s
|
|||
size_t api_size; // must matched with sizeof(render_imp_t)
|
||||
|
||||
// client fundamental callbacks
|
||||
void (*StudioEvent)( mstudioevent_t *event, entity_state_t *ent );
|
||||
float (*CalcFov)( float fov_x, float width, float height );
|
||||
void (*StudioEvent)( dstudioevent_t *event, entity_state_t *ent );
|
||||
void (*ShowCollision)( cmdraw_t callback ); // debug
|
||||
long (*WndProc)( void *hWnd, uint uMsg, uint wParam, long lParam );
|
||||
entity_state_t *(*GetClientEdict)( int index );
|
||||
|
|
|
@ -166,6 +166,20 @@ static dllfunc_t texture3dextfuncs[] =
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* GL_ARB_occlusion_query */
|
||||
static dllfunc_t occlusionqueryfuncs[] =
|
||||
{
|
||||
{"glGenQueriesARB", (void **) &pglGenQueriesARB},
|
||||
{"glDeleteQueriesARB", (void **) &pglDeleteQueriesARB},
|
||||
{"glIsQueryARB", (void **) &pglIsQueryARB},
|
||||
{"glBeginQueryARB", (void **) &pglBeginQueryARB},
|
||||
{"glEndQueryARB", (void **) &pglEndQueryARB},
|
||||
{"glGetQueryivARB", (void **) &pglGetQueryivARB},
|
||||
{"glGetQueryObjectivARB", (void **) &pglGetQueryObjectivARB},
|
||||
{"glGetQueryObjectuivARB", (void **) &pglGetQueryObjectuivARB},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static dllfunc_t atiseparatestencilfuncs[] =
|
||||
{
|
||||
{"glStencilOpSeparateATI", (void **) &pglStencilOpSeparate},
|
||||
|
@ -247,17 +261,6 @@ static dllfunc_t vertexshaderfuncs[] =
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static dllfunc_t cgprogramfuncs[] =
|
||||
{
|
||||
{"glBindProgramARB", (void **) &pglBindProgramARB},
|
||||
{"glDeleteProgramsARB", (void **) &pglDeleteProgramsARB},
|
||||
{"glGenProgramsARB", (void **) &pglGenProgramsARB},
|
||||
{"glProgramStringARB", (void **) &pglProgramStringARB},
|
||||
{"glProgramEnvParameter4fARB", (void **) &pglProgramEnvParameter4fARB},
|
||||
{"glProgramLocalParameter4fARB", (void **) &pglProgramLocalParameter4fARB},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static dllfunc_t vbofuncs[] =
|
||||
{
|
||||
{"glBindBufferARB" , (void **) &pglBindBufferARB},
|
||||
|
@ -303,11 +306,6 @@ void R_RenderInfo_f( void )
|
|||
Msg("GL_MAX_TEXTURE_UNITS_ARB: %i\n", gl_config.textureunits );
|
||||
if( GL_Support( R_TEXTURECUBEMAP_EXT ))
|
||||
Msg("GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: %i\n", gl_config.max_cubemap_texture_size );
|
||||
if( GL_Support( R_FRAGMENT_PROGRAM_EXT ))
|
||||
{
|
||||
Msg("GL_MAX_TEXTURE_COORDS_ARB: %i\n", gl_config.texturecoords );
|
||||
Msg("GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %i\n", gl_config.imageunits );
|
||||
}
|
||||
if( GL_Support( R_ANISOTROPY_EXT ))
|
||||
Msg("GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: %.1f\n", gl_config.max_anisotropy );
|
||||
if( gl_config.texRectangle )
|
||||
|
@ -328,6 +326,7 @@ void GL_InitCommands( void )
|
|||
r_mode = Cvar_Get( "r_mode", "0", CVAR_ARCHIVE, "display resolution mode" );
|
||||
|
||||
r_check_errors = Cvar_Get("r_check_errors", "1", CVAR_ARCHIVE, "ignore video engine errors" );
|
||||
r_hwgamma = Cvar_Get( "r_hwgamma", "1", CVAR_ARCHIVE|CVAR_LATCH, "using hardware gamma adjustment" );
|
||||
r_lefthand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE, "viewmodel handedness" );
|
||||
r_norefresh = Cvar_Get ("r_norefresh", "0", 0, "no description" );
|
||||
r_fullbright = Cvar_Get ("r_fullbright", "0", CVAR_LATCH, "disable lightmaps" );
|
||||
|
@ -362,6 +361,7 @@ void GL_InitCommands( void )
|
|||
|
||||
r_mirroralpha = Cvar_Get( "r_mirroralpha", "0.5", CVAR_ARCHIVE, "no description" );
|
||||
r_interpolate = Cvar_Get( "r_interpolate", "0", CVAR_ARCHIVE, "no description" );
|
||||
r_lmblocksize = Cvar_Get( "r_lmblocksize", "0", CVAR_ARCHIVE, "lightmap packed block size [dxd]" );
|
||||
|
||||
r_lightmap = Cvar_Get ("r_lightmap", "0", 0, "no description" );
|
||||
r_shadows = Cvar_Get ("r_shadows", "0", CVAR_ARCHIVE, "no description" );
|
||||
|
@ -384,11 +384,12 @@ void GL_InitCommands( void )
|
|||
r_showtextures = Cvar_Get("r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures" );
|
||||
r_offsetfactor = Cvar_Get("r_offsetfactor", "-1", CVAR_CHEAT, "z_trick offset factor" );
|
||||
r_offsetunits = Cvar_Get("r_offsetunits", "-2", CVAR_CHEAT, "z_trick offset uints" );
|
||||
r_debugsort = Cvar_Get( "r_debugsort", "0", CVAR_CHEAT, "enable custom z-sorting" );
|
||||
r_debugsort = Cvar_Get("r_debugsort", "0", CVAR_CHEAT, "enable custom z-sorting" );
|
||||
r_singleshader = Cvar_Get("r_singleshader", "0", CVAR_CHEAT|CVAR_LATCH, "apply default shader everywhere" );
|
||||
r_skipbackend = Cvar_Get("r_skipbackend", "0", CVAR_CHEAT, "skip 2d drawing (hud, console, etc)" );
|
||||
r_skipfrontend = Cvar_Get("r_skipfronend", "0", CVAR_CHEAT, "skip 3d drawing (scene)" );
|
||||
r_overbrightbits = Cvar_Get("r_overbrightbits", "0", CVAR_ARCHIVE|CVAR_LATCH, "hardware gamma overbright" );
|
||||
r_mapoverbrightbits = Cvar_Get("r_mapoverbrightbits", "0", CVAR_ARCHIVE|CVAR_LATCH, "hardware gamma map overbright bits" );
|
||||
|
||||
r_modulate = Cvar_Get( "r_modulate", "1.0", CVAR_ARCHIVE|CVAR_LATCH, "modulate light" );
|
||||
r_ambientscale = Cvar_Get("r_ambientScale", "0.6", CVAR_ARCHIVE, "default ambient light level" );
|
||||
|
@ -397,6 +398,12 @@ void GL_InitCommands( void )
|
|||
r_texturefilter = Cvar_Get( "gl_texturefilter", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, "texture filter" );
|
||||
r_texturefilteranisotropy = Cvar_Get( "r_anisotropy", "2.0", CVAR_ARCHIVE, "textures anisotropic filter" );
|
||||
r_detailtextures = Cvar_Get( "r_detailtextures", "0", CVAR_ARCHIVE|CVAR_LATCH, "allow detail textures" );
|
||||
r_portalmaps = Cvar_Get( "r_portalmaps", "0", CVAR_ARCHIVE|CVAR_LATCH, "allow portal maps" );
|
||||
r_fastsky = Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE, "disable sky portal (given some speedup)" );
|
||||
r_flares = Cvar_Get( "r_flares", "1", CVAR_ARCHIVE, "draw light flares" );
|
||||
r_flarefade = Cvar_Get( "r_flarefade", "0", CVAR_ARCHIVE, "enable linear fade for light flares" );
|
||||
r_occlusion_queries = Cvar_Get( "r_occlusion_queries", "0", CVAR_ARCHIVE, "enable render occlusion queries" );
|
||||
r_occlusion_queries_finish = Cvar_Get( "r_oq_finish", "0", CVAR_ARCHIVE, "call glFinish instead of glFlush at end of occlusion pass" );
|
||||
|
||||
r_swapInterval = Cvar_Get ("gl_swapinterval", "0", CVAR_ARCHIVE, "time beetween frames (in msec)" );
|
||||
gl_finish = Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE, "no description" );
|
||||
|
@ -595,6 +602,7 @@ void GL_InitExtensions( void )
|
|||
}
|
||||
|
||||
GL_CheckExtension( "GL_SGIS_generate_mipmap", NULL, "gl_sgis_generate_mipmaps", R_SGIS_MIPMAPS_EXT );
|
||||
GL_CheckExtension( "GL_ARB_occlusion_query", occlusionqueryfuncs, "gl_occlusion_query", R_OCCLUSION_QUERY );
|
||||
|
||||
// hardware cubemaps
|
||||
GL_CheckExtension( "GL_ARB_texture_cube_map", NULL, "gl_texture_cubemap", R_TEXTURECUBEMAP_EXT );
|
||||
|
@ -625,16 +633,8 @@ void GL_InitExtensions( void )
|
|||
// we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code
|
||||
if( pglDrawRangeElementsEXT == NULL ) pglDrawRangeElementsEXT = pglDrawRangeElements;
|
||||
|
||||
GL_CheckExtension( "GL_ARB_vertex_program", cgprogramfuncs, "gl_vertexprogram", R_VERTEX_PROGRAM_EXT );
|
||||
GL_CheckExtension( "GL_ARB_fragment_program", cgprogramfuncs, "gl_fragmentprogram", R_FRAGMENT_PROGRAM_EXT );
|
||||
GL_CheckExtension( "GL_ARB_texture_env_add", NULL, "gl_texture_env_add", R_TEXTURE_ENV_ADD_EXT );
|
||||
|
||||
if(GL_Support( R_FRAGMENT_PROGRAM_EXT ))
|
||||
{
|
||||
pglGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, &gl_config.texturecoords );
|
||||
pglGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_config.imageunits );
|
||||
}
|
||||
|
||||
// vp and fp shaders
|
||||
GL_CheckExtension( "GL_ARB_shader_objects", shaderobjectsfuncs, "gl_shaderobjects", R_SHADER_OBJECTS_EXT );
|
||||
GL_CheckExtension( "GL_ARB_shading_language_100", NULL, "gl_glslprogram", R_SHADER_GLSL100_EXT );
|
||||
|
@ -655,6 +655,75 @@ void GL_InitExtensions( void )
|
|||
else gl_config.texRectangle = gl_config.max_2d_rectangle_size = 0; // no rectangle
|
||||
}
|
||||
|
||||
void GL_EnableTexGen( GLint coord, GLint mode )
|
||||
{
|
||||
int tmu = gl_state.activeTMU;
|
||||
int bit, gen;
|
||||
|
||||
switch( coord )
|
||||
{
|
||||
case GL_S:
|
||||
bit = 1;
|
||||
gen = GL_TEXTURE_GEN_S;
|
||||
break;
|
||||
case GL_T:
|
||||
bit = 2;
|
||||
gen = GL_TEXTURE_GEN_T;
|
||||
break;
|
||||
case GL_R:
|
||||
bit = 4;
|
||||
gen = GL_TEXTURE_GEN_R;
|
||||
break;
|
||||
case GL_Q:
|
||||
bit = 8;
|
||||
gen = GL_TEXTURE_GEN_Q;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if( mode )
|
||||
{
|
||||
if(!(gl_state.texGen[tmu] & bit ))
|
||||
{
|
||||
pglEnable( gen );
|
||||
gl_state.texGen[tmu] |= bit;
|
||||
}
|
||||
pglTexGeni( coord, GL_TEXTURE_GEN_MODE, mode );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( gl_state.texGen[tmu] & bit )
|
||||
{
|
||||
pglDisable( gen );
|
||||
gl_state.texGen[tmu] &= ~bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GL_TexCoordMode( GLenum mode )
|
||||
{
|
||||
int tmu = gl_state.activeTMU;
|
||||
int bit, cmode = gl_state.texMod[tmu];
|
||||
|
||||
if( mode == GL_TEXTURE_COORD_ARRAY )
|
||||
bit = 1;
|
||||
else if( mode == GL_TEXTURE_CUBE_MAP_ARB )
|
||||
bit = 2;
|
||||
else bit = 0;
|
||||
|
||||
if( cmode != bit )
|
||||
{
|
||||
if( cmode == 1 ) pglDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
else if( cmode == 2 ) pglDisable( GL_TEXTURE_CUBE_MAP_ARB );
|
||||
|
||||
if( bit == 1 ) pglEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
else if( bit == 2 ) pglEnable( GL_TEXTURE_CUBE_MAP_ARB );
|
||||
|
||||
gl_state.texMod[tmu] = bit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_SelectTexture
|
||||
|
@ -724,16 +793,6 @@ void GL_Enable( GLenum cap )
|
|||
if( gl_state.polygonOffsetFill ) return;
|
||||
gl_state.polygonOffsetFill = true;
|
||||
break;
|
||||
case GL_VERTEX_PROGRAM_ARB:
|
||||
if(!GL_Support( R_VERTEX_PROGRAM_EXT ) || gl_state.vertexProgram )
|
||||
return;
|
||||
gl_state.vertexProgram = true;
|
||||
break;
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
if(!GL_Support( R_FRAGMENT_PROGRAM_EXT ) || gl_state.fragmentProgram )
|
||||
return;
|
||||
gl_state.fragmentProgram = true;
|
||||
break;
|
||||
case GL_ALPHA_TEST:
|
||||
if( gl_state.alpha_test ) return;
|
||||
gl_state.alpha_test = true;
|
||||
|
@ -767,16 +826,6 @@ void GL_Disable( GLenum cap )
|
|||
if( !gl_state.polygonOffsetFill ) return;
|
||||
gl_state.polygonOffsetFill = false;
|
||||
break;
|
||||
case GL_VERTEX_PROGRAM_ARB:
|
||||
if(!GL_Support( R_VERTEX_PROGRAM_EXT ) || !gl_state.vertexProgram )
|
||||
return;
|
||||
gl_state.vertexProgram = false;
|
||||
break;
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
if(!GL_Support( R_FRAGMENT_PROGRAM_EXT ) || !gl_state.fragmentProgram )
|
||||
return;
|
||||
gl_state.fragmentProgram = false;
|
||||
break;
|
||||
case GL_ALPHA_TEST:
|
||||
if(!gl_state.alpha_test ) return;
|
||||
gl_state.alpha_test = false;
|
||||
|
@ -803,6 +852,16 @@ void GL_CullFace( GLenum mode )
|
|||
if( gl_state.cullMode == mode )
|
||||
return;
|
||||
|
||||
if( !mode )
|
||||
{
|
||||
pglDisable( GL_CULL_FACE );
|
||||
gl_state.cullMode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if( !gl_state.cullMode )
|
||||
pglEnable( GL_CULL_FACE );
|
||||
|
||||
gl_state.cullMode = mode;
|
||||
pglCullFace( mode );
|
||||
}
|
||||
|
@ -880,6 +939,17 @@ void GL_DepthMask( GLboolean mask )
|
|||
pglDepthMask( mask );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_FrontFace
|
||||
=================
|
||||
*/
|
||||
void GL_FrontFace( GLboolean front )
|
||||
{
|
||||
pglFrontFace( front ? GL_CW : GL_CCW );
|
||||
gl_state.frontFace = front;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GL_SetColor
|
||||
|
@ -900,7 +970,24 @@ void GL_SetColor( const void *data )
|
|||
}
|
||||
}
|
||||
|
||||
void GL_LoadMatrix( matrix4x4 source )
|
||||
void GL_LoadTexMatrix( const matrix4x4 source )
|
||||
{
|
||||
pglMatrixMode( GL_TEXTURE );
|
||||
GL_LoadMatrix( source );
|
||||
gl_state.texMat[gl_state.activeTMU] = true;
|
||||
}
|
||||
|
||||
void GL_LoadIdentityTexMatrix( void )
|
||||
{
|
||||
if( gl_state.texMat[gl_state.activeTMU] )
|
||||
{
|
||||
pglMatrixMode( GL_TEXTURE );
|
||||
pglLoadIdentity();
|
||||
gl_state.texMat[gl_state.activeTMU] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GL_LoadMatrix( const matrix4x4 source )
|
||||
{
|
||||
gl_matrix dest;
|
||||
|
||||
|
@ -916,6 +1003,144 @@ void GL_SaveMatrix( GLenum target, matrix4x4 dest )
|
|||
Matrix4x4_FromArrayFloatGL( dest, source );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_SetState
|
||||
=================
|
||||
*/
|
||||
void GL_SetState( GLint state )
|
||||
{
|
||||
GLint diff;
|
||||
|
||||
if( gl_state.orthogonal ) state |= GLSTATE_NO_DEPTH_TEST;
|
||||
if( state & GLSTATE_NO_DEPTH_TEST )
|
||||
state &= ~( GLSTATE_DEPTHWRITE|GLSTATE_DEPTHFUNC_EQ );
|
||||
|
||||
diff = gl_state.flags ^ state;
|
||||
if( !diff ) return;
|
||||
|
||||
if( diff & ( GLSTATE_BLEND_MTEX|GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK ))
|
||||
{
|
||||
if( state & ( GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK ))
|
||||
{
|
||||
GLint blendsrc, blenddst;
|
||||
|
||||
switch( state & GLSTATE_SRCBLEND_MASK )
|
||||
{
|
||||
case GLSTATE_SRCBLEND_ZERO:
|
||||
blendsrc = GL_ZERO;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_DST_COLOR:
|
||||
blendsrc = GL_DST_COLOR;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_ONE_MINUS_DST_COLOR:
|
||||
blendsrc = GL_ONE_MINUS_DST_COLOR;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_SRC_ALPHA:
|
||||
blendsrc = GL_SRC_ALPHA;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA:
|
||||
blendsrc = GL_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_DST_ALPHA:
|
||||
blendsrc = GL_DST_ALPHA;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_ONE_MINUS_DST_ALPHA:
|
||||
blendsrc = GL_ONE_MINUS_DST_ALPHA;
|
||||
break;
|
||||
case GLSTATE_SRCBLEND_ONE:
|
||||
default:
|
||||
blendsrc = GL_ONE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch( state & GLSTATE_DSTBLEND_MASK )
|
||||
{
|
||||
case GLSTATE_DSTBLEND_ONE:
|
||||
blenddst = GL_ONE;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_SRC_COLOR:
|
||||
blenddst = GL_SRC_COLOR;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR:
|
||||
blenddst = GL_ONE_MINUS_SRC_COLOR;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_SRC_ALPHA:
|
||||
blenddst = GL_SRC_ALPHA;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA:
|
||||
blenddst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_DST_ALPHA:
|
||||
blenddst = GL_DST_ALPHA;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_ONE_MINUS_DST_ALPHA:
|
||||
blenddst = GL_ONE_MINUS_DST_ALPHA;
|
||||
break;
|
||||
case GLSTATE_DSTBLEND_ZERO:
|
||||
default:
|
||||
blenddst = GL_ZERO;
|
||||
break;
|
||||
}
|
||||
|
||||
if( state & GLSTATE_BLEND_MTEX )
|
||||
{
|
||||
if( gl_state.texEnv[gl_state.activeTMU] != GL_REPLACE )
|
||||
GL_Enable( GL_BLEND );
|
||||
else GL_Disable( GL_BLEND );
|
||||
}
|
||||
else GL_Enable( GL_BLEND );
|
||||
GL_BlendFunc( blendsrc, blenddst );
|
||||
}
|
||||
else GL_Disable( GL_BLEND );
|
||||
}
|
||||
|
||||
if( diff & GLSTATE_ALPHAFUNC )
|
||||
{
|
||||
if( state & GLSTATE_ALPHAFUNC )
|
||||
{
|
||||
if(!( gl_state.flags & GLSTATE_ALPHAFUNC ))
|
||||
GL_Enable( GL_ALPHA_TEST );
|
||||
|
||||
if( state & GLSTATE_AFUNC_GT0 )
|
||||
GL_AlphaFunc( GL_GREATER, 0 );
|
||||
else if( state & GLSTATE_AFUNC_LT128 )
|
||||
GL_AlphaFunc( GL_LESS, 0.5f );
|
||||
else GL_AlphaFunc( GL_GEQUAL, 0.5f );
|
||||
}
|
||||
else GL_Disable( GL_ALPHA_TEST );
|
||||
}
|
||||
|
||||
if( diff & GLSTATE_DEPTHFUNC_EQ )
|
||||
{
|
||||
if( state & GLSTATE_DEPTHFUNC_EQ )
|
||||
GL_DepthFunc( GL_EQUAL );
|
||||
else GL_DepthFunc( GL_LEQUAL );
|
||||
}
|
||||
|
||||
if( diff & GLSTATE_DEPTHWRITE )
|
||||
{
|
||||
if( state & GLSTATE_DEPTHWRITE )
|
||||
GL_DepthMask( GL_TRUE );
|
||||
else GL_DepthMask( GL_FALSE );
|
||||
}
|
||||
|
||||
if( diff & GLSTATE_NO_DEPTH_TEST )
|
||||
{
|
||||
if( state & GLSTATE_NO_DEPTH_TEST )
|
||||
GL_Disable( GL_DEPTH_TEST );
|
||||
else GL_Enable( GL_DEPTH_TEST );
|
||||
}
|
||||
|
||||
if( diff & GLSTATE_OFFSET_FILL )
|
||||
{
|
||||
if( state & GLSTATE_OFFSET_FILL )
|
||||
GL_Enable( GL_POLYGON_OFFSET_FILL );
|
||||
else GL_Disable( GL_POLYGON_OFFSET_FILL );
|
||||
}
|
||||
gl_state.flags = state;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_SetDefaultState
|
||||
|
@ -937,8 +1162,6 @@ void GL_SetDefaultState( void )
|
|||
|
||||
gl_state.cullFace = true;
|
||||
gl_state.polygonOffsetFill = false;
|
||||
gl_state.vertexProgram = false;
|
||||
gl_state.fragmentProgram = false;
|
||||
gl_state.alpha_test = false;
|
||||
gl_state.blend = false;
|
||||
gl_state.depth_test = true;
|
||||
|
@ -960,9 +1183,6 @@ void GL_SetDefaultState( void )
|
|||
pglDisable( GL_BLEND );
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
|
||||
if(GL_Support( R_VERTEX_PROGRAM_EXT )) pglDisable( GL_VERTEX_PROGRAM_ARB );
|
||||
if(GL_Support( R_FRAGMENT_PROGRAM_EXT )) pglDisable( GL_FRAGMENT_PROGRAM_ARB );
|
||||
|
||||
pglCullFace( GL_FRONT );
|
||||
pglPolygonOffset( -1, -2 );
|
||||
pglAlphaFunc( GL_GREATER, 0.0 );
|
||||
|
@ -1030,7 +1250,7 @@ void GL_Setup3D( void )
|
|||
|
||||
// Set up projection
|
||||
pglMatrixMode( GL_PROJECTION );
|
||||
pglLoadMatrixf( gl_projectionMatrix );
|
||||
GL_LoadMatrix( Ref.projectionMatrix );
|
||||
pglMatrixMode( GL_MODELVIEW );
|
||||
|
||||
// Set state
|
||||
|
@ -1039,8 +1259,6 @@ void GL_Setup3D( void )
|
|||
GL_TexEnv( GL_MODULATE );
|
||||
GL_Enable( GL_CULL_FACE );
|
||||
GL_Disable( GL_POLYGON_OFFSET_FILL );
|
||||
GL_Disable( GL_VERTEX_PROGRAM_ARB );
|
||||
GL_Disable( GL_FRAGMENT_PROGRAM_ARB );
|
||||
GL_Disable( GL_ALPHA_TEST );
|
||||
GL_Disable( GL_BLEND );
|
||||
GL_Enable( GL_DEPTH_TEST );
|
||||
|
@ -1067,6 +1285,7 @@ void GL_Setup3D( void )
|
|||
*/
|
||||
void GL_Setup2D( void )
|
||||
{
|
||||
extern meshbuffer_t pic_mbuffer;
|
||||
if( gl_finish->integer ) pglFinish();
|
||||
|
||||
// set 2D virtual screen size
|
||||
|
@ -1085,16 +1304,24 @@ void GL_Setup2D( void )
|
|||
// Set state
|
||||
gl_state.orthogonal = true;
|
||||
|
||||
GL_SetState( GLSTATE_NO_DEPTH_TEST );
|
||||
/*
|
||||
GL_TexEnv( GL_MODULATE );
|
||||
|
||||
GL_Disable( GL_CULL_FACE );
|
||||
GL_Disable( GL_POLYGON_OFFSET_FILL );
|
||||
GL_Disable( GL_VERTEX_PROGRAM_ARB );
|
||||
GL_Disable( GL_FRAGMENT_PROGRAM_ARB );
|
||||
GL_Disable( GL_ALPHA_TEST );
|
||||
GL_Enable( GL_BLEND );
|
||||
GL_Disable( GL_DEPTH_TEST );
|
||||
|
||||
GL_BlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
GL_DepthMask( GL_FALSE );
|
||||
*/
|
||||
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
pic_mbuffer.infoKey = -1;
|
||||
pic_mbuffer.shaderKey = 0;
|
||||
Ref.m_pCurrentEntity = Ref.m_pPrevEntity = NULL;
|
||||
Ref.m_pCurrentModel = NULL;
|
||||
}
|
3353
render/r_backend.c
3353
render/r_backend.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,493 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2008 ©
|
||||
// r_cull.c - frustum and pvs culling
|
||||
//=======================================================================
|
||||
|
||||
#include <assert.h>
|
||||
#include "r_local.h"
|
||||
#include "r_meshbuffer.h"
|
||||
#include "mathlib.h"
|
||||
#include "const.h"
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
FRUSTUM AND PVS CULLING
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
R_CullBox
|
||||
|
||||
Returns true if the box is completely outside the frustum
|
||||
=================
|
||||
*/
|
||||
bool R_CullBox( const vec3_t mins, const vec3_t maxs, const uint clipflags )
|
||||
{
|
||||
uint i, bit;
|
||||
const cplane_t *plane;
|
||||
|
||||
if( r_nocull->integer ) return false;
|
||||
|
||||
i = sizeof( Ref.frustum ) / sizeof( Ref.frustum[0] );
|
||||
for( bit = 1, plane = Ref.frustum; i > 0; i--, bit<<=1, plane++ )
|
||||
{
|
||||
if(!( clipflags & bit )) continue;
|
||||
if( BoxOnPlaneSide( mins, maxs, plane ) == SIDE_ON )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullSphere
|
||||
|
||||
Returns true if the sphere is completely outside the frustum
|
||||
=================
|
||||
*/
|
||||
bool R_CullSphere( const vec3_t origin, const float radius, const uint clipflags )
|
||||
{
|
||||
uint i, bit;
|
||||
const cplane_t *plane;
|
||||
|
||||
if( r_nocull->integer ) return false;
|
||||
|
||||
i = sizeof( Ref.frustum ) / sizeof( Ref.frustum[0] );
|
||||
for( bit = 1, plane = Ref.frustum; i > 0; i--, bit<<=1, plane++ )
|
||||
{
|
||||
if(!( clipflags & bit )) continue;
|
||||
if( DotProduct( origin, plane->normal ) - plane->dist <= -radius )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
R_VisCullBox
|
||||
===================
|
||||
*/
|
||||
bool R_VisCullBox( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
int s, stackdepth = 0;
|
||||
vec3_t extmins, extmaxs;
|
||||
mnode_t *node, *localstack[2048];
|
||||
|
||||
if( !r_worldModel || ( Ref.refdef.rdflags & RDF_NOWORLDMODEL ))
|
||||
return false;
|
||||
if( r_novis->integer ) return false;
|
||||
|
||||
for( s = 0; s < 3; s++ )
|
||||
{
|
||||
extmins[s] = mins[s] - 4;
|
||||
extmaxs[s] = maxs[s] + 4;
|
||||
}
|
||||
|
||||
for( node = r_worldBrushModel->nodes;; )
|
||||
{
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
{
|
||||
if( !stackdepth ) return true;
|
||||
node = localstack[--stackdepth];
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !node->plane ) return false;
|
||||
|
||||
s = BoxOnPlaneSide( extmins, extmaxs, node->plane ) - 1;
|
||||
if( s < 2 )
|
||||
{
|
||||
node = node->children[s];
|
||||
continue;
|
||||
}
|
||||
|
||||
// go down both sides
|
||||
if( stackdepth < sizeof( localstack )/sizeof( mnode_t * ))
|
||||
localstack[stackdepth++] = node->children[0];
|
||||
node = node->children[1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
R_VisCullSphere
|
||||
===================
|
||||
*/
|
||||
bool R_VisCullSphere( const vec3_t origin, float radius )
|
||||
{
|
||||
float dist;
|
||||
int stackdepth = 0;
|
||||
mnode_t *node, *localstack[2048];
|
||||
|
||||
if( !r_worldModel || ( Ref.refdef.rdflags & RDF_NOWORLDMODEL ))
|
||||
return false;
|
||||
if( r_novis->integer ) return false;
|
||||
|
||||
radius += 4;
|
||||
for( node = r_worldBrushModel->nodes;; )
|
||||
{
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
{
|
||||
if( !stackdepth ) return true;
|
||||
node = localstack[--stackdepth];
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !node->plane ) return false;
|
||||
|
||||
dist = PlaneDiff( origin, node->plane );
|
||||
if( dist > radius )
|
||||
{
|
||||
node = node->children[0];
|
||||
continue;
|
||||
}
|
||||
else if( dist < -radius )
|
||||
{
|
||||
node = node->children[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
// go down both sides
|
||||
if( stackdepth < sizeof( localstack ) / sizeof( mnode_t * ))
|
||||
localstack[stackdepth++] = node->children[0];
|
||||
node = node->children[1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CullModel
|
||||
=============
|
||||
*/
|
||||
int R_CullModel( ref_entity_t *e, vec3_t mins, vec3_t maxs, float radius )
|
||||
{
|
||||
if( e->renderfx & RF_VIEWMODEL )
|
||||
{
|
||||
if( Ref.params & RP_NONVIEWERREF )
|
||||
return SIDE_BACK;
|
||||
return SIDE_FRONT;
|
||||
}
|
||||
|
||||
if( e->renderfx & RF_PLAYERMODEL )
|
||||
{
|
||||
if(!( Ref.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW )))
|
||||
return SIDE_BACK;
|
||||
}
|
||||
|
||||
if( R_CullSphere( e->origin, radius, Ref.clipFlags ))
|
||||
return SIDE_BACK;
|
||||
|
||||
if( Ref.refdef.rdflags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( Ref.params & RP_SKYPORTALVIEW ))
|
||||
{
|
||||
if( R_VisCullSphere( e->origin, radius ))
|
||||
return SIDE_ON;
|
||||
}
|
||||
return SIDE_FRONT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
OCCLUSION QUERIES
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
|
||||
// occlusion queries for entities
|
||||
#define BEGIN_OQ_ENTITIES 0
|
||||
#define MAX_OQ_ENTITIES MAX_ENTITIES
|
||||
#define END_OQ_ENTITIES ( BEGIN_OQ_ENTITIES+MAX_OQ_ENTITIES )
|
||||
|
||||
// occlusion queries for planar shadows
|
||||
#define BEGIN_OQ_PLANARSHADOWS END_OQ_ENTITIES
|
||||
#define MAX_OQ_PLANARSHADOWS MAX_ENTITIES
|
||||
#define END_OQ_PLANARSHADOWS ( BEGIN_OQ_PLANARSHADOWS+MAX_OQ_PLANARSHADOWS )
|
||||
|
||||
// occlusion queries for shadowgroups
|
||||
#define BEGIN_OQ_SHADOWGROUPS END_OQ_PLANARSHADOWS
|
||||
#define MAX_OQ_SHADOWGROUPS MAX_SHADOWGROUPS
|
||||
#define END_OQ_SHADOWGROUPS ( BEGIN_OQ_SHADOWGROUPS+MAX_OQ_SHADOWGROUPS )
|
||||
|
||||
// custom occlusion queries (portals, mirrors, etc)
|
||||
#define BEGIN_OQ_CUSTOM END_OQ_SHADOWGROUPS
|
||||
#define MAX_OQ_CUSTOM MAX_SURF_QUERIES
|
||||
#define END_OQ_CUSTOM ( BEGIN_OQ_CUSTOM+MAX_OQ_CUSTOM )
|
||||
|
||||
#define MAX_OQ_TOTAL ( MAX_OQ_ENTITIES+MAX_OQ_PLANARSHADOWS+MAX_OQ_SHADOWGROUPS+MAX_OQ_CUSTOM )
|
||||
|
||||
static byte r_queriesBits[MAX_OQ_TOTAL/8];
|
||||
static GLuint r_occlusionQueries[MAX_OQ_TOTAL];
|
||||
|
||||
static meshbuffer_t r_occluderMB;
|
||||
static shader_t *r_occlusionShader;
|
||||
static bool r_occludersQueued;
|
||||
static ref_entity_t *r_occlusionEntity;
|
||||
|
||||
static void R_RenderOccludingSurfaces( void );
|
||||
|
||||
/*
|
||||
===============
|
||||
R_InitOcclusionQueries
|
||||
===============
|
||||
*/
|
||||
void R_InitOcclusionQueries( void )
|
||||
{
|
||||
meshbuffer_t *meshbuf = &r_occluderMB;
|
||||
|
||||
if( !r_occlusionShader )
|
||||
r_occlusionShader = R_FindShader( "***r_occlusion***", SHADER_OPAQUE_OCCLUDER, 0 );
|
||||
|
||||
if( !GL_Support( R_OCCLUSION_QUERY ))
|
||||
return;
|
||||
|
||||
pglGenQueriesARB( MAX_OQ_TOTAL, r_occlusionQueries );
|
||||
|
||||
meshbuf->sortKey = R_EDICTNUM( r_worldEntity )|MESH_MODEL;
|
||||
meshbuf->shaderKey = r_occlusionShader->sortKey;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_BeginOcclusionPass
|
||||
===============
|
||||
*/
|
||||
void R_BeginOcclusionPass( void )
|
||||
{
|
||||
assert( OCCLUSION_QUERIES_ENABLED( Ref ));
|
||||
|
||||
r_occludersQueued = false;
|
||||
r_occlusionEntity = r_worldEntity;
|
||||
Mem_Set( r_queriesBits, 0, sizeof( r_queriesBits ));
|
||||
|
||||
R_LoadIdentity();
|
||||
RB_ResetPassMask();
|
||||
R_ClearSurfOcclusionQueryKeys();
|
||||
|
||||
pglShadeModel( GL_FLAT );
|
||||
pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_EndOcclusionPass
|
||||
===============
|
||||
*/
|
||||
void R_EndOcclusionPass( void )
|
||||
{
|
||||
assert( OCCLUSION_QUERIES_ENABLED( Ref ));
|
||||
|
||||
R_RenderOccludingSurfaces();
|
||||
R_SurfIssueOcclusionQueries();
|
||||
RB_ResetPassMask();
|
||||
RB_ResetCounters();
|
||||
|
||||
if( r_occlusion_queries_finish->integer )
|
||||
pglFinish();
|
||||
else pglFlush();
|
||||
|
||||
pglShadeModel( GL_SMOOTH );
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_RenderOccludingSurfaces
|
||||
===============
|
||||
*/
|
||||
static void R_RenderOccludingSurfaces( void )
|
||||
{
|
||||
if( !r_occludersQueued )
|
||||
return;
|
||||
|
||||
r_occludersQueued = false;
|
||||
R_RotateForEntity( r_occlusionEntity );
|
||||
RB_ResetPassMask();
|
||||
R_RenderMeshBuffer( &r_occluderMB );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_OcclusionShader
|
||||
===============
|
||||
*/
|
||||
shader_t *R_OcclusionShader( void )
|
||||
{
|
||||
return r_occlusionShader;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_AddOccludingSurface
|
||||
===============
|
||||
*/
|
||||
void R_AddOccludingSurface( msurface_t *surf, shader_t *shader )
|
||||
{
|
||||
int diff = shader->flags ^ r_occlusionShader->flags;
|
||||
|
||||
if( R_MeshOverflow( surf->mesh ) || ( diff & ( SHADER_CULL )) || r_occlusionEntity != Ref.m_pCurrentEntity )
|
||||
{
|
||||
R_RenderOccludingSurfaces();
|
||||
|
||||
r_occlusionShader->flags ^= diff;
|
||||
r_occlusionEntity = Ref.m_pCurrentEntity;
|
||||
}
|
||||
|
||||
r_occludersQueued = true;
|
||||
R_PushMesh( surf->mesh, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_GetOcclusionQueryNum
|
||||
===============
|
||||
*/
|
||||
int R_GetOcclusionQueryNum( int type, int key )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case OQ_ENTITY:
|
||||
return ( r_occlusion_queries->integer & 1 ) ? BEGIN_OQ_ENTITIES + ( key%MAX_OQ_ENTITIES ) : -1;
|
||||
case OQ_PLANARSHADOW:
|
||||
return ( r_occlusion_queries->integer & 1 ) ? BEGIN_OQ_PLANARSHADOWS + ( key%MAX_OQ_PLANARSHADOWS ) : -1;
|
||||
case OQ_SHADOWGROUP:
|
||||
return ( r_occlusion_queries->integer & 2 ) ? BEGIN_OQ_SHADOWGROUPS + ( key%MAX_OQ_SHADOWGROUPS ) : -1;
|
||||
case OQ_CUSTOM:
|
||||
return BEGIN_OQ_CUSTOM + ( key%MAX_OQ_CUSTOM );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_IssueOcclusionQuery
|
||||
===============
|
||||
*/
|
||||
int R_IssueOcclusionQuery( int query, ref_entity_t *e, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
static vec4_t verts[8];
|
||||
static rb_mesh_t mesh;
|
||||
static uint indices[] =
|
||||
{
|
||||
0, 1, 2, 1, 2, 3, // top
|
||||
7, 5, 6, 5, 6, 4, // bottom
|
||||
4, 0, 6, 0, 6, 2, // front
|
||||
3, 7, 1, 7, 1, 5, // back
|
||||
0, 1, 4, 1, 4, 5, // left
|
||||
7, 6, 3, 6, 3, 2, // right
|
||||
};
|
||||
int i;
|
||||
vec3_t bbox[8];
|
||||
|
||||
if( query < 0 ) return -1;
|
||||
if( r_queriesBits[query>>3] & (1<<( query&7 )))
|
||||
return -1;
|
||||
r_queriesBits[query>>3] |= (1<<( query&7 ));
|
||||
|
||||
R_RenderOccludingSurfaces();
|
||||
|
||||
mesh.numVerts = 8;
|
||||
mesh.points = verts;
|
||||
mesh.numIndexes = 36;
|
||||
mesh.indexes = indices;
|
||||
r_occlusionShader->flags &= ~SHADER_CULL;
|
||||
|
||||
pglBeginQueryARB( GL_SAMPLES_PASSED_ARB, r_occlusionQueries[query] );
|
||||
|
||||
R_TransformEntityBBox( e, mins, maxs, bbox, false );
|
||||
for( i = 0; i < 8; i++ )
|
||||
Vector4Set( verts[i], bbox[i][0], bbox[i][1], bbox[i][2], 1 );
|
||||
|
||||
R_RotateForEntity( e );
|
||||
RB_SetPassMask( GLSTATE_MASK & ~GLSTATE_DEPTHWRITE );
|
||||
R_PushMesh( &mesh, MF_NONBATCHED|MF_NOCULL );
|
||||
R_RenderMeshBuffer( &r_occluderMB );
|
||||
|
||||
pglEndQueryARB( GL_SAMPLES_PASSED_ARB );
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_OcclusionQueryIssued
|
||||
===============
|
||||
*/
|
||||
bool R_OcclusionQueryIssued( int query )
|
||||
{
|
||||
assert( query >= 0 && query < MAX_OQ_TOTAL );
|
||||
return r_queriesBits[query>>3] & (1<<(query & 7));
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_GetOcclusionQueryResult
|
||||
===============
|
||||
*/
|
||||
uint R_GetOcclusionQueryResult( int query, bool wait )
|
||||
{
|
||||
GLint available;
|
||||
GLuint sampleCount;
|
||||
|
||||
if( query < 0 ) return 1;
|
||||
if( !R_OcclusionQueryIssued( query ))
|
||||
return 1;
|
||||
|
||||
query = r_occlusionQueries[query];
|
||||
|
||||
pglGetQueryObjectivARB( query, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
|
||||
if( !available && wait )
|
||||
{
|
||||
int n = 0;
|
||||
do
|
||||
{
|
||||
n++;
|
||||
pglGetQueryObjectivARB( query, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
|
||||
} while( !available && ( n < 10000 ));
|
||||
}
|
||||
|
||||
if( !available ) return 0;
|
||||
pglGetQueryObjectuivARB( query, GL_QUERY_RESULT_ARB, &sampleCount );
|
||||
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_GetOcclusionQueryResultBool
|
||||
===============
|
||||
*/
|
||||
bool R_GetOcclusionQueryResultBool( int type, int key, bool wait )
|
||||
{
|
||||
int query = R_GetOcclusionQueryNum( type, key );
|
||||
|
||||
if( query >= 0 && R_OcclusionQueryIssued( query ) )
|
||||
{
|
||||
if( R_GetOcclusionQueryResult( query, wait ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ShutdownOcclusionQueries
|
||||
===============
|
||||
*/
|
||||
void R_ShutdownOcclusionQueries( void )
|
||||
{
|
||||
r_occlusionShader = NULL;
|
||||
|
||||
if(!GL_Support( R_OCCLUSION_QUERY ))
|
||||
return;
|
||||
|
||||
pglDeleteQueriesARB( MAX_OQ_TOTAL, r_occlusionQueries );
|
||||
r_occludersQueued = false;
|
||||
}
|
|
@ -14,7 +14,7 @@ this is needed by some client drawing functions
|
|||
*/
|
||||
void R_GetPicSize( int *w, int *h, const char *pic )
|
||||
{
|
||||
shader_t *shader = R_RegisterShaderNoMip( pic );
|
||||
shader_t *shader = R_RegisterShaderNoMip(va( "gfx/%s", pic ));
|
||||
*w = (int)shader->stages[0]->bundles[0]->textures[0]->width;
|
||||
*h = (int)shader->stages[0]->bundles[0]->textures[0]->height;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ void R_DrawStretchRaw( int x, int y, int w, int h, int rawWidth, int rawHeight,
|
|||
int width = 1, height = 1;
|
||||
|
||||
// Make sure everything is flushed if needed
|
||||
if( !dirty ) RB_RenderMesh();
|
||||
// if( !dirty ) RB_RenderMesh();
|
||||
|
||||
// Check the dimensions
|
||||
while( width < rawWidth ) width <<= 1;
|
||||
|
|
1411
render/r_light.c
1411
render/r_light.c
File diff suppressed because it is too large
Load Diff
1255
render/r_local.h
1255
render/r_local.h
File diff suppressed because it is too large
Load Diff
2008
render/r_main.c
2008
render/r_main.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,171 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// r_meshbuffer.h - configurable mesh buffer
|
||||
//=======================================================================
|
||||
|
||||
#ifndef R_MESHBUFFER_H
|
||||
#define R_MESHBUFFER_H
|
||||
|
||||
static _inline void R_PushElems( uint *elems, int count, int features )
|
||||
{
|
||||
uint *currentElem;
|
||||
|
||||
// this is a fast path for non-batched geometry, use carefully
|
||||
// used on pics, sprites, and studio models
|
||||
if( features & MF_NONBATCHED )
|
||||
{
|
||||
// simply change elemsArray to point at elems
|
||||
r_stats.numIndices = count;
|
||||
indexArray = currentElem = elems;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentElem = indexArray + r_stats.numIndices;
|
||||
r_stats.numIndices += count;
|
||||
|
||||
// the following code assumes that R_PushElems is fed with triangles...
|
||||
for(; count > 0; count -= 3, elems += 3, currentElem += 3 )
|
||||
{
|
||||
currentElem[0] = r_stats.numVertices + elems[0];
|
||||
currentElem[1] = r_stats.numVertices + elems[1];
|
||||
currentElem[2] = r_stats.numVertices + elems[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static _inline void R_PushTrifanElems( int numverts )
|
||||
{
|
||||
int count;
|
||||
uint *currentElem;
|
||||
|
||||
currentElem = indexArray + r_stats.numIndices;
|
||||
r_stats.numIndices += numverts + numverts + numverts - 6;
|
||||
|
||||
for( count = 2; count < numverts; count++, currentElem += 3 )
|
||||
{
|
||||
currentElem[0] = r_stats.numVertices;
|
||||
currentElem[1] = r_stats.numVertices + count - 1;
|
||||
currentElem[2] = r_stats.numVertices + count;
|
||||
}
|
||||
}
|
||||
|
||||
_inline static void R_PushMesh( const rb_mesh_t *mesh, int features )
|
||||
{
|
||||
int numverts;
|
||||
|
||||
if(!( mesh->indexes || ( features & MF_TRIFAN )) || !mesh->points )
|
||||
return;
|
||||
|
||||
r_features = features;
|
||||
|
||||
if( features & MF_TRIFAN )
|
||||
R_PushTrifanElems( mesh->numVerts );
|
||||
else R_PushElems( mesh->indexes, mesh->numIndexes, features );
|
||||
|
||||
numverts = mesh->numVerts;
|
||||
|
||||
if( features & MF_NONBATCHED )
|
||||
{
|
||||
if( features & MF_DEFORMVS )
|
||||
{
|
||||
if( mesh->points != inVertsArray )
|
||||
Mem_Copy( inVertsArray, mesh->points, numverts * sizeof( vec4_t ));
|
||||
|
||||
if( ( features & MF_NORMALS ) && mesh->normal && ( mesh->normal != inNormalArray ))
|
||||
Mem_Copy( inNormalArray, mesh->normal, numverts * sizeof( vec4_t ));
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexArray = mesh->points;
|
||||
|
||||
if(( features & MF_NORMALS ) && mesh->normal )
|
||||
normalArray = mesh->normal;
|
||||
}
|
||||
|
||||
if(( features & MF_STCOORDS ) && mesh->st )
|
||||
texCoordArray = mesh->st;
|
||||
|
||||
if( ( features & MF_LMCOORDS ) && mesh->lm[0] )
|
||||
{
|
||||
lmCoordArray[0] = mesh->lm[0];
|
||||
if( features & MF_LMCOORDS1 )
|
||||
{
|
||||
lmCoordArray[1] = mesh->lm[1];
|
||||
if( features & MF_LMCOORDS2 )
|
||||
{
|
||||
lmCoordArray[2] = mesh->lm[2];
|
||||
if( features & MF_LMCOORDS3 )
|
||||
lmCoordArray[3] = mesh->lm[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ( features & MF_SVECTORS ) && mesh->sVectors )
|
||||
sVectorArray = mesh->sVectors;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mesh->points != inVertsArray )
|
||||
Mem_Copy( inVertsArray[r_stats.numVertices], mesh->points, numverts * sizeof( vec4_t ));
|
||||
|
||||
if(( features & MF_NORMALS ) && mesh->normal && (mesh->normal != inNormalArray ))
|
||||
Mem_Copy( inNormalArray[r_stats.numVertices], mesh->normal, numverts * sizeof( vec4_t ));
|
||||
|
||||
if(( features & MF_STCOORDS ) && mesh->st && (mesh->st != inTexCoordArray ))
|
||||
Mem_Copy( inTexCoordArray[r_stats.numVertices], mesh->st, numverts * sizeof( vec2_t ));
|
||||
|
||||
if(( features & MF_LMCOORDS ) && mesh->lm[0] )
|
||||
{
|
||||
Mem_Copy( inLMCoordsArray[0][r_stats.numVertices], mesh->lm[0], numverts * sizeof( vec2_t ));
|
||||
if( features & MF_LMCOORDS1 )
|
||||
{
|
||||
memcpy( inLMCoordsArray[1][r_stats.numVertices], mesh->lm[1], numverts * sizeof( vec2_t ));
|
||||
if( features & MF_LMCOORDS2 )
|
||||
{
|
||||
Mem_Copy( inLMCoordsArray[2][r_stats.numVertices], mesh->lm[2], numverts * sizeof( vec2_t ));
|
||||
if( features & MF_LMCOORDS3 )
|
||||
Mem_Copy( inLMCoordsArray[3][r_stats.numVertices], mesh->lm[3], numverts * sizeof( vec2_t ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(( features & MF_SVECTORS ) && mesh->sVectors && (mesh->sVectors != inSVectorsArray ))
|
||||
Mem_Copy( inSVectorsArray[r_stats.numVertices], mesh->sVectors, numverts * sizeof( vec4_t ));
|
||||
}
|
||||
|
||||
if(( features & MF_COLORS ) && mesh->color[0] )
|
||||
{
|
||||
Mem_Copy( inColorArray[0][r_stats.numVertices], mesh->color[0], numverts * sizeof( vec4_t ));
|
||||
if( features & MF_COLORS1 )
|
||||
{
|
||||
Mem_Copy( inColorArray[1][r_stats.numVertices], mesh->color[1], numverts * sizeof( vec4_t ));
|
||||
if( features & MF_COLORS2 )
|
||||
{
|
||||
Mem_Copy( inColorArray[2][r_stats.numVertices], mesh->color[2], numverts * sizeof( vec4_t ));
|
||||
if( features & MF_COLORS3 )
|
||||
Mem_Copy( inColorArray[3][r_stats.numVertices], mesh->color[3], numverts * sizeof( vec4_t ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_stats.numVertices += numverts;
|
||||
r_stats.totalVerts += numverts;
|
||||
}
|
||||
|
||||
static _inline bool R_MeshOverflow( const rb_mesh_t *mesh )
|
||||
{
|
||||
return ( r_stats.numVertices + mesh->numVerts > MAX_ARRAY_VERTS || r_stats.numIndices + mesh->numIndexes > MAX_ARRAY_ELEMENTS );
|
||||
}
|
||||
|
||||
static _inline bool R_MeshOverflow2( const rb_mesh_t *mesh1, const rb_mesh_t *mesh2 )
|
||||
{
|
||||
return ( r_stats.numVertices + mesh1->numVerts + mesh2->numVerts > MAX_ARRAY_VERTS ||
|
||||
r_stats.numIndices + mesh1->numIndexes + mesh2->numIndexes > MAX_ARRAY_ELEMENTS );
|
||||
}
|
||||
|
||||
static _inline bool R_InvalidMesh( const rb_mesh_t *mesh )
|
||||
{
|
||||
return ( !mesh->numVerts || !mesh->numIndexes || mesh->numVerts > MAX_ARRAY_VERTS || mesh->numIndexes > MAX_ARRAY_ELEMENTS );
|
||||
}
|
||||
|
||||
#endif//R_MESHBUFFER_H
|
1788
render/r_model.c
1788
render/r_model.c
File diff suppressed because it is too large
Load Diff
|
@ -45,6 +45,8 @@ typedef uint GLhandleARB;
|
|||
#define GL_DEPTH_TEST 0x0B71
|
||||
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_CW 0x0900
|
||||
#define GL_CCW 0x0901
|
||||
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_ALPHA_TEST 0x0BC0
|
||||
|
@ -169,6 +171,9 @@ extern int gl_max_anisotropy;
|
|||
#define GL_OUT_OF_MEMORY 0x0505
|
||||
|
||||
#define GL_DITHER 0x0BD0
|
||||
#define GL_COLOR_INDEX 0x1900
|
||||
#define GL_STENCIL_INDEX 0x1901
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_ALPHA4 0x803B
|
||||
|
@ -386,6 +391,12 @@ extern int gl_max_anisotropy;
|
|||
#define GL_MAX_EXT 0x8008
|
||||
#define GL_BLEND_EQUATION_EXT 0x8009
|
||||
|
||||
#define GL_QUERY_COUNTER_BITS_ARB 0x8864
|
||||
#define GL_CURRENT_QUERY_ARB 0x8865
|
||||
#define GL_QUERY_RESULT_ARB 0x8866
|
||||
#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
|
||||
#define GL_SAMPLES_PASSED_ARB 0x8914
|
||||
|
||||
#define GL_VERTEX_SHADER_ARB 0x8B31
|
||||
#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
|
||||
#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
|
||||
|
@ -578,7 +589,11 @@ extern int gl_max_anisotropy;
|
|||
#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
|
||||
#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
|
||||
|
||||
#define GL_FRAGMENT_SHADER_ARB 0x8B30
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
|
||||
#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
|
||||
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
|
||||
|
||||
// helper opengl functions
|
||||
GLenum ( APIENTRY *pglGetError )(void);
|
||||
|
@ -985,9 +1000,17 @@ void ( APIENTRY *pglGetUniformfvARB)(GLhandleARB programObj, GLint location, GLf
|
|||
void ( APIENTRY *pglGetUniformivARB)(GLhandleARB programObj, GLint location, GLint *params);
|
||||
void ( APIENTRY *pglGetShaderSourceARB)(GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
|
||||
void ( APIENTRY *pglPolygonStipple)(const GLubyte *mask);
|
||||
void ( APIENTRY *pglTexImage3D)( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
|
||||
void ( APIENTRY *pglTexSubImage3D)( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels );
|
||||
void ( APIENTRY *pglCopyTexSubImage3D)( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
|
||||
void ( APIENTRY *pglTexImage3D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
|
||||
void ( APIENTRY *pglTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels );
|
||||
void ( APIENTRY *pglCopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
|
||||
void ( APIENTRY *pglGenQueriesARB)(GLsizei n, GLuint *ids);
|
||||
void ( APIENTRY *pglDeleteQueriesARB)(GLsizei n, const GLuint *ids);
|
||||
void ( APIENTRY *pglIsQueryARB)(GLuint id);
|
||||
void ( APIENTRY *pglBeginQueryARB)(GLenum target, GLuint id);
|
||||
void ( APIENTRY *pglEndQueryARB)(GLenum target);
|
||||
void ( APIENTRY *pglGetQueryivARB)(GLenum target, GLenum pname, GLint *params);
|
||||
void ( APIENTRY *pglGetQueryObjectivARB)(GLuint id, GLenum pname, GLint *params);
|
||||
void ( APIENTRY *pglGetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint *params);
|
||||
void ( APIENTRY *pglBlendEquationEXT)(GLenum);
|
||||
void ( APIENTRY *pglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum);
|
||||
void ( APIENTRY *pglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint);
|
||||
|
@ -1038,7 +1061,12 @@ BOOL ( WINAPI * pwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned cha
|
|||
BOOL ( WINAPI * pwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue );
|
||||
|
||||
|
||||
extern int GL_TEXTURE0, GL_TEXTURE1;
|
||||
#define GL_TEXTURE0 0
|
||||
#define GL_TEXTURE1 1
|
||||
#define GL_TEXTURE2 2
|
||||
#define GL_TEXTURE3 3
|
||||
#define GL_TEXTURE4 4
|
||||
#define GL_TEXTURE5 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -0,0 +1,777 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2008 ©
|
||||
// r_poly.c - handles fragments and arbitrary polygons
|
||||
//=======================================================================
|
||||
|
||||
#include "r_local.h"
|
||||
#include "r_meshbuffer.h"
|
||||
#include "mathlib.h"
|
||||
#include "matrixlib.h"
|
||||
#include "const.h"
|
||||
|
||||
static rb_mesh_t poly_mesh;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PushPoly
|
||||
=================
|
||||
*/
|
||||
void R_PushPoly( const meshbuffer_t *mb )
|
||||
{
|
||||
int i, j;
|
||||
poly_t *p;
|
||||
shader_t *shader;
|
||||
int features;
|
||||
|
||||
R_SHADER_FOR_KEY( mb->shaderKey, shader );
|
||||
|
||||
features = shader->features|MF_TRIFAN;
|
||||
|
||||
for( i = -mb->infoKey-1, p = r_polys + i; i < mb->lastPoly; i++, p++ )
|
||||
{
|
||||
poly_mesh.numVerts = p->numverts;
|
||||
poly_mesh.points = inVertsArray;
|
||||
poly_mesh.normal = inNormalArray;
|
||||
poly_mesh.st = p->st;
|
||||
poly_mesh.color[0] = p->colors;
|
||||
for( j = 0; j < p->numverts; j++ )
|
||||
{
|
||||
Vector4Set( inVertsArray[r_stats.numVertices+j], p->verts[j][0], p->verts[j][1], p->verts[j][2], 1 );
|
||||
VectorCopy( p->normal, inNormalArray[r_stats.numVertices+j] );
|
||||
}
|
||||
R_PushMesh( &poly_mesh, features );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AddPolysToList
|
||||
=================
|
||||
*/
|
||||
void R_AddPolysToList( void )
|
||||
{
|
||||
uint i, nverts = 0;
|
||||
int fognum = -1;
|
||||
poly_t *p;
|
||||
mfog_t *fog, *lastFog = NULL;
|
||||
meshbuffer_t *mb = NULL;
|
||||
shader_t *shader;
|
||||
vec3_t lastNormal = { 0, 0, 0 };
|
||||
|
||||
Ref.m_pCurrentEntity = r_worldEntity;
|
||||
for( i = 0, p = r_polys; i < r_numPolys; nverts += p->numverts, mb->lastPoly++, i++, p++ )
|
||||
{
|
||||
shader = p->shader;
|
||||
if( p->fognum < 0 )
|
||||
fognum = -1;
|
||||
else if( p->fognum )
|
||||
fognum = bound( 1, p->fognum, r_worldBrushModel->numFogs + 1 );
|
||||
else
|
||||
fognum = r_worldBrushModel->numFogs ? 0 : -1;
|
||||
|
||||
if( fognum == -1 ) fog = NULL;
|
||||
else if( !fognum ) fog = R_FogForSphere( p->verts[0], 0 );
|
||||
else fog = r_worldBrushModel->fogs + fognum - 1;
|
||||
|
||||
// we ignore SHADER_ENTITY_MERGABLE here because polys are just regular trifans
|
||||
if( !mb || mb->shaderKey != (int)shader->sortKey || lastFog != fog || nverts + p->numverts > MAX_ARRAY_VERTS
|
||||
|| (( shader->flags & SHADER_MATERIAL ) && !VectorCompare( p->normal, lastNormal )))
|
||||
{
|
||||
nverts = 0;
|
||||
lastFog = fog;
|
||||
VectorCopy( p->normal, lastNormal );
|
||||
|
||||
mb = R_AddMeshToList( MESH_POLY, fog, shader, -( (signed int)i + 1 ));
|
||||
mb->lastPoly = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
|
||||
static int numFragmentVerts;
|
||||
static int maxFragmentVerts;
|
||||
static vec3_t *fragmentVerts;
|
||||
|
||||
static int numClippedFragments;
|
||||
static int maxClippedFragments;
|
||||
static fragment_t *clippedFragments;
|
||||
|
||||
static cplane_t fragmentPlanes[6];
|
||||
static vec3_t fragmentOrigin;
|
||||
static vec3_t fragmentNormal;
|
||||
static float fragmentRadius;
|
||||
static float fragmentDiameterSquared;
|
||||
|
||||
static int r_fragmentframecount;
|
||||
|
||||
#define MAX_FRAGMENT_VERTS 64
|
||||
|
||||
/*
|
||||
=================
|
||||
R_WindingClipFragment
|
||||
|
||||
This function operates on windings (convex polygons without
|
||||
any points inside) like triangles, quads, etc. The output is
|
||||
a convex fragment (polygon, trifan) which the result of clipping
|
||||
the input winding by six fragment planes.
|
||||
=================
|
||||
*/
|
||||
static bool R_WindingClipFragment( vec3_t *wVerts, int numVerts, msurface_t *surf, vec3_t snorm )
|
||||
{
|
||||
int i, j;
|
||||
int stage, newc, numv;
|
||||
cplane_t *plane;
|
||||
bool front;
|
||||
float *v, *nextv, d;
|
||||
float dists[MAX_FRAGMENT_VERTS+1];
|
||||
int sides[MAX_FRAGMENT_VERTS+1];
|
||||
vec3_t *verts, *newverts, newv[2][MAX_FRAGMENT_VERTS], t;
|
||||
fragment_t *fr;
|
||||
|
||||
numv = numVerts;
|
||||
verts = wVerts;
|
||||
|
||||
for( stage = 0, plane = fragmentPlanes; stage < 6; stage++, plane++ )
|
||||
{
|
||||
for( i = 0, v = verts[0], front = false; i < numv; i++, v += 3 )
|
||||
{
|
||||
d = PlaneDiff( v, plane );
|
||||
|
||||
if( d > ON_EPSILON )
|
||||
{
|
||||
front = true;
|
||||
sides[i] = SIDE_FRONT;
|
||||
}
|
||||
else if( d < -ON_EPSILON )
|
||||
{
|
||||
sides[i] = SIDE_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = true;
|
||||
sides[i] = SIDE_ON;
|
||||
}
|
||||
dists[i] = d;
|
||||
}
|
||||
|
||||
if( !front ) return false;
|
||||
|
||||
// clip it
|
||||
sides[i] = sides[0];
|
||||
dists[i] = dists[0];
|
||||
|
||||
newc = 0;
|
||||
newverts = newv[stage & 1];
|
||||
for( i = 0, v = verts[0]; i < numv; i++, v += 3 )
|
||||
{
|
||||
switch( sides[i] )
|
||||
{
|
||||
case SIDE_FRONT:
|
||||
if( newc == MAX_FRAGMENT_VERTS )
|
||||
return false;
|
||||
VectorCopy( v, newverts[newc] );
|
||||
newc++;
|
||||
break;
|
||||
case SIDE_BACK:
|
||||
break;
|
||||
case SIDE_ON:
|
||||
if( newc == MAX_FRAGMENT_VERTS )
|
||||
return false;
|
||||
VectorCopy( v, newverts[newc] );
|
||||
newc++;
|
||||
break;
|
||||
}
|
||||
|
||||
if( sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i] )
|
||||
continue;
|
||||
if( newc == MAX_FRAGMENT_VERTS )
|
||||
return false;
|
||||
|
||||
d = dists[i] / ( dists[i] - dists[i+1] );
|
||||
nextv = ( i == numv - 1 ) ? verts[0] : v + 3;
|
||||
for( j = 0; j < 3; j++ )
|
||||
newverts[newc][j] = v[j] + d * ( nextv[j] - v[j] );
|
||||
newc++;
|
||||
}
|
||||
|
||||
if( newc <= 2 )
|
||||
return false;
|
||||
|
||||
// continue with new verts
|
||||
numv = newc;
|
||||
verts = newverts;
|
||||
}
|
||||
|
||||
// fully clipped
|
||||
if( numFragmentVerts + numv > maxFragmentVerts )
|
||||
return false;
|
||||
|
||||
fr = &clippedFragments[numClippedFragments++];
|
||||
fr->numVerts = numv;
|
||||
fr->firstVert = numFragmentVerts;
|
||||
fr->fogNum = surf->fog ? surf->fog - r_worldBrushModel->fogs + 1 : -1;
|
||||
VectorCopy( snorm, fr->normal );
|
||||
for( i = 0, v = verts[0], nextv = fragmentVerts[numFragmentVerts]; i < numv; i++, v += 3, nextv += 3 )
|
||||
VectorCopy( v, nextv );
|
||||
|
||||
numFragmentVerts += numv;
|
||||
if( numFragmentVerts == maxFragmentVerts && numClippedFragments == maxClippedFragments )
|
||||
return true;
|
||||
|
||||
// if all of the following is true:
|
||||
// a) all clipping planes are perpendicular
|
||||
// b) there are 4 in a clipped fragment
|
||||
// c) all sides of the fragment are equal (it is a quad)
|
||||
// d) all sides are radius*2 +- epsilon (0.001)
|
||||
// then it is safe to assume there's only one fragment possible
|
||||
// not sure if it's 100% correct, but sounds convincing
|
||||
if( numv == 4 )
|
||||
{
|
||||
for( i = 0, v = verts[0]; i < numv; i++, v += 3 )
|
||||
{
|
||||
nextv = ( i == 3 ) ? verts[0] : v + 3;
|
||||
VectorSubtract( v, nextv, t );
|
||||
|
||||
d = fragmentDiameterSquared - DotProduct( t, t );
|
||||
if( d > 0.01 || d < -0.01 )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PlanarSurfClipFragment
|
||||
|
||||
NOTE: one might want to combine this function with
|
||||
R_WindingClipFragment for special cases like trifans (q1 and
|
||||
q2 polys) or tristrips for ultra-fast clipping, providing there's
|
||||
enough stack space (depending on MAX_FRAGMENT_VERTS value).
|
||||
=================
|
||||
*/
|
||||
static bool R_PlanarSurfClipFragment( msurface_t *surf, vec3_t normal )
|
||||
{
|
||||
int i;
|
||||
rb_mesh_t *mesh;
|
||||
uint *elem;
|
||||
vec4_t *verts;
|
||||
vec3_t poly[4];
|
||||
vec3_t dir1, dir2, snorm;
|
||||
bool planar;
|
||||
|
||||
planar = surf->plane && !VectorCompare( surf->plane->normal, vec3_origin );
|
||||
if( planar )
|
||||
{
|
||||
VectorCopy( surf->plane->normal, snorm );
|
||||
if( DotProduct( normal, snorm ) < 0.5 )
|
||||
return false; // greater than 60 degrees
|
||||
}
|
||||
|
||||
mesh = surf->mesh;
|
||||
elem = mesh->indexes;
|
||||
verts = mesh->points;
|
||||
|
||||
// clip each triangle individually
|
||||
for( i = 0; i < mesh->numIndexes; i += 3, elem += 3 )
|
||||
{
|
||||
VectorCopy( verts[elem[0]], poly[0] );
|
||||
VectorCopy( verts[elem[1]], poly[1] );
|
||||
VectorCopy( verts[elem[2]], poly[2] );
|
||||
|
||||
if( !planar )
|
||||
{
|
||||
// calculate two mostly perpendicular edge directions
|
||||
VectorSubtract( poly[0], poly[1], dir1 );
|
||||
VectorSubtract( poly[2], poly[1], dir2 );
|
||||
|
||||
// we have two edge directions, we can calculate a third vector from
|
||||
// them, which is the direction of the triangle normal
|
||||
CrossProduct( dir1, dir2, snorm );
|
||||
VectorNormalize( snorm );
|
||||
|
||||
// we multiply 0.5 by length of snorm to avoid normalizing
|
||||
if( DotProduct( normal, snorm ) < 0.5f )
|
||||
continue; // greater than 60 degrees
|
||||
}
|
||||
|
||||
if( R_WindingClipFragment( poly, 3, surf, snorm ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PatchSurfClipFragment
|
||||
=================
|
||||
*/
|
||||
static bool R_PatchSurfClipFragment( msurface_t *surf, vec3_t normal )
|
||||
{
|
||||
int i, j;
|
||||
rb_mesh_t *mesh;
|
||||
uint *elem;
|
||||
vec4_t *verts;
|
||||
vec3_t poly[3];
|
||||
vec3_t dir1, dir2, snorm;
|
||||
|
||||
mesh = surf->mesh;
|
||||
elem = mesh->indexes;
|
||||
verts = mesh->points;
|
||||
|
||||
// clip each triangle individually
|
||||
for( i = j = 0; i < mesh->numIndexes; i += 6, elem += 6, j = 0 )
|
||||
{
|
||||
VectorCopy( verts[elem[1]], poly[1] );
|
||||
|
||||
if( !j )
|
||||
{
|
||||
VectorCopy( verts[elem[0]], poly[0] );
|
||||
VectorCopy( verts[elem[2]], poly[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
tri2:
|
||||
j++;
|
||||
VectorCopy( poly[2], poly[0] );
|
||||
VectorCopy( verts[elem[5]], poly[2] );
|
||||
}
|
||||
|
||||
// calculate two mostly perpendicular edge directions
|
||||
VectorSubtract( poly[0], poly[1], dir1 );
|
||||
VectorSubtract( poly[2], poly[1], dir2 );
|
||||
|
||||
// we have two edge directions, we can calculate a third vector from
|
||||
// them, which is the direction of the triangle normal
|
||||
CrossProduct( dir1, dir2, snorm );
|
||||
VectorNormalize( snorm );
|
||||
|
||||
// we multiply 0.5 by length of snorm to avoid normalizing
|
||||
if( DotProduct( normal, snorm ) < 0.5 )
|
||||
continue; // greater than 60 degrees
|
||||
|
||||
if( R_WindingClipFragment( poly, 3, surf, snorm ) )
|
||||
return true;
|
||||
|
||||
if( !j ) goto tri2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SurfPotentiallyFragmented
|
||||
=================
|
||||
*/
|
||||
bool R_SurfPotentiallyFragmented( msurface_t *surf )
|
||||
{
|
||||
if( surf->flags & ( SURF_NOMARKS|SURF_NOIMPACT|SURF_NODRAW ))
|
||||
return false;
|
||||
return (( surf->faceType == MST_PLANAR ) || ( surf->faceType == MST_PATCH ));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveFragmentNode
|
||||
=================
|
||||
*/
|
||||
static void R_RecursiveFragmentNode( void )
|
||||
{
|
||||
int stackdepth = 0;
|
||||
float dist;
|
||||
bool inside;
|
||||
mnode_t *node, *localstack[2048];
|
||||
mleaf_t *leaf;
|
||||
msurface_t *surf, **mark;
|
||||
|
||||
for( node = r_worldBrushModel->nodes, stackdepth = 0;; )
|
||||
{
|
||||
if( node->plane == NULL )
|
||||
{
|
||||
leaf = (mleaf_t *)node;
|
||||
mark = leaf->firstFragmentSurface;
|
||||
if( !mark ) goto nextNodeOnStack;
|
||||
|
||||
do
|
||||
{
|
||||
if( numFragmentVerts == maxFragmentVerts || numClippedFragments == maxClippedFragments )
|
||||
return; // already reached the limit
|
||||
|
||||
surf = *mark++;
|
||||
if( surf->fragmentframe == r_fragmentframecount )
|
||||
continue;
|
||||
surf->fragmentframe = r_fragmentframecount;
|
||||
|
||||
if( !BoundsAndSphereIntersect( surf->mins, surf->maxs, fragmentOrigin, fragmentRadius ) )
|
||||
continue;
|
||||
|
||||
if( surf->faceType == MST_PATCH )
|
||||
inside = R_PatchSurfClipFragment( surf, fragmentNormal );
|
||||
else inside = R_PlanarSurfClipFragment( surf, fragmentNormal );
|
||||
|
||||
if( inside ) return;
|
||||
} while( *mark );
|
||||
|
||||
if( numFragmentVerts == maxFragmentVerts || numClippedFragments == maxClippedFragments )
|
||||
return; // already reached the limit
|
||||
|
||||
nextNodeOnStack:
|
||||
if( !stackdepth ) break;
|
||||
node = localstack[--stackdepth];
|
||||
continue;
|
||||
}
|
||||
|
||||
dist = PlaneDiff( fragmentOrigin, node->plane );
|
||||
if( dist > fragmentRadius )
|
||||
{
|
||||
node = node->children[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ( dist >= -fragmentRadius ) && ( stackdepth < sizeof( localstack )/sizeof( mnode_t * )))
|
||||
localstack[stackdepth++] = node->children[0];
|
||||
node = node->children[1];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_GetClippedFragments
|
||||
=================
|
||||
*/
|
||||
int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts, int maxfragments, fragment_t *fragments )
|
||||
{
|
||||
int i;
|
||||
float d;
|
||||
|
||||
r_fragmentframecount++;
|
||||
|
||||
// initialize fragments
|
||||
numFragmentVerts = 0;
|
||||
maxFragmentVerts = maxfverts;
|
||||
fragmentVerts = fverts;
|
||||
|
||||
numClippedFragments = 0;
|
||||
maxClippedFragments = maxfragments;
|
||||
clippedFragments = fragments;
|
||||
|
||||
VectorCopy( origin, fragmentOrigin );
|
||||
VectorCopy( axis[0], fragmentNormal );
|
||||
fragmentRadius = radius;
|
||||
fragmentDiameterSquared = radius * radius * 4;
|
||||
|
||||
// calculate clipping planes
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
d = DotProduct( origin, axis[i] );
|
||||
|
||||
VectorCopy( axis[i], fragmentPlanes[i*2].normal );
|
||||
fragmentPlanes[i*2].dist = d - radius;
|
||||
PlaneClassify( &fragmentPlanes[i*2] );
|
||||
|
||||
VectorNegate( axis[i], fragmentPlanes[i*2+1].normal );
|
||||
fragmentPlanes[i*2+1].dist = -d - radius;
|
||||
PlaneClassify( &fragmentPlanes[i*2+1] );
|
||||
}
|
||||
R_RecursiveFragmentNode();
|
||||
|
||||
return numClippedFragments;
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
|
||||
static int trace_umask;
|
||||
static vec3_t trace_start, trace_end;
|
||||
static vec3_t trace_absmins, trace_absmaxs;
|
||||
static float trace_fraction;
|
||||
|
||||
static vec3_t trace_impact;
|
||||
static cplane_t trace_plane;
|
||||
static msurface_t *trace_surface;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_TraceAgainstTriangle
|
||||
|
||||
Ray-triangle intersection as per
|
||||
http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm
|
||||
(original paper by Dan Sunday)
|
||||
=================
|
||||
*/
|
||||
static void R_TraceAgainstTriangle( const vec_t *a, const vec_t *b, const vec_t *c )
|
||||
{
|
||||
const vec_t *p1 = trace_start, *p2 = trace_end, *p0 = a;
|
||||
vec3_t u, v, w, n, p;
|
||||
float d1, d2, d, frac;
|
||||
float uu, uv, vv, wu, wv, s, t;
|
||||
|
||||
// calculate two mostly perpendicular edge directions
|
||||
VectorSubtract( b, p0, u );
|
||||
VectorSubtract( c, p0, v );
|
||||
|
||||
// we have two edge directions, we can calculate the normal
|
||||
CrossProduct( v, u, n );
|
||||
if( VectorIsNull( n )) return; // degenerate triangle
|
||||
|
||||
VectorSubtract( p2, p1, p );
|
||||
VectorSubtract( p1, p0, w );
|
||||
|
||||
d1 = -DotProduct( n, w );
|
||||
d2 = DotProduct( n, p );
|
||||
if( fabs( d2 ) < 0.0001f )
|
||||
return;
|
||||
|
||||
// get intersect point of ray with triangle plane
|
||||
frac = (d1) / d2;
|
||||
if( frac <= 0 ) return;
|
||||
if( frac >= trace_fraction ) return; // we have hit something earlier
|
||||
|
||||
// calculate the impact point
|
||||
VectorLerp( p1, frac, p2, p );
|
||||
|
||||
// does p lie inside triangle?
|
||||
uu = DotProduct( u, u );
|
||||
uv = DotProduct( u, v );
|
||||
vv = DotProduct( v, v );
|
||||
|
||||
VectorSubtract( p, p0, w );
|
||||
wu = DotProduct( w, u );
|
||||
wv = DotProduct( w, v );
|
||||
d = uv * uv - uu * vv;
|
||||
|
||||
// get and test parametric coords
|
||||
s = (uv * wv - vv * wu) / d;
|
||||
if( s < 0.0 || s > 1.0 )
|
||||
return; // p is outside
|
||||
|
||||
t = (uv * wu - uu * wv) / d;
|
||||
if( t < 0.0 || (s + t) > 1.0 )
|
||||
return; // p is outside
|
||||
|
||||
trace_fraction = frac;
|
||||
VectorCopy( p, trace_impact );
|
||||
VectorCopy( n, trace_plane.normal );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_TraceAgainstSurface
|
||||
=================
|
||||
*/
|
||||
static bool R_TraceAgainstSurface( msurface_t *surf )
|
||||
{
|
||||
int i;
|
||||
rb_mesh_t *mesh = surf->mesh;
|
||||
uint *elem = mesh->indexes;
|
||||
vec4_t *verts = mesh->points;
|
||||
float old_frac = trace_fraction;
|
||||
|
||||
// clip each triangle individually
|
||||
for( i = 0; i < mesh->numIndexes; i += 3, elem += 3 )
|
||||
{
|
||||
R_TraceAgainstTriangle( verts[elem[0]], verts[elem[1]], verts[elem[2]] );
|
||||
if( old_frac > trace_fraction )
|
||||
{
|
||||
// flip normal is we are on the backside (does it really happen?)...
|
||||
if( surf->faceType == MST_PLANAR )
|
||||
{
|
||||
if( DotProduct( trace_plane.normal, surf->plane->normal ) < 0 )
|
||||
VectorNegate( trace_plane.normal, trace_plane.normal );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_TraceAgainstLeaf
|
||||
=================
|
||||
*/
|
||||
static int R_TraceAgainstLeaf( mleaf_t *leaf )
|
||||
{
|
||||
msurface_t *surf, **mark;
|
||||
|
||||
if( leaf->cluster == -1 )
|
||||
return 1; // solid leaf
|
||||
|
||||
mark = leaf->firstVisSurface;
|
||||
if( mark )
|
||||
{
|
||||
do
|
||||
{
|
||||
surf = *mark++;
|
||||
if( surf->fragmentframe == r_fragmentframecount )
|
||||
continue; // do not test the same surface more than once
|
||||
surf->fragmentframe = r_fragmentframecount;
|
||||
|
||||
if( surf->flags & trace_umask ) continue;
|
||||
|
||||
if( surf->mesh )
|
||||
{
|
||||
if( R_TraceAgainstSurface( surf ))
|
||||
trace_surface = surf; // impact surface
|
||||
}
|
||||
} while( *mark );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_TraceAgainstBmodel
|
||||
=================
|
||||
*/
|
||||
static int R_TraceAgainstBmodel( mbrushmodel_t *bmodel )
|
||||
{
|
||||
int i;
|
||||
msurface_t *surf;
|
||||
|
||||
for( i = 0; i < bmodel->numModelSurfaces; i++ )
|
||||
{
|
||||
surf = bmodel->firstModelSurface + i;
|
||||
if( surf->flags & trace_umask ) continue;
|
||||
|
||||
if( R_TraceAgainstSurface( surf ))
|
||||
trace_surface = surf; // impact point
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveHullCheck
|
||||
=================
|
||||
*/
|
||||
static int R_RecursiveHullCheck( mnode_t *node, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
int side, r;
|
||||
float t1, t2;
|
||||
float frac;
|
||||
vec3_t mid;
|
||||
const vec_t *p1 = start, *p2 = end;
|
||||
cplane_t *plane;
|
||||
|
||||
loc0:
|
||||
plane = node->plane;
|
||||
if( !plane ) return R_TraceAgainstLeaf((mleaf_t *)node );
|
||||
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
t1 = p1[plane->type] - plane->dist;
|
||||
t2 = p2[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
|
||||
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
|
||||
}
|
||||
|
||||
if( t1 >= -ON_EPSILON && t2 >= -ON_EPSILON )
|
||||
{
|
||||
node = node->children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( t1 < ON_EPSILON && t2 < ON_EPSILON )
|
||||
{
|
||||
node = node->children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
side = t1 < 0;
|
||||
frac = t1 / (t1 - t2);
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
r = R_RecursiveHullCheck( node->children[side], p1, mid );
|
||||
if( r ) return r;
|
||||
|
||||
return R_RecursiveHullCheck( node->children[!side], mid, p2 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_TraceLine
|
||||
=================
|
||||
*/
|
||||
msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int surfumask )
|
||||
{
|
||||
rmodel_t *model;
|
||||
|
||||
// fill in a default trace
|
||||
Mem_Set( tr, 0, sizeof( trace_t ));
|
||||
r_fragmentframecount++; // for multi-check avoidance
|
||||
|
||||
trace_surface = NULL;
|
||||
trace_umask = surfumask;
|
||||
trace_fraction = 1;
|
||||
VectorCopy( end, trace_impact );
|
||||
Mem_Set( &trace_plane, 0, sizeof( trace_plane ));
|
||||
|
||||
ClearBounds( trace_absmins, trace_absmaxs );
|
||||
AddPointToBounds( start, trace_absmins, trace_absmaxs );
|
||||
AddPointToBounds( end, trace_absmins, trace_absmaxs );
|
||||
|
||||
model = test->model;
|
||||
if( model )
|
||||
{
|
||||
if( model->type == mod_brush || model->type == mod_world )
|
||||
{
|
||||
mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata;
|
||||
vec3_t temp, start_l, end_l;
|
||||
bool rotated = !Matrix3x3_Compare( test->matrix, matrix3x3_identity );
|
||||
matrix3x3 matrix;
|
||||
|
||||
// transform
|
||||
VectorSubtract( start, test->origin, start_l );
|
||||
VectorSubtract( end, test->origin, end_l );
|
||||
if( rotated )
|
||||
{
|
||||
VectorCopy( start_l, temp );
|
||||
Matrix3x3_Transform( test->matrix, temp, start_l );
|
||||
VectorCopy( end_l, temp );
|
||||
Matrix3x3_Transform( test->matrix, temp, end_l );
|
||||
}
|
||||
|
||||
VectorCopy( start_l, trace_start );
|
||||
VectorCopy( end_l, trace_end );
|
||||
|
||||
// world uses a recursive approach using BSP tree, submodels
|
||||
// just walk the list of surfaces linearly
|
||||
if( model->type == mod_world )
|
||||
R_RecursiveHullCheck( bmodel->nodes, start_l, end_l );
|
||||
else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ))
|
||||
R_TraceAgainstBmodel( bmodel );
|
||||
|
||||
// transform back
|
||||
if( rotated && trace_fraction != 1 )
|
||||
{
|
||||
Matrix3x3_Transpose( test->matrix, matrix );
|
||||
VectorCopy( tr->plane.normal, temp );
|
||||
Matrix3x3_Transform( matrix, temp, trace_plane.normal );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the impact plane, if any
|
||||
if( trace_fraction < 1 )
|
||||
{
|
||||
VectorNormalize( trace_plane.normal );
|
||||
trace_plane.dist = DotProduct( trace_plane.normal, trace_impact );
|
||||
PlaneClassify( &trace_plane );
|
||||
|
||||
tr->plane = trace_plane;
|
||||
tr->surfaceflags = trace_surface->flags;
|
||||
tr->ent = (edict_t *)test;
|
||||
}
|
||||
|
||||
tr->fraction = trace_fraction;
|
||||
VectorCopy( trace_impact, tr->endpos );
|
||||
|
||||
return trace_surface;
|
||||
}
|
1210
render/r_program.c
1210
render/r_program.c
File diff suppressed because it is too large
Load Diff
|
@ -4,9 +4,13 @@
|
|||
//=======================================================================
|
||||
|
||||
#include "r_local.h"
|
||||
#include "mathlib.h"
|
||||
#include "const.h"
|
||||
|
||||
#define SHADERS_HASHSIZE 256
|
||||
#define Shader_Malloc( size ) Mem_Alloc( r_shaderpool, size )
|
||||
#define Shader_Free( data ) Mem_Free( data )
|
||||
#define Shader_Sortkey( shader, sort ) ((( sort )<<26 )|((shader)->shaderNum))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -34,8 +38,13 @@ static shader_t *r_shadersHash[SHADERS_HASHSIZE];
|
|||
static texture_t *r_internalMiptex;
|
||||
|
||||
shader_t *r_shaders[MAX_SHADERS];
|
||||
skydome_t *r_skydomes[MAX_SHADERS];
|
||||
int r_numShaders = 0;
|
||||
byte *r_shaderpool;
|
||||
static bool r_shaderNoMipMaps;
|
||||
static bool r_shaderNoPicMip;
|
||||
static bool r_shaderNoCompress;
|
||||
static bool r_shaderHasDlightPass;
|
||||
|
||||
// builtin shaders
|
||||
shader_t *r_defaultShader;
|
||||
|
@ -190,7 +199,7 @@ static bool R_ParseGeneralSurfaceParm( shader_t *shader, char **script )
|
|||
|
||||
switch( shader->shaderType )
|
||||
{
|
||||
case SHADER_TEXTURE:
|
||||
case SHADER_SURFACE:
|
||||
case SHADER_STUDIO:
|
||||
case SHADER_SPRITE:
|
||||
break;
|
||||
|
@ -221,8 +230,6 @@ static bool R_ParseGeneralSurfaceParm( shader_t *shader, char **script )
|
|||
MsgDev( D_WARN, "unknown 'surfaceParm' parameter '%s' in shader '%s'\n", tok, shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
shader->flags |= SHADER_SURFACEPARM;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -233,7 +240,7 @@ R_ParseGeneralNoMipmaps
|
|||
*/
|
||||
static bool R_ParseGeneralNoMipmaps( shader_t *shader, char **script )
|
||||
{
|
||||
shader->flags |= (SHADER_NOMIPMAPS|SHADER_NOPICMIP);
|
||||
r_shaderNoMipMaps = r_shaderNoPicMip = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -244,7 +251,7 @@ R_ParseGeneralNoPicmip
|
|||
*/
|
||||
static bool R_ParseGeneralNoPicmip( shader_t *shader, char **script )
|
||||
{
|
||||
shader->flags |= SHADER_NOPICMIP;
|
||||
r_shaderNoPicMip = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -255,29 +262,7 @@ R_ParseGeneralNoCompress
|
|||
*/
|
||||
static bool R_ParseGeneralNoCompress( shader_t *shader, char **script )
|
||||
{
|
||||
shader->flags |= SHADER_NOCOMPRESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseGeneralNoShadows
|
||||
=================
|
||||
*/
|
||||
static bool R_ParseGeneralNoShadows( shader_t *shader, char **script )
|
||||
{
|
||||
shader->flags |= SHADER_NOSHADOWS;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseGeneralNoFragments
|
||||
=================
|
||||
*/
|
||||
static bool R_ParseGeneralNoFragments( shader_t *shader, char **script )
|
||||
{
|
||||
shader->flags |= SHADER_NOFRAGMENTS;
|
||||
r_shaderNoCompress = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -350,16 +335,10 @@ static bool R_ParseGeneralSort( shader_t *shader, char **script )
|
|||
if(Com_MatchToken( "sky" )) shader->sort = SORT_SKY;
|
||||
else if(Com_MatchToken( "opaque")) shader->sort = SORT_OPAQUE;
|
||||
else if(Com_MatchToken( "decal")) shader->sort = SORT_DECAL;
|
||||
else if(Com_MatchToken( "seeThrough")) shader->sort = SORT_SEETHROUGH;
|
||||
else if(Com_MatchToken( "portal")) shader->sort = SORT_PORTAL;
|
||||
else if(Com_MatchToken( "banner")) shader->sort = SORT_BANNER;
|
||||
else if(Com_MatchToken( "underwater")) shader->sort = SORT_UNDERWATER;
|
||||
else if(Com_MatchToken( "water")) shader->sort = SORT_WATER;
|
||||
else if(Com_MatchToken( "innerBlend")) shader->sort = SORT_INNERBLEND;
|
||||
else if(Com_MatchToken( "blend")) shader->sort = SORT_BLEND;
|
||||
else if(Com_MatchToken( "blend2")) shader->sort = SORT_BLEND2;
|
||||
else if(Com_MatchToken( "blend3")) shader->sort = SORT_BLEND3;
|
||||
else if(Com_MatchToken( "blend4")) shader->sort = SORT_BLEND4;
|
||||
else if(Com_MatchToken( "outerBlend")) shader->sort = SORT_OUTERBLEND;
|
||||
else if(Com_MatchToken( "alphatest")) shader->sort = SORT_ALPHATEST;
|
||||
else if(Com_MatchToken( "additive")) shader->sort = SORT_ADDITIVE;
|
||||
else if(Com_MatchToken( "nearest")) shader->sort = SORT_NEAREST;
|
||||
else
|
||||
|
@ -376,46 +355,6 @@ static bool R_ParseGeneralSort( shader_t *shader, char **script )
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseGeneralTessSize
|
||||
=================
|
||||
*/
|
||||
static bool R_ParseGeneralTessSize( shader_t *shader, char **script )
|
||||
{
|
||||
char *tok;
|
||||
int i = 8;
|
||||
|
||||
if( shader->shaderType != SHADER_TEXTURE )
|
||||
{
|
||||
MsgDev( D_WARN, "'tessSize' not allowed in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "missing parameters for 'tessSize' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
shader->tessSize = com.atoi( tok );
|
||||
|
||||
if( shader->tessSize < 8 || shader->tessSize > 256 )
|
||||
{
|
||||
MsgDev( D_WARN, "out of range size value of %i for 'tessSize' in shader '%s', defaulting to 64\n", shader->tessSize, shader->name );
|
||||
shader->tessSize = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
while( i <= shader->tessSize ) i<<=1;
|
||||
shader->tessSize = i>>1;
|
||||
}
|
||||
|
||||
shader->flags |= SHADER_TESSSIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseGeneralSkyParms
|
||||
|
@ -447,7 +386,7 @@ static bool R_ParseGeneralSkyParms( shader_t *shader, char **script )
|
|||
if( shader->skyParms.farBox[i] )
|
||||
shader->skyParms.farBox[i]->flags &= ~TF_STATIC; // old skybox will be removed on next loading
|
||||
com.snprintf( name, sizeof(name), "%s%s", tok, r_skyBoxSuffix[i] );
|
||||
shader->skyParms.farBox[i] = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_SKYSIDE|TF_STATIC, 0 );
|
||||
shader->skyParms.farBox[i] = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_SKYBOX|TF_STATIC, 0 );
|
||||
if( !shader->skyParms.farBox[i] )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find texture '%s' in shader '%s'\n", name, shader->name );
|
||||
|
@ -488,7 +427,7 @@ static bool R_ParseGeneralSkyParms( shader_t *shader, char **script )
|
|||
if( shader->skyParms.nearBox[i] )
|
||||
shader->skyParms.nearBox[i]->flags &= ~TF_STATIC; // old skybox will be removed on next loading
|
||||
com.snprintf( name, sizeof(name), "%s%s", tok, r_skyBoxSuffix[i] );
|
||||
shader->skyParms.nearBox[i] = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_SKYSIDE|TF_STATIC, 0 );
|
||||
shader->skyParms.nearBox[i] = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_SKYBOX|TF_STATIC, 0 );
|
||||
if( !shader->skyParms.nearBox[i] )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find texture '%s' in shader '%s'\n", name, shader->name );
|
||||
|
@ -693,13 +632,11 @@ static bool R_ParseStageMap( shader_t *shader, shaderStage_t *stage, char **scri
|
|||
MsgDev( D_WARN, "SHADER_MAX_TEXTURES hit in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!(bundle->flags & STAGEBUNDLE_MAP))
|
||||
{
|
||||
MsgDev( D_WARN, "animation with mixed texture types in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!(bundle->flags & STAGEBUNDLE_ANIMFREQUENCY))
|
||||
{
|
||||
MsgDev( D_WARN, "multiple 'map' specifications without preceding 'animFrequency' in shader '%s'\n", shader->name );
|
||||
|
@ -722,7 +659,7 @@ static bool R_ParseStageMap( shader_t *shader, shaderStage_t *stage, char **scri
|
|||
|
||||
if(Com_MatchToken( "$lightmap"))
|
||||
{
|
||||
if( shader->shaderType != SHADER_TEXTURE )
|
||||
if( shader->shaderType != SHADER_SURFACE )
|
||||
{
|
||||
MsgDev( D_WARN, "'map $lightmap' not allowed in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
|
@ -736,24 +673,53 @@ static bool R_ParseStageMap( shader_t *shader, shaderStage_t *stage, char **scri
|
|||
|
||||
bundle->texType = TEX_LIGHTMAP;
|
||||
bundle->flags |= STAGEBUNDLE_MAP;
|
||||
shader->flags |= SHADER_HASLIGHTMAP;
|
||||
shader->flags |= SHADER_LIGHTMAP;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(Com_MatchToken( "$dlight" ))
|
||||
{
|
||||
if( bundle->flags & STAGEBUNDLE_ANIMFREQUENCY )
|
||||
{
|
||||
MsgDev( D_WARN, "'map $dlight' not allowed with 'animFrequency' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( Com_MatchToken( "$whiteImage" )) bundle->textures[bundle->numTextures++] = r_whiteTexture;
|
||||
else if( Com_MatchToken( "$blackImage")) bundle->textures[bundle->numTextures++] = r_blackTexture;
|
||||
bundle->texType = TEX_DLIGHT;
|
||||
bundle->tcGen.type = TCGEN_BASE;
|
||||
bundle->flags |= STAGEBUNDLE_MAP;
|
||||
r_shaderHasDlightPass = true;
|
||||
return true;
|
||||
}
|
||||
else if(Com_MatchToken( "$portal" ) || Com_MatchToken( "$mirror" ))
|
||||
{
|
||||
if( bundle->flags & STAGEBUNDLE_ANIMFREQUENCY )
|
||||
{
|
||||
MsgDev( D_WARN, "'map $portal' or $mirror not allowed with 'animFrequency' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
bundle->texType = TEX_PORTAL;
|
||||
bundle->tcGen.type = TCGEN_PROJECTION;
|
||||
bundle->flags |= STAGEBUNDLE_MAP;
|
||||
if(( shader->flags & SHADER_PORTAL ) && ( shader->sort == SORT_PORTAL ))
|
||||
shader->sort = 0; // reset sorting so we can figure it out later. FIXME?
|
||||
shader->flags |= SHADER_PORTAL|( r_portalmaps->integer ? SHADER_PORTAL_CAPTURE : 0 );
|
||||
return true;
|
||||
}
|
||||
if( Com_MatchToken( "$white" )) bundle->textures[bundle->numTextures++] = r_whiteTexture;
|
||||
else if( Com_MatchToken( "$black")) bundle->textures[bundle->numTextures++] = r_blackTexture;
|
||||
else if( Com_MatchToken( "$internal")) bundle->textures[bundle->numTextures++] = r_internalMiptex;
|
||||
else
|
||||
{
|
||||
if(!(shader->flags & SHADER_NOMIPMAPS) && !(bundle->flags & STAGEBUNDLE_NOMIPMAPS))
|
||||
flags |= TF_MIPMAPS;
|
||||
if(!(shader->flags & SHADER_NOPICMIP) && !(bundle->flags & STAGEBUNDLE_NOPICMIP))
|
||||
flags |= TF_IMAGE2D;
|
||||
if(!(shader->flags & SHADER_NOCOMPRESS) && !(bundle->flags & STAGEBUNDLE_NOCOMPRESS))
|
||||
if( r_shaderNoMipMaps || bundle->flags & STAGEBUNDLE_NOMIPMAPS )
|
||||
flags |= TF_NOMIPMAP;
|
||||
if( r_shaderNoPicMip || bundle->flags & STAGEBUNDLE_NOPICMIP )
|
||||
flags |= TF_NOPICMIP;
|
||||
if( !r_shaderNoCompress && !(bundle->flags & STAGEBUNDLE_NOCOMPRESS))
|
||||
flags |= TF_COMPRESS;
|
||||
|
||||
if( bundle->flags & STAGEBUNDLE_CLAMPTEXCOORDS)
|
||||
if( bundle->flags & STAGEBUNDLE_CLAMPTEXCOORDS )
|
||||
flags |= TF_CLAMP;
|
||||
|
||||
bundle->textures[bundle->numTextures] = R_FindTexture( tok, NULL, 0, flags, 0 );
|
||||
|
@ -815,11 +781,11 @@ static bool R_ParseStageBumpMap( shader_t *shader, shaderStage_t *stage, char **
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!(shader->flags & SHADER_NOMIPMAPS) && !(bundle->flags & STAGEBUNDLE_NOMIPMAPS))
|
||||
flags |= TF_MIPMAPS;
|
||||
if(!(shader->flags & SHADER_NOPICMIP) && !(bundle->flags & STAGEBUNDLE_NOPICMIP))
|
||||
flags |= TF_IMAGE2D;
|
||||
if(!(shader->flags & SHADER_NOCOMPRESS) && !(bundle->flags & STAGEBUNDLE_NOCOMPRESS))
|
||||
if( r_shaderNoMipMaps || bundle->flags & STAGEBUNDLE_NOMIPMAPS )
|
||||
flags |= TF_NOMIPMAP;
|
||||
if( r_shaderNoPicMip || bundle->flags & STAGEBUNDLE_NOPICMIP )
|
||||
flags |= TF_NOPICMIP;
|
||||
if( !r_shaderNoCompress && !( bundle->flags & STAGEBUNDLE_NOCOMPRESS ))
|
||||
flags |= TF_COMPRESS;
|
||||
|
||||
if(bundle->flags & STAGEBUNDLE_CLAMPTEXCOORDS)
|
||||
|
@ -915,11 +881,11 @@ static bool R_ParseStageCubeMap( shader_t *shader, shaderStage_t *stage, char **
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!(shader->flags & SHADER_NOMIPMAPS) && !(bundle->flags & STAGEBUNDLE_NOMIPMAPS))
|
||||
flags |= TF_MIPMAPS;
|
||||
if(!(shader->flags & SHADER_NOPICMIP) && !(bundle->flags & STAGEBUNDLE_NOPICMIP))
|
||||
flags |= TF_IMAGE2D;
|
||||
if(!(shader->flags & SHADER_NOCOMPRESS) && !(bundle->flags & STAGEBUNDLE_NOCOMPRESS))
|
||||
if( r_shaderNoMipMaps || bundle->flags & STAGEBUNDLE_NOMIPMAPS )
|
||||
flags |= TF_NOMIPMAP;
|
||||
if( r_shaderNoPicMip || bundle->flags & STAGEBUNDLE_NOPICMIP )
|
||||
flags |= TF_NOPICMIP;
|
||||
if( !r_shaderNoCompress && !(bundle->flags & STAGEBUNDLE_NOCOMPRESS))
|
||||
flags |= TF_COMPRESS;
|
||||
|
||||
if(bundle->flags & STAGEBUNDLE_CLAMPTEXCOORDS)
|
||||
|
@ -1746,27 +1712,10 @@ static bool R_ParseStageNextBundle( shader_t *shader, shaderStage_t *stage, char
|
|||
return false;
|
||||
}
|
||||
|
||||
if( stage->flags & SHADERSTAGE_FRAGMENTPROGRAM )
|
||||
if( stage->numBundles == gl_config.textureunits )
|
||||
{
|
||||
if( stage->numBundles == gl_config.texturecoords )
|
||||
{
|
||||
MsgDev( D_WARN, "shader '%s' has %i or more bundles without suitable 'requires GL_MAX_TEXTURE_COORDS_ARB'\n", shader->name, stage->numBundles + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( stage->numBundles == gl_config.imageunits )
|
||||
{
|
||||
MsgDev( D_WARN, "shader '%s' has %i or more bundles without suitable 'requires GL_MAX_TEXTURE_IMAGE_UNITS_ARB'\n", shader->name, stage->numBundles + 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( stage->numBundles == gl_config.textureunits )
|
||||
{
|
||||
MsgDev( D_WARN, "shader '%s' has %i or more bundles without suitable 'requires GL_MAX_TEXTURE_UNITS_ARB'\n", shader->name, stage->numBundles + 1);
|
||||
return false;
|
||||
}
|
||||
MsgDev( D_WARN, "shader '%s' has %i or more bundles without suitable 'requires GL_MAX_TEXTURE_UNITS_ARB'\n", shader->name, stage->numBundles + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( stage->numBundles == MAX_TEXTURE_UNITS )
|
||||
|
@ -1892,96 +1841,6 @@ static bool R_ParseStageNextBundle( shader_t *shader, shaderStage_t *stage, char
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseStageVertexProgram
|
||||
=================
|
||||
*/
|
||||
static bool R_ParseStageVertexProgram( shader_t *shader, shaderStage_t *stage, char **script )
|
||||
{
|
||||
char *tok;
|
||||
|
||||
if( !GL_Support( R_VERTEX_PROGRAM_EXT ))
|
||||
{
|
||||
MsgDev( D_WARN, "shader '%s' uses 'vertexProgram' without 'requires GL_ARB_vertex_program'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( shader->shaderType == SHADER_NOMIP )
|
||||
{
|
||||
MsgDev( D_WARN, "'vertexProgram' not allowed in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( stage->flags & SHADERSTAGE_NEXTBUNDLE )
|
||||
{
|
||||
MsgDev( D_WARN, "'vertexProgram' not allowed in 'nextBundle' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "missing parameters for 'vertexProgram' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
stage->vertexProgram = R_FindProgram( tok, GL_VERTEX_PROGRAM_ARB );
|
||||
if( !stage->vertexProgram )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find vertex program '%s' in shader '%s'\n", tok, shader->name );
|
||||
return false;
|
||||
}
|
||||
stage->flags |= SHADERSTAGE_VERTEXPROGRAM;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseStageFragmentProgram
|
||||
=================
|
||||
*/
|
||||
static bool R_ParseStageFragmentProgram( shader_t *shader, shaderStage_t *stage, char **script )
|
||||
{
|
||||
char *tok;
|
||||
|
||||
if (!GL_Support( R_FRAGMENT_PROGRAM_EXT ))
|
||||
{
|
||||
MsgDev( D_WARN, "shader '%s' uses 'fragmentProgram' without 'requires GL_ARB_fragment_program'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( shader->shaderType == SHADER_NOMIP )
|
||||
{
|
||||
MsgDev( D_WARN, "'fragmentProgram' not allowed in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( stage->flags & SHADERSTAGE_NEXTBUNDLE )
|
||||
{
|
||||
MsgDev( D_WARN, "'fragmentProgram' not allowed in 'nextBundle' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "missing parameters for 'fragmentProgram' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
stage->fragmentProgram = R_FindProgram( tok, GL_FRAGMENT_PROGRAM_ARB );
|
||||
if( !stage->fragmentProgram )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find fragment program '%s' in shader '%s'\n", tok, shader->name );
|
||||
return false;
|
||||
}
|
||||
stage->flags |= SHADERSTAGE_FRAGMENTPROGRAM;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ParseStageAlphaFunc
|
||||
|
@ -2258,26 +2117,6 @@ static bool R_ParseStageRgbGen( shader_t *shader, shaderStage_t *stage, char **s
|
|||
}
|
||||
stage->rgbGen.type = RGBGEN_WAVE;
|
||||
}
|
||||
else if (Com_MatchToken( "colorWave"))
|
||||
{
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "missing parameters for 'rgbGen colorWave' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
stage->rgbGen.params[i] = bound( 0.0, com.atof( tok ), 1.0 );
|
||||
}
|
||||
|
||||
if( !R_ParseWaveFunc(shader, &stage->rgbGen.func, script ))
|
||||
{
|
||||
MsgDev( D_WARN, "missing waveform parameters for 'rgbGen colorWave' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
stage->rgbGen.type = RGBGEN_COLORWAVE;
|
||||
}
|
||||
else if (Com_MatchToken( "vertex"))
|
||||
stage->rgbGen.type = RGBGEN_VERTEX;
|
||||
else if (Com_MatchToken( "oneMinusVertex"))
|
||||
|
@ -2347,24 +2186,6 @@ static bool R_ParseStageAlphaGen( shader_t *shader, shaderStage_t *stage, char *
|
|||
}
|
||||
stage->alphaGen.type = ALPHAGEN_WAVE;
|
||||
}
|
||||
else if (Com_MatchToken( "alphaWave"))
|
||||
{
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "missing parameters for 'alphaGen alphaWave' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
stage->alphaGen.params[0] = bound( 0.0, com.atof( tok ), 1.0 );
|
||||
|
||||
if(!R_ParseWaveFunc( shader, &stage->alphaGen.func, script ))
|
||||
{
|
||||
MsgDev( D_WARN, "missing waveform parameters for 'alphaGen alphaWave' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
stage->alphaGen.type = ALPHAGEN_ALPHAWAVE;
|
||||
}
|
||||
else if (Com_MatchToken( "vertex"))
|
||||
stage->alphaGen.type = ALPHAGEN_VERTEX;
|
||||
else if (Com_MatchToken( "oneMinusVertex"))
|
||||
|
@ -2468,7 +2289,7 @@ static bool R_ParseStageAlphaGen( shader_t *shader, shaderStage_t *stage, char *
|
|||
}
|
||||
stage->alphaGen.type = ALPHAGEN_ONEMINUSFADE;
|
||||
}
|
||||
else if (Com_MatchToken( "lightingSpecular" ))
|
||||
else if (Com_MatchToken( "specular" ))
|
||||
{
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] ) stage->alphaGen.params[0] = 5.0;
|
||||
|
@ -2481,7 +2302,7 @@ static bool R_ParseStageAlphaGen( shader_t *shader, shaderStage_t *stage, char *
|
|||
stage->alphaGen.params[0] = 5.0;
|
||||
}
|
||||
}
|
||||
stage->alphaGen.type = ALPHAGEN_LIGHTINGSPECULAR;
|
||||
stage->alphaGen.type = ALPHAGEN_SPECULAR;
|
||||
}
|
||||
else if (Com_MatchToken( "const" ) || Com_MatchToken( "constant" ))
|
||||
{
|
||||
|
@ -2525,13 +2346,10 @@ static shaderGeneralCmd_t r_shaderGeneralCmds[] =
|
|||
{"noMipmaps", R_ParseGeneralNoMipmaps },
|
||||
{"noPicmip", R_ParseGeneralNoPicmip },
|
||||
{"noCompress", R_ParseGeneralNoCompress },
|
||||
{"noShadows", R_ParseGeneralNoShadows },
|
||||
{"noFragments", R_ParseGeneralNoFragments },
|
||||
{"entityMergable", R_ParseGeneralEntityMergable },
|
||||
{"polygonOffset", R_ParseGeneralPolygonOffset },
|
||||
{"cull", R_ParseGeneralCull },
|
||||
{"sort", R_ParseGeneralSort },
|
||||
{"tessSize", R_ParseGeneralTessSize },
|
||||
{"skyParms", R_ParseGeneralSkyParms },
|
||||
{"deformVertexes", R_ParseGeneralDeformVertexes },
|
||||
{NULL, NULL } // terminator
|
||||
|
@ -2553,8 +2371,6 @@ static shaderStageCmd_t r_shaderStageCmds[] =
|
|||
{"tcGen", R_ParseStageTcGen },
|
||||
{"tcMod", R_ParseStageTcMod },
|
||||
{"nextBundle", R_ParseStageNextBundle },
|
||||
{"vertexProgram", R_ParseStageVertexProgram },
|
||||
{"fragmentProgram", R_ParseStageFragmentProgram },
|
||||
{"alphaFunc", R_ParseStageAlphaFunc },
|
||||
{"blendFunc", R_ParseStageBlendFunc },
|
||||
{"depthFunc", R_ParseStageDepthFunc },
|
||||
|
@ -2663,14 +2479,10 @@ static bool R_EvaluateRequires( shader_t *shader, char **script )
|
|||
return false;
|
||||
}
|
||||
|
||||
if( Com_MatchToken( "GL_MAX_TEXTURE_UNITS_ARB") || Com_MatchToken( "GL_MAX_TEXTURE_COORDS_ARB") || Com_MatchToken( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB"))
|
||||
if( Com_MatchToken( "GL_MAX_TEXTURE_UNITS_ARB"))
|
||||
{
|
||||
if( Com_MatchToken( "GL_MAX_TEXTURE_UNITS_ARB" ))
|
||||
cmpOperand1 = gl_config.textureunits;
|
||||
else if( Com_MatchToken( "GL_MAX_TEXTURE_COORDS_ARB"))
|
||||
cmpOperand1 = gl_config.texturecoords;
|
||||
else if (Com_MatchToken( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" ))
|
||||
cmpOperand1 = gl_config.imageunits;
|
||||
|
||||
tok = Com_ParseToken( script, false );
|
||||
if( !tok[0] )
|
||||
|
@ -2738,10 +2550,6 @@ static bool R_EvaluateRequires( shader_t *shader, char **script )
|
|||
results[count] = GL_Support( R_DOT3_ARB_EXT );
|
||||
else if (Com_MatchToken( "GL_ARB_texture_cube_map"))
|
||||
results[count] = GL_Support( R_TEXTURECUBEMAP_EXT );
|
||||
else if (Com_MatchToken( "GL_ARB_vertex_program"))
|
||||
results[count] = GL_Support( R_VERTEX_PROGRAM_EXT );
|
||||
else if (Com_MatchToken( "GL_ARB_fragment_program"))
|
||||
results[count] = GL_Support( R_FRAGMENT_PROGRAM_EXT );
|
||||
else
|
||||
{
|
||||
MsgDev( D_WARN, "unknown 'requires' expression '%s' in shader '%s', discarded stage\n", tok, shader->name );
|
||||
|
@ -3024,9 +2832,8 @@ static shader_t *R_CreateShader( const char *name, shaderType_t shaderType, uint
|
|||
shader->shaderNum = r_numShaders;
|
||||
shader->shaderType = shaderType;
|
||||
shader->surfaceParm = surfaceParm;
|
||||
shader->flags = SHADER_EXTERNAL;
|
||||
|
||||
if( shaderType == SHADER_NOMIP ) shader->flags |= (SHADER_NOMIPMAPS | SHADER_NOPICMIP);
|
||||
if( shaderType == SHADER_NOMIP ) r_shaderNoMipMaps = r_shaderNoPicMip = true;
|
||||
|
||||
if( !R_ParseShader( shader, script ))
|
||||
{
|
||||
|
@ -3052,7 +2859,6 @@ static shader_t *R_CreateShader( const char *name, shaderType_t shaderType, uint
|
|||
shader->shaderNum = r_numShaders;
|
||||
shader->shaderType = shaderType;
|
||||
shader->surfaceParm = surfaceParm;
|
||||
shader->flags = SHADER_EXTERNAL|SHADER_DEFAULTED;
|
||||
shader->stages[0]->bundles[0]->textures[0] = r_defaultTexture;
|
||||
shader->stages[0]->bundles[0]->numTextures++;
|
||||
shader->stages[0]->numBundles++;
|
||||
|
@ -3060,7 +2866,7 @@ static shader_t *R_CreateShader( const char *name, shaderType_t shaderType, uint
|
|||
|
||||
if(!( shader->surfaceParm & SURF_NOLIGHTMAP ))
|
||||
{
|
||||
shader->flags |= SHADER_HASLIGHTMAP;
|
||||
shader->flags |= SHADER_LIGHTMAP;
|
||||
shader->stages[1]->bundles[0]->flags |= STAGEBUNDLE_MAP;
|
||||
shader->stages[1]->bundles[0]->texType = TEX_LIGHTMAP;
|
||||
shader->stages[1]->flags |= SHADERSTAGE_BLENDFUNC;
|
||||
|
@ -3104,7 +2910,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
{
|
||||
if( shader->skyParms.farBox[i] )
|
||||
shader->skyParms.farBox[i]->flags &= ~TF_STATIC; // old skybox will be removed on next loading
|
||||
shader->skyParms.farBox[i] = R_FindTexture(va("gfx/env/%s%s", shader->name, r_skyBoxSuffix[i]), NULL, 0, TF_CLAMP|TF_SKYSIDE|TF_STATIC, 0 );
|
||||
shader->skyParms.farBox[i] = R_FindTexture(va("gfx/env/%s%s", shader->name, r_skyBoxSuffix[i]), NULL, 0, TF_CLAMP|TF_SKYBOX|TF_STATIC, 0 );
|
||||
if( !shader->skyParms.farBox[i] )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find texture for shader '%s', using default...\n", shader->name );
|
||||
|
@ -3113,9 +2919,9 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
}
|
||||
shader->skyParms.cloudHeight = 128.0;
|
||||
break;
|
||||
case SHADER_TEXTURE:
|
||||
case SHADER_SURFACE:
|
||||
shader->stages[0]->bundles[0]->flags |= STAGEBUNDLE_MAP;
|
||||
shader->stages[0]->bundles[0]->textures[0] = R_FindTexture( shader->name, buffer, bufsize, TF_MIPMAPS|TF_COMPRESS, 0 );
|
||||
shader->stages[0]->bundles[0]->textures[0] = R_FindTexture( shader->name, buffer, bufsize, TF_COMPRESS, 0 );
|
||||
if( !shader->stages[0]->bundles[0]->textures[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find texture for shader '%s', using default...\n", shader->name );
|
||||
|
@ -3145,7 +2951,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
|
||||
if(!( shader->surfaceParm & SURF_NOLIGHTMAP ))
|
||||
{
|
||||
shader->flags |= SHADER_HASLIGHTMAP;
|
||||
shader->flags |= SHADER_LIGHTMAP;
|
||||
shader->stages[1]->bundles[0]->flags |= STAGEBUNDLE_MAP;
|
||||
shader->stages[1]->bundles[0]->texType = TEX_LIGHTMAP;
|
||||
shader->stages[1]->flags |= SHADERSTAGE_BLENDFUNC;
|
||||
|
@ -3170,7 +2976,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
shader->stages[0]->blendFunc.src = GL_SRC_ALPHA;
|
||||
shader->stages[0]->blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
shader->flags |= SHADER_ENTITYMERGABLE; // using renderamt
|
||||
shader->sort = SORT_BLEND;
|
||||
shader->sort = SORT_ADDITIVE;
|
||||
}
|
||||
if( shader->surfaceParm & SURF_ADDITIVE )
|
||||
{
|
||||
|
@ -3178,7 +2984,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
shader->stages[0]->blendFunc.src = GL_SRC_ALPHA;
|
||||
shader->stages[0]->blendFunc.dst = GL_ONE;
|
||||
shader->flags |= SHADER_ENTITYMERGABLE; // using renderamt
|
||||
shader->sort = SORT_BLEND;
|
||||
shader->sort = SORT_ADDITIVE;
|
||||
}
|
||||
if( shader->surfaceParm & SURF_ALPHA )
|
||||
{
|
||||
|
@ -3188,7 +2994,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
shader->stages[0]->alphaFunc.func = GL_GREATER;
|
||||
shader->stages[0]->alphaFunc.ref = 0.666;
|
||||
shader->flags |= SHADER_ENTITYMERGABLE; // using renderamt
|
||||
shader->sort = SORT_SEETHROUGH;
|
||||
shader->sort = SORT_ALPHATEST;
|
||||
}
|
||||
shader->stages[0]->bundles[0]->numTextures++;
|
||||
shader->stages[0]->numBundles++;
|
||||
|
@ -3209,7 +3015,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
shader->stages[0]->blendFunc.src = GL_SRC_ALPHA;
|
||||
shader->stages[0]->blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
shader->flags |= SHADER_ENTITYMERGABLE; // using renderamt
|
||||
shader->sort = SORT_BLEND;
|
||||
shader->sort = SORT_ADDITIVE;
|
||||
}
|
||||
if( shader->surfaceParm & SURF_ALPHA )
|
||||
{
|
||||
|
@ -3219,7 +3025,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
shader->stages[0]->alphaFunc.func = GL_GREATER;
|
||||
shader->stages[0]->alphaFunc.ref = 0.666;
|
||||
shader->flags |= SHADER_ENTITYMERGABLE; // using renderamt
|
||||
shader->sort = SORT_SEETHROUGH;
|
||||
shader->sort = SORT_ALPHATEST;
|
||||
}
|
||||
shader->stages[0]->bundles[0]->numTextures++;
|
||||
shader->stages[0]->numBundles++;
|
||||
|
@ -3229,8 +3035,9 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
// don't let user set invalid font
|
||||
// FIXME: make case SHADER_FONT and func RegisterShaderFont
|
||||
if(com.stristr( shader->name, "fonts/" )) buffer = FS_LoadInternal( "default.dds", &bufsize );
|
||||
shader->features = MF_STCOORDS|MF_COLORS;
|
||||
shader->stages[0]->bundles[0]->flags |= STAGEBUNDLE_MAP;
|
||||
shader->stages[0]->bundles[0]->textures[0] = R_FindTexture( shader->name, buffer, bufsize, TF_COMPRESS|TF_IMAGE2D, 0 );
|
||||
shader->stages[0]->bundles[0]->textures[0] = R_FindTexture( shader->name, buffer, bufsize, TF_COMPRESS|TF_NOMIPMAP, 0 );
|
||||
if( !shader->stages[0]->bundles[0]->textures[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find texture for shader '%s', using default...\n", shader->name );
|
||||
|
@ -3245,7 +3052,7 @@ static shader_t *R_CreateDefaultShader( const char *name, shaderType_t shaderTyp
|
|||
break;
|
||||
case SHADER_GENERIC:
|
||||
shader->stages[0]->bundles[0]->flags |= STAGEBUNDLE_MAP;
|
||||
shader->stages[0]->bundles[0]->textures[0] = R_FindTexture( shader->name, buffer, bufsize, TF_MIPMAPS|TF_COMPRESS, 0 );
|
||||
shader->stages[0]->bundles[0]->textures[0] = R_FindTexture( shader->name, buffer, bufsize, TF_COMPRESS, 0 );
|
||||
if( !shader->stages[0]->bundles[0]->textures[0] )
|
||||
{
|
||||
MsgDev( D_WARN, "couldn't find texture for shader '%s', using default...\n", shader->name );
|
||||
|
@ -3321,9 +3128,9 @@ static void R_FinishShader( shader_t *shader )
|
|||
}
|
||||
|
||||
// lightmap but no lightmap stage?
|
||||
if( shader->shaderType == SHADER_TEXTURE && !(shader->surfaceParm & SURF_NOLIGHTMAP ))
|
||||
if( shader->shaderType == SHADER_SURFACE && !(shader->surfaceParm & SURF_NOLIGHTMAP ))
|
||||
{
|
||||
if(!(shader->flags & SHADER_DEFAULTED) && !(shader->flags & SHADER_HASLIGHTMAP))
|
||||
if(!(shader->flags & SHADER_LIGHTMAP))
|
||||
MsgDev( D_WARN, "shader '%s' has lightmap but no lightmap stage!\n", shader->name );
|
||||
}
|
||||
|
||||
|
@ -3358,7 +3165,7 @@ static void R_FinishShader( shader_t *shader )
|
|||
// only allow tcGen lightmap on world surfaces
|
||||
if( bundle->tcGen.type == TCGEN_LIGHTMAP )
|
||||
{
|
||||
if( shader->shaderType != SHADER_TEXTURE )
|
||||
if( shader->shaderType != SHADER_SURFACE )
|
||||
bundle->tcGen.type = TCGEN_BASE;
|
||||
}
|
||||
}
|
||||
|
@ -3424,7 +3231,7 @@ static void R_FinishShader( shader_t *shader )
|
|||
case SHADER_SKY:
|
||||
stage->rgbGen.type = RGBGEN_IDENTITY;
|
||||
break;
|
||||
case SHADER_TEXTURE:
|
||||
case SHADER_SURFACE:
|
||||
if((stage->flags & SHADERSTAGE_BLENDFUNC) && (stage->bundles[0]->texType != TEX_LIGHTMAP))
|
||||
stage->rgbGen.type = RGBGEN_IDENTITYLIGHTING;
|
||||
else stage->rgbGen.type = RGBGEN_IDENTITY;
|
||||
|
@ -3456,7 +3263,7 @@ static void R_FinishShader( shader_t *shader )
|
|||
case SHADER_SKY:
|
||||
stage->alphaGen.type = ALPHAGEN_IDENTITY;
|
||||
break;
|
||||
case SHADER_TEXTURE:
|
||||
case SHADER_SURFACE:
|
||||
if((stage->flags & SHADERSTAGE_BLENDFUNC) && (stage->bundles[0]->texType != TEX_LIGHTMAP))
|
||||
{
|
||||
if( shader->surfaceParm & SURF_ADDITIVE )
|
||||
|
@ -3504,7 +3311,7 @@ static void R_FinishShader( shader_t *shader )
|
|||
case ALPHAGEN_ONEMINUSDOT:
|
||||
case ALPHAGEN_FADE:
|
||||
case ALPHAGEN_ONEMINUSFADE:
|
||||
case ALPHAGEN_LIGHTINGSPECULAR:
|
||||
case ALPHAGEN_SPECULAR:
|
||||
if( shader->shaderType == SHADER_NOMIP )
|
||||
stage->alphaGen.type = ALPHAGEN_VERTEX;
|
||||
shader->flags &= ~SHADER_ENTITYMERGABLE;
|
||||
|
@ -3559,13 +3366,8 @@ static void R_FinishShader( shader_t *shader )
|
|||
if( shader->flags & SHADER_POLYGONOFFSET )
|
||||
shader->sort = SORT_DECAL;
|
||||
else if( stage->flags & SHADERSTAGE_ALPHAFUNC )
|
||||
shader->sort = SORT_SEETHROUGH;
|
||||
else
|
||||
{
|
||||
if((stage->blendFunc.src == GL_SRC_ALPHA && stage->blendFunc.dst == GL_ONE) || (stage->blendFunc.src == GL_ONE && stage->blendFunc.dst == GL_ONE))
|
||||
shader->sort = SORT_ADDITIVE;
|
||||
else shader->sort = SORT_BLEND;
|
||||
}
|
||||
shader->sort = SORT_ALPHATEST;
|
||||
else shader->sort = SORT_ADDITIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3587,9 +3389,6 @@ static bool R_MergeShaderStages( shaderStage_t *stage1, shaderStage_t *stage2 )
|
|||
if( stage1->flags & SHADERSTAGE_NEXTBUNDLE || stage2->flags & SHADERSTAGE_NEXTBUNDLE )
|
||||
return false;
|
||||
|
||||
if( stage1->flags & (SHADERSTAGE_VERTEXPROGRAM | SHADERSTAGE_FRAGMENTPROGRAM) || stage2->flags & (SHADERSTAGE_VERTEXPROGRAM | SHADERSTAGE_FRAGMENTPROGRAM))
|
||||
return false;
|
||||
|
||||
if( stage2->flags & SHADERSTAGE_ALPHAFUNC )
|
||||
return false;
|
||||
|
||||
|
@ -3679,6 +3478,28 @@ static void R_OptimizeShader( shader_t *shader )
|
|||
}
|
||||
}
|
||||
|
||||
void R_DeformVertexesBBoxForShader( const shader_t *shader, vec3_t ebbox )
|
||||
{
|
||||
int dv;
|
||||
float dvmax;
|
||||
|
||||
if( !shader ) return;
|
||||
for( dv = 0; dv < shader->deformVertexesNum; dv++ )
|
||||
{
|
||||
switch( shader->deformVertexes[dv].type )
|
||||
{
|
||||
case DEFORMVERTEXES_WAVE:
|
||||
dvmax = fabs( shader->deformVertexes[dv].func.params[1] ) + shader->deformVertexes[dv].func.params[0];
|
||||
ebbox[0] = max( ebbox[0], dvmax );
|
||||
ebbox[1] = ebbox[0];
|
||||
ebbox[2] = ebbox[0];
|
||||
break;
|
||||
// FIXME: need to implementation for another funcs ?
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LoadShader
|
||||
|
@ -3693,7 +3514,7 @@ shader_t *R_LoadShader( shader_t *newShader )
|
|||
if( r_numShaders == MAX_SHADERS )
|
||||
Host_Error( "R_LoadShader: MAX_SHADERS limit exceeded\n" );
|
||||
|
||||
r_shaders[r_numShaders++] = shader = Mem_Alloc( r_shaderpool, sizeof( shader_t ));
|
||||
r_shaders[r_numShaders++] = shader = Shader_Malloc( sizeof( shader_t ));
|
||||
|
||||
// make sure the shader is valid and set all the unset parameters
|
||||
R_FinishShader( newShader );
|
||||
|
@ -3723,6 +3544,9 @@ shader_t *R_LoadShader( shader_t *newShader )
|
|||
shader->numStages++;
|
||||
}
|
||||
|
||||
// calculate sortkey
|
||||
shader->sortKey = Shader_Sortkey( shader, shader->sort );
|
||||
|
||||
// add to hash table
|
||||
hashKey = Com_HashKey( shader->name, SHADERS_HASHSIZE );
|
||||
shader->nextHash = r_shadersHash[hashKey];
|
||||
|
@ -3769,6 +3593,11 @@ shader_t *R_FindShader( const char *name, shaderType_t shaderType, uint surfaceP
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_shaderNoMipMaps = false;
|
||||
r_shaderNoPicMip = false;
|
||||
r_shaderNoCompress = false;
|
||||
r_shaderHasDlightPass = false;
|
||||
|
||||
// create the shader
|
||||
if( script ) shader = R_CreateShader( name, shaderType, surfaceParm, script );
|
||||
|
@ -3821,35 +3650,31 @@ R_ShaderRegisterImages
|
|||
many many included cycles ...
|
||||
=================
|
||||
*/
|
||||
void R_ShaderRegisterImages( rmodel_t *mod )
|
||||
void R_ShaderRegisterImages( shader_t *shader )
|
||||
{
|
||||
int i, j, k, l;
|
||||
int c_total = 0;
|
||||
shader_t *shader;
|
||||
int i, j, k;
|
||||
shaderStage_t *stage;
|
||||
stageBundle_t *bundle;
|
||||
texture_t *texture;
|
||||
int c_total = 0;
|
||||
|
||||
if( !mod ) return;
|
||||
for( i = 0; i < mod->numShaders; i++ )
|
||||
if( !shader ) return;
|
||||
for( i = 0; i < shader->numStages; i++ )
|
||||
{
|
||||
shader = mod->shaders[i].shader;
|
||||
for( j = 0; j < shader->numStages; j++ )
|
||||
stage = shader->stages[i];
|
||||
for( j = 0; j < stage->numBundles; j++ )
|
||||
{
|
||||
stage = shader->stages[j];
|
||||
for( k = 0; k < stage->numBundles; k++ )
|
||||
bundle = stage->bundles[j];
|
||||
for( k = 0; k < bundle->numTextures; k++ )
|
||||
{
|
||||
bundle = stage->bundles[k];
|
||||
for( l = 0; l < bundle->numTextures; l++ )
|
||||
{
|
||||
// prolonge registration for all shader textures
|
||||
texture = bundle->textures[l];
|
||||
texture->registration_sequence = registration_sequence;
|
||||
c_total++; // just for debug
|
||||
}
|
||||
// prolonge registration for all shader textures
|
||||
texture = bundle->textures[k];
|
||||
texture->sequence = registration_sequence;
|
||||
c_total++; // just for debug
|
||||
}
|
||||
}
|
||||
}
|
||||
MsgDev( D_INFO, "%i textures updated by shader %s\n", c_total, shader->name );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3866,7 +3691,7 @@ static void R_CreateBuiltInShaders( void )
|
|||
|
||||
com.strncpy( shader->name, "<default>", sizeof( shader->name ));
|
||||
shader->shaderNum = r_numShaders;
|
||||
shader->shaderType = SHADER_TEXTURE;
|
||||
shader->shaderType = SHADER_SURFACE;
|
||||
shader->surfaceParm = SURF_NOLIGHTMAP;
|
||||
shader->stages[0]->bundles[0]->textures[0] = r_defaultTexture;
|
||||
shader->stages[0]->bundles[0]->numTextures++;
|
||||
|
@ -3880,8 +3705,8 @@ static void R_CreateBuiltInShaders( void )
|
|||
|
||||
com.strncpy( shader->name, "<lightmap>", sizeof( shader->name ));
|
||||
shader->shaderNum = r_numShaders;
|
||||
shader->shaderType = SHADER_TEXTURE;
|
||||
shader->flags = SHADER_HASLIGHTMAP;
|
||||
shader->shaderType = SHADER_SURFACE;
|
||||
shader->flags = SHADER_LIGHTMAP;
|
||||
shader->stages[0]->bundles[0]->texType = TEX_LIGHTMAP;
|
||||
shader->stages[0]->numBundles++;
|
||||
shader->numStages++;
|
||||
|
@ -3911,16 +3736,12 @@ void R_ShaderList_f( void )
|
|||
|
||||
Msg( "%i/%i ", passes, shader->numStages );
|
||||
|
||||
if( shader->flags & SHADER_EXTERNAL )
|
||||
Msg("E ");
|
||||
else Msg(" ");
|
||||
|
||||
switch( shader->shaderType )
|
||||
{
|
||||
case SHADER_SKY:
|
||||
Msg( "sky " );
|
||||
break;
|
||||
case SHADER_TEXTURE:
|
||||
case SHADER_SURFACE:
|
||||
Msg( "bsp " );
|
||||
break;
|
||||
case SHADER_STUDIO:
|
||||
|
@ -3942,7 +3763,6 @@ void R_ShaderList_f( void )
|
|||
else Msg(" ");
|
||||
|
||||
Msg( "%2i ", shader->sort );
|
||||
Msg( ": %s%s\n", shader->name, (shader->flags & SHADER_DEFAULTED) ? " (DEFAULTED)" : "" );
|
||||
}
|
||||
|
||||
Msg( "-----------------------------------\n" );
|
||||
|
|
1007
render/r_sky.c
1007
render/r_sky.c
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,7 @@ string frame_prefix;
|
|||
byte *spr_palette;
|
||||
static byte pal[256][4];
|
||||
uint surfaceParm;
|
||||
mipTex_t *frames;
|
||||
shader_t *frames;
|
||||
|
||||
/*
|
||||
====================
|
||||
|
@ -35,7 +35,7 @@ dframetype_t *R_SpriteLoadFrame( rmodel_t *mod, void *pin, mspriteframe_t **ppfr
|
|||
rgbdata_t *spr_frame;
|
||||
texture_t *image;
|
||||
string name;
|
||||
mipTex_t *out;
|
||||
shader_t *out;
|
||||
|
||||
pinframe = (dframe_t *)pin;
|
||||
|
||||
|
@ -88,8 +88,8 @@ dframetype_t *R_SpriteLoadFrame( rmodel_t *mod, void *pin, mspriteframe_t **ppfr
|
|||
spr_frametype = (dframetype_t *)((byte *)(pinframe + 1) + size );
|
||||
|
||||
com.strncpy( out->name, name, 64 );
|
||||
out->shader = pspriteframe->shader;
|
||||
out->flags = surfaceParm;
|
||||
out = pspriteframe->shader;
|
||||
out->surfaceParm = surfaceParm;
|
||||
|
||||
FS_FreeImage( spr_frame );
|
||||
return spr_frametype;
|
||||
|
@ -239,7 +239,7 @@ void R_SpriteLoadModel( rmodel_t *mod, const void *buffer )
|
|||
|
||||
MsgDev( D_LOAD, "%s, rendermode %d\n", mod->name, psprite->rendermode );
|
||||
|
||||
mod->registration_sequence = registration_sequence;
|
||||
mod->sequence = registration_sequence;
|
||||
spr_palette = (byte *)(&pal[0][0]);
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
|
@ -264,7 +264,7 @@ void R_SpriteLoadModel( rmodel_t *mod, const void *buffer )
|
|||
}
|
||||
if( pframetype == NULL ) break; // technically an error
|
||||
}
|
||||
mod->shaders = frames; // setup texture links
|
||||
*mod->shaders = frames; // setup texture links
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -329,23 +329,7 @@ R_AddSpriteModelToList
|
|||
add spriteframe to list
|
||||
=================
|
||||
*/
|
||||
void R_AddSpriteModelToList( ref_entity_t *entity )
|
||||
{
|
||||
mspriteframe_t *frame;
|
||||
|
||||
frame = R_GetSpriteFrame( entity );
|
||||
|
||||
if( R_CullSphere( entity->origin, frame->radius, MAX_CLIPFLAGS ))
|
||||
return;
|
||||
|
||||
// copy frame params
|
||||
entity->radius = frame->radius;
|
||||
entity->rotation = 0;
|
||||
entity->shader = frame->shader;
|
||||
|
||||
// add it
|
||||
R_AddMeshToList( MESH_SPRITE, NULL, entity->shader, entity, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -361,55 +345,55 @@ void R_DrawSpriteModel( void )
|
|||
ref_entity_t *e;
|
||||
int i;
|
||||
|
||||
e = m_pCurrentEntity;
|
||||
e = Ref.m_pCurrentEntity;
|
||||
frame = R_GetSpriteFrame( e );
|
||||
psprite = (msprite_t *)m_pRenderModel->extradata;
|
||||
psprite = (msprite_t *)Ref.m_pCurrentModel->extradata;
|
||||
|
||||
// setup orientation
|
||||
switch( psprite->type )
|
||||
{
|
||||
case SPR_ORIENTED:
|
||||
VectorCopy( e->axis[0], forward );
|
||||
VectorCopy( e->axis[1], right );
|
||||
VectorCopy( e->axis[2], up );
|
||||
VectorCopy( e->matrix[0], forward );
|
||||
VectorCopy( e->matrix[1], right );
|
||||
VectorCopy( e->matrix[2], up );
|
||||
VectorScale( forward, 0.01, forward ); // to avoid z-fighting
|
||||
VectorSubtract( e->origin, forward, e->origin );
|
||||
break;
|
||||
case SPR_FACING_UPRIGHT:
|
||||
VectorSet( right, e->origin[1] - r_origin[1], -(e->origin[0] - r_origin[0]), 0 );
|
||||
VectorNegate( r_forward, forward );
|
||||
VectorSet( right, e->origin[1] - Ref.vieworg[1], -(e->origin[0] - Ref.vieworg[0]), 0 );
|
||||
VectorNegate( Ref.forward, forward );
|
||||
VectorSet( up, 0, 0, 1 );
|
||||
VectorNormalize( right );
|
||||
break;
|
||||
case SPR_FWD_PARALLEL_UPRIGHT:
|
||||
VectorSet( right, r_forward[1], -r_forward[0], 0 );
|
||||
VectorNegate( r_forward, forward );
|
||||
VectorSet( right, Ref.forward[1], -Ref.forward[0], 0 );
|
||||
VectorNegate( Ref.forward, forward );
|
||||
VectorSet( up, 0, 0, 1 );
|
||||
break;
|
||||
case SPR_FWD_PARALLEL_ORIENTED:
|
||||
right[0] = e->axis[1][0] * r_forward[0] + e->axis[1][1] * r_right[0] + e->axis[1][2] * r_up[0];
|
||||
right[1] = e->axis[1][0] * r_forward[1] + e->axis[1][1] * r_right[1] + e->axis[1][2] * r_up[1];
|
||||
right[2] = e->axis[1][0] * r_forward[2] + e->axis[1][1] * r_right[2] + e->axis[1][2] * r_up[2];
|
||||
up[0] = e->axis[2][0] * r_forward[0] + e->axis[2][1] * r_right[0] + e->axis[2][2] * r_up[0];
|
||||
up[1] = e->axis[2][0] * r_forward[1] + e->axis[2][1] * r_right[1] + e->axis[2][2] * r_up[1];
|
||||
up[2] = e->axis[2][0] * r_forward[2] + e->axis[2][1] * r_right[2] + e->axis[2][2] * r_up[2];
|
||||
right[0] = e->matrix[1][0] * Ref.forward[0] + e->matrix[1][1] * Ref.right[0] + e->matrix[1][2] * Ref.up[0];
|
||||
right[1] = e->matrix[1][0] * Ref.forward[1] + e->matrix[1][1] * Ref.right[1] + e->matrix[1][2] * Ref.up[1];
|
||||
right[2] = e->matrix[1][0] * Ref.forward[2] + e->matrix[1][1] * Ref.right[2] + e->matrix[1][2] * Ref.up[2];
|
||||
up[0] = e->matrix[2][0] * Ref.forward[0] + e->matrix[2][1] * Ref.right[0] + e->matrix[2][2] * Ref.up[0];
|
||||
up[1] = e->matrix[2][0] * Ref.forward[1] + e->matrix[2][1] * Ref.right[1] + e->matrix[2][2] * Ref.up[1];
|
||||
up[2] = e->matrix[2][0] * Ref.forward[2] + e->matrix[2][1] * Ref.right[2] + e->matrix[2][2] * Ref.up[2];
|
||||
break;
|
||||
case SPR_FWD_PARALLEL:
|
||||
default: // normal sprite
|
||||
VectorNegate( r_forward, forward );
|
||||
VectorNegate( r_right, right );
|
||||
VectorCopy( r_up, up );
|
||||
VectorNegate( Ref.forward, forward );
|
||||
VectorNegate( Ref.right, right );
|
||||
VectorCopy( Ref.up, up );
|
||||
break;
|
||||
}
|
||||
|
||||
// draw it
|
||||
RB_CheckMeshOverflow( 6, 4 );
|
||||
// RB_CheckMeshOverflow( 6, 4 );
|
||||
|
||||
for( i = 2; i < 4; i++ )
|
||||
{
|
||||
indexArray[numIndex++] = numVertex + 0;
|
||||
indexArray[numIndex++] = numVertex + i-1;
|
||||
indexArray[numIndex++] = numVertex + i;
|
||||
indexArray[r_stats.numIndices++] = r_stats.numVertices + 0;
|
||||
indexArray[r_stats.numIndices++] = r_stats.numVertices + i-1;
|
||||
indexArray[r_stats.numIndices++] = r_stats.numVertices + i;
|
||||
}
|
||||
|
||||
GL_Begin( GL_QUADS );
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,12 +4,11 @@
|
|||
//=======================================================================
|
||||
|
||||
#include "r_local.h"
|
||||
#include "r_meshbuffer.h"
|
||||
#include "mathlib.h"
|
||||
#include "matrixlib.h"
|
||||
#include "const.h"
|
||||
|
||||
#define BACKFACE_EPSILON 0.01
|
||||
|
||||
rmodel_t *r_worldModel;
|
||||
ref_entity_t *r_worldEntity;
|
||||
vec3_t r_worldMins, r_worldMaxs;
|
||||
|
@ -17,54 +16,36 @@ int r_frameCount;
|
|||
int r_visFrameCount;
|
||||
int r_areabitsChanged;
|
||||
int r_viewCluster;
|
||||
int r_oldViewCluster;
|
||||
int numRadarEnts = 0;
|
||||
radar_ent_t RadarEnts[MAX_RADAR_ENTS];
|
||||
static vec3_t modelorg; // relative to viewpoint
|
||||
static vec3_t modelmins;
|
||||
static vec3_t modelmaxs;
|
||||
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
BRUSH MODELS
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
R_DrawSurface
|
||||
R_SurfPotentiallyVisible
|
||||
=================
|
||||
*/
|
||||
void R_DrawSurface( void )
|
||||
bool R_SurfPotentiallyVisible( msurface_t *surf )
|
||||
{
|
||||
surface_t *surf = m_pRenderMesh->mesh;
|
||||
surfPoly_t *p;
|
||||
surfPolyVert_t *v;
|
||||
int i;
|
||||
|
||||
for( p = surf->poly; p; p = p->next )
|
||||
{
|
||||
RB_CheckMeshOverflow( p->numIndices, p->numVertices );
|
||||
|
||||
for( i = 0; i < p->numIndices; i += 3 )
|
||||
{
|
||||
indexArray[numIndex++] = numVertex + p->indices[i+0];
|
||||
indexArray[numIndex++] = numVertex + p->indices[i+1];
|
||||
indexArray[numIndex++] = numVertex + p->indices[i+2];
|
||||
}
|
||||
|
||||
for( i = 0, v = p->vertices; i < p->numVertices; i++, v++ )
|
||||
{
|
||||
vertexArray[numVertex][0] = v->xyz[0];
|
||||
vertexArray[numVertex][1] = v->xyz[1];
|
||||
vertexArray[numVertex][2] = v->xyz[2];
|
||||
tangentArray[numVertex][0] = surf->tangent[0];
|
||||
tangentArray[numVertex][1] = surf->tangent[1];
|
||||
tangentArray[numVertex][2] = surf->tangent[2];
|
||||
binormalArray[numVertex][0] = surf->binormal[0];
|
||||
binormalArray[numVertex][1] = surf->binormal[1];
|
||||
binormalArray[numVertex][2] = surf->binormal[2];
|
||||
normalArray[numVertex][0] = surf->normal[0];
|
||||
normalArray[numVertex][1] = surf->normal[1];
|
||||
normalArray[numVertex][2] = surf->normal[2];
|
||||
inTexCoordArray[numVertex][0] = v->st[0];
|
||||
inTexCoordArray[numVertex][1] = v->st[1];
|
||||
inTexCoordArray[numVertex][2] = v->lightmap[0];
|
||||
inTexCoordArray[numVertex][3] = v->lightmap[1];
|
||||
Vector4Copy(v->color, inColorArray[numVertex]);
|
||||
numVertex++;
|
||||
}
|
||||
}
|
||||
if( surf->faceType == MST_FLARE )
|
||||
return true;
|
||||
if( surf->flags & SURF_NODRAW )
|
||||
return false;
|
||||
if( !surf->mesh || R_InvalidMesh( surf->mesh ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -72,36 +53,68 @@ void R_DrawSurface( void )
|
|||
R_CullSurface
|
||||
=================
|
||||
*/
|
||||
static bool R_CullSurface( surface_t *surf, const vec3_t origin, int clipFlags )
|
||||
bool R_CullSurface( msurface_t *surf, uint clipflags )
|
||||
{
|
||||
cplane_t *plane;
|
||||
float dist;
|
||||
shader_t *shader = surf->shader;
|
||||
|
||||
if( r_nocull->integer ) return false;
|
||||
if(( shader->flags & SHADER_SKY ) && r_fastsky->integer )
|
||||
return true;
|
||||
if( r_nocull->integer )
|
||||
return false;
|
||||
if( shader->flags & SHADER_AUTOSPRITE )
|
||||
return false;
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = surf->plane;
|
||||
if( plane->type < 3 ) dist = origin[plane->type] - plane->dist;
|
||||
else dist = DotProduct( origin, plane->normal ) - plane->dist;
|
||||
|
||||
if(!(surf->flags & SURF_PLANEBACK))
|
||||
// flare
|
||||
if( surf->faceType == MST_FLARE )
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return true; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return true; // wrong side
|
||||
if( r_flares->integer && r_flarefade->value )
|
||||
{
|
||||
vec3_t origin;
|
||||
|
||||
if( Ref.m_pCurrentModel != r_worldModel )
|
||||
{
|
||||
Matrix3x3_Transform( Ref.m_pCurrentEntity->matrix, surf->origin, origin );
|
||||
VectorAdd( origin, Ref.m_pCurrentEntity->origin, origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( surf->origin, origin );
|
||||
}
|
||||
|
||||
// cull it because we don't want to sort unneeded things
|
||||
if((origin[0] - Ref.vieworg[0]) * Ref.forward[0] + (origin[1] - Ref.vieworg[1])
|
||||
* Ref.forward[1] + (origin[2] - Ref.vieworg[2]) * Ref.forward[2] < 0 )
|
||||
return true;
|
||||
return ( clipflags && R_CullSphere( origin, 1, clipflags ));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// cull
|
||||
if( clipFlags )
|
||||
if( surf->faceType == MST_PLANAR && !r_nocull->integer )
|
||||
{
|
||||
if( R_CullBox( surf->mins, surf->maxs, clipFlags ))
|
||||
return true;
|
||||
cplane_t *plane;
|
||||
float dist;
|
||||
|
||||
// NOTE: bsplib have support for SURF_PLANEBACK
|
||||
// this code don't working correctly with another bsp compilers
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = surf->plane;
|
||||
if( plane->type < 3 ) dist = modelorg[plane->type] - plane->dist;
|
||||
else dist = DotProduct( modelorg, plane->normal ) - plane->dist;
|
||||
|
||||
if(!(surf->flags & SURF_PLANEBACK) || ( Ref.params & RP_MIRRORVIEW ))
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return true; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return true; // wrong side
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ( clipflags && R_CullBox( surf->mins, surf->maxs, clipflags ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -109,368 +122,514 @@ static bool R_CullSurface( surface_t *surf, const vec3_t origin, int clipFlags )
|
|||
R_AddSurfaceToList
|
||||
=================
|
||||
*/
|
||||
static void R_AddSurfaceToList( surface_t *surf, ref_entity_t *entity )
|
||||
static meshbuffer_t *R_AddSurfaceToList( msurface_t *surf, uint clipflags )
|
||||
{
|
||||
mipTex_t *tex = surf->texInfo;
|
||||
shader_t *shader = tex->shader;
|
||||
int map, lmNum;
|
||||
shader_t *shader;
|
||||
meshbuffer_t *mb;
|
||||
|
||||
if( tex->flags & SURF_NODRAW )
|
||||
return;
|
||||
if( R_CullSurface( surf, clipflags ))
|
||||
return NULL;
|
||||
|
||||
// select lightmap
|
||||
lmNum = surf->lmNum;
|
||||
|
||||
// check for lightmap modification
|
||||
if( r_dynamiclights->integer && (shader->flags & SHADER_HASLIGHTMAP))
|
||||
shader = ((r_drawworld->integer == 2) ? R_OcclusionShader() : surf->shader);
|
||||
if( shader->flags & SHADER_SKY )
|
||||
{
|
||||
if( surf->dlightFrame == r_frameCount )
|
||||
bool vis = R_AddSkySurface( surf );
|
||||
if( ( Ref.params & RP_NOSKY ) && vis )
|
||||
{
|
||||
lmNum = 255;
|
||||
R_AddMeshToList( MESH_MODEL, surf->fog, shader, surf - r_worldBrushModel->surfaces + 1 );
|
||||
Ref.params &= ~RP_NOSKY;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( OCCLUSION_QUERIES_ENABLED( Ref ))
|
||||
{
|
||||
if( shader->flags & SHADER_PORTAL )
|
||||
R_SurfOcclusionQueryKey( Ref.m_pCurrentEntity, surf );
|
||||
if( OCCLUSION_OPAQUE_SHADER( shader ))
|
||||
R_AddOccludingSurface( surf, shader );
|
||||
}
|
||||
|
||||
mb = R_AddMeshToList( surf->faceType == MST_FLARE ? MESH_SPRITE : MESH_MODEL, surf->fog, shader, surf - r_worldBrushModel->surfaces + 1 );
|
||||
Ref.surfmbuffers[surf - r_worldBrushModel->surfaces] = mb;
|
||||
return mb;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullBrushModel
|
||||
=================
|
||||
*/
|
||||
bool R_CullBrushModel( ref_entity_t *e )
|
||||
{
|
||||
int i;
|
||||
bool rotated;
|
||||
rmodel_t *model = e->model;
|
||||
mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata;
|
||||
|
||||
if( bmodel->numModelSurfaces == 0 )
|
||||
return true;
|
||||
|
||||
if( !Matrix3x3_Compare( e->matrix, matrix3x3_identity ))
|
||||
{
|
||||
rotated = true;
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
modelmins[i] = e->origin[i] - model->radius * e->scale;
|
||||
modelmaxs[i] = e->origin[i] + model->radius * e->scale;
|
||||
}
|
||||
if( R_CullSphere( e->origin, model->radius * e->scale, Ref.clipFlags ))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotated = false;
|
||||
VectorMA( e->origin, e->scale, model->mins, modelmins );
|
||||
VectorMA( e->origin, e->scale, model->maxs, modelmaxs );
|
||||
if( R_CullBox( modelmins, modelmaxs, Ref.clipFlags ))
|
||||
return true;
|
||||
}
|
||||
|
||||
if( Ref.refdef.rdflags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( Ref.params & RP_SKYPORTALVIEW ))
|
||||
{
|
||||
if( rotated )
|
||||
{
|
||||
if( R_VisCullSphere( e->origin, model->radius * e->scale ) )
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( map = 0; map < surf->numStyles; map++ )
|
||||
{
|
||||
if( surf->cachedLight[map] != r_lightStyles[surf->styles[map]].white )
|
||||
{
|
||||
lmNum = 255;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( R_VisCullBox( modelmins, modelmaxs ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// add it
|
||||
R_AddMeshToList( MESH_SURFACE, surf, shader, entity, lmNum );
|
||||
|
||||
// Also add caustics
|
||||
if( r_caustics->integer )
|
||||
{
|
||||
if( surf->flags & SURF_WATERCAUSTICS )
|
||||
R_AddMeshToList( MESH_SURFACE, surf, r_waterCausticsShader, entity, 0 );
|
||||
if( surf->flags & SURF_SLIMECAUSTICS )
|
||||
R_AddMeshToList( MESH_SURFACE, surf, r_slimeCausticsShader, entity, 0 );
|
||||
if( surf->flags & SURF_LAVACAUSTICS )
|
||||
R_AddMeshToList( MESH_SURFACE, surf, r_lavaCausticsShader, entity, 0 );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
BRUSH MODELS
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
R_AddBrushModelToList
|
||||
=================
|
||||
*/
|
||||
void R_AddBrushModelToList( ref_entity_t *entity )
|
||||
void R_AddBrushModelToList( ref_entity_t *e )
|
||||
{
|
||||
rmodel_t *model = entity->model;
|
||||
surface_t *surf;
|
||||
dlight_t *dl;
|
||||
vec3_t origin, tmp;
|
||||
vec3_t mins, maxs;
|
||||
int i, l;
|
||||
uint i;
|
||||
bool rotated;
|
||||
rmodel_t *model = e->model;
|
||||
mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;
|
||||
msurface_t *psurf;
|
||||
uint dlightbits;
|
||||
meshbuffer_t *mb;
|
||||
|
||||
if( !model->numModelSurfaces )
|
||||
return;
|
||||
|
||||
// cull
|
||||
if( !AxisCompare( entity->axis, axisDefault ))
|
||||
rotated = !Matrix3x3_Compare( e->matrix, matrix3x3_identity );
|
||||
VectorSubtract( Ref.refdef.vieworg, e->origin, modelorg );
|
||||
if( rotated )
|
||||
{
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
mins[i] = entity->origin[i] - model->radius;
|
||||
maxs[i] = entity->origin[i] + model->radius;
|
||||
}
|
||||
vec3_t temp;
|
||||
|
||||
if( R_CullSphere( entity->origin, model->radius, MAX_CLIPFLAGS ))
|
||||
return;
|
||||
|
||||
VectorSubtract( r_origin, entity->origin, tmp );
|
||||
VectorRotate( tmp, entity->axis, origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd( entity->origin, model->mins, mins );
|
||||
VectorAdd( entity->origin, model->maxs, maxs );
|
||||
|
||||
if( R_CullBox( mins, maxs, MAX_CLIPFLAGS ))
|
||||
return;
|
||||
|
||||
VectorSubtract( r_refdef.vieworg, entity->origin, origin );
|
||||
VectorCopy( modelorg, temp );
|
||||
Matrix3x3_Transform( e->matrix, temp, modelorg );
|
||||
}
|
||||
|
||||
// Calculate dynamic lighting
|
||||
if( r_dynamiclights->integer )
|
||||
dlightbits = 0;
|
||||
if(( r_dynamiclights->integer == 1 ) && !r_fullbright->integer && !( Ref.params & RP_SHADOWMAPVIEW ))
|
||||
{
|
||||
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
|
||||
for( i = 0; i < r_numDLights; i++ )
|
||||
{
|
||||
if( !BoundsAndSphereIntersect( mins, maxs, dl->origin, dl->intensity ))
|
||||
continue;
|
||||
|
||||
surf = model->surfaces + model->firstModelSurface;
|
||||
for( i = 0; i < model->numModelSurfaces; i++, surf++ )
|
||||
{
|
||||
if( surf->dlightFrame != r_frameCount )
|
||||
{
|
||||
surf->dlightFrame = r_frameCount;
|
||||
surf->dlightBits = (1<<l);
|
||||
}
|
||||
else surf->dlightBits |= (1<<l);
|
||||
}
|
||||
if( BoundsIntersect( modelmins, modelmaxs, r_dlights[i].mins, r_dlights[i].maxs ))
|
||||
dlightbits |= ( 1<<i );
|
||||
}
|
||||
}
|
||||
|
||||
// add all the surfaces
|
||||
surf = model->surfaces + model->firstModelSurface;
|
||||
for( i = 0; i < model->numModelSurfaces; i++, surf++ )
|
||||
for( i = 0, psurf = bmodel->firstModelSurface; i < (unsigned)bmodel->numModelSurfaces; i++, psurf++ )
|
||||
{
|
||||
// cull
|
||||
if( R_CullSurface( surf, origin, 0 ))
|
||||
if( !R_SurfPotentiallyVisible( psurf ))
|
||||
continue;
|
||||
|
||||
// add the surface
|
||||
R_AddSurfaceToList( surf, entity );
|
||||
if( Ref.params & RP_SHADOWMAPVIEW )
|
||||
{
|
||||
if( psurf->visFrame != r_frameCount )
|
||||
continue;
|
||||
if(( psurf->shader->sort >= SORT_OPAQUE ) && ( psurf->shader->sort <= SORT_BANNER ))
|
||||
{
|
||||
if( oldRef.surfmbuffers[psurf - r_worldBrushModel->surfaces] )
|
||||
{
|
||||
if( !R_CullSurface( psurf, 0 ) )
|
||||
{
|
||||
Ref.params |= RP_WORLDSURFVISIBLE;
|
||||
oldRef.surfmbuffers[psurf - r_worldBrushModel->surfaces]->shadowbits |= Ref.shadowGroup->bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
psurf->visFrame = r_frameCount;
|
||||
mb = R_AddSurfaceToList( psurf, 0 );
|
||||
if( mb )
|
||||
{
|
||||
mb->sortKey |= (( psurf->superLightStyle+1 )<<10 );
|
||||
if( R_SurfPotentiallyLit( psurf ))
|
||||
mb->dlightbits = dlightbits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
=============================================================
|
||||
|
||||
WORLD MODEL
|
||||
|
||||
=======================================================================
|
||||
=============================================================
|
||||
*/
|
||||
/*
|
||||
================
|
||||
R_MarkLeafSurfaces
|
||||
================
|
||||
*/
|
||||
static void R_MarkLeafSurfaces( msurface_t **mark, uint clipflags, uint dlightbits )
|
||||
{
|
||||
uint newDlightbits;
|
||||
msurface_t *surf;
|
||||
meshbuffer_t *mb;
|
||||
|
||||
do
|
||||
{
|
||||
surf = *mark++;
|
||||
|
||||
// NOTE: that R_AddSurfaceToList may set meshBuffer to NULL
|
||||
// for world ALL surfaces to prevent referencing to freed memory region
|
||||
if( surf->visFrame != r_frameCount )
|
||||
{
|
||||
surf->visFrame = r_frameCount;
|
||||
mb = R_AddSurfaceToList( surf, clipflags );
|
||||
if( mb ) mb->sortKey |= (( surf->superLightStyle+1 )<<10 );
|
||||
}
|
||||
else mb = Ref.surfmbuffers[surf - r_worldBrushModel->surfaces];
|
||||
|
||||
newDlightbits = mb ? dlightbits & ~mb->dlightbits : 0;
|
||||
if( newDlightbits && R_SurfPotentiallyLit( surf ))
|
||||
mb->dlightbits |= R_AddSurfDlighbits( surf, newDlightbits );
|
||||
} while( *mark );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
================
|
||||
R_RecursiveWorldNode
|
||||
================
|
||||
*/
|
||||
static void R_RecursiveWorldNode( mnode_t *node, uint clipflags, uint dlightbits )
|
||||
{
|
||||
uint i, bit, newDlightbits;
|
||||
const cplane_t *clipplane;
|
||||
mleaf_t *pleaf;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
return;
|
||||
|
||||
if( clipflags )
|
||||
{
|
||||
i = sizeof(Ref.frustum) / sizeof( Ref.frustum[0]);
|
||||
for( bit = 1, clipplane = Ref.frustum; i > 0; i--, bit<<=1, clipplane++ )
|
||||
{
|
||||
if( clipflags & bit )
|
||||
{
|
||||
int clipped = BoxOnPlaneSide( node->mins, node->maxs, clipplane );
|
||||
if( clipped == 2 ) return;
|
||||
if( clipped == 1 ) clipflags &= ~bit; // node is entirely on screen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !node->plane ) break;
|
||||
|
||||
newDlightbits = 0;
|
||||
if( dlightbits )
|
||||
{
|
||||
float dist;
|
||||
|
||||
for( i = 0, bit = 1; i < r_numDLights; i++, bit<<=1 )
|
||||
{
|
||||
if(!( dlightbits & bit ))
|
||||
continue;
|
||||
|
||||
dist = PlaneDiff( r_dlights[i].origin, node->plane );
|
||||
if( dist < -r_dlights[i].intensity )
|
||||
dlightbits &= ~bit;
|
||||
if( dist < r_dlights[i].intensity )
|
||||
newDlightbits |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
R_RecursiveWorldNode( node->children[0], clipflags, dlightbits );
|
||||
|
||||
node = node->children[1];
|
||||
dlightbits = newDlightbits;
|
||||
}
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
pleaf = ( mleaf_t * )node;
|
||||
pleaf->visFrame = r_frameCount;
|
||||
|
||||
// add leaf bounds to view bounds
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
Ref.visMins[i] = min( Ref.visMins[i], pleaf->mins[i] );
|
||||
Ref.visMaxs[i] = max( Ref.visMaxs[i], pleaf->maxs[i] );
|
||||
}
|
||||
|
||||
R_MarkLeafSurfaces( pleaf->firstVisSurface, clipflags, dlightbits );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_MarkShadowLeafSurfaces
|
||||
================
|
||||
*/
|
||||
static void R_MarkShadowLeafSurfaces( msurface_t **mark, uint clipflags )
|
||||
{
|
||||
msurface_t *surf;
|
||||
meshbuffer_t *mb;
|
||||
const uint bit = Ref.shadowGroup->bit;
|
||||
|
||||
do
|
||||
{
|
||||
surf = *mark++;
|
||||
if( surf->flags & ( SURF_NOIMPACT|SURF_NODRAW ))
|
||||
continue;
|
||||
|
||||
mb = oldRef.surfmbuffers[surf - r_worldBrushModel->surfaces];
|
||||
if( !mb || (mb->shadowbits & bit))
|
||||
continue;
|
||||
|
||||
// this surface is visible in previous RI, not marked as shadowed...
|
||||
if(( surf->shader->sort >= SORT_OPAQUE ) && ( surf->shader->sort <= SORT_ALPHATEST ))
|
||||
{
|
||||
// ...is opaque
|
||||
if( !R_CullSurface( surf, clipflags ))
|
||||
{
|
||||
// and is visible to the light source too
|
||||
Ref.params |= RP_WORLDSURFVISIBLE;
|
||||
mb->shadowbits |= bit;
|
||||
}
|
||||
}
|
||||
} while( *mark );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_LinearShadowLeafs
|
||||
================
|
||||
*/
|
||||
static void R_LinearShadowLeafs( void )
|
||||
{
|
||||
uint i, j;
|
||||
uint cpf, bit;
|
||||
const cplane_t *clipplane;
|
||||
mleaf_t *pleaf;
|
||||
|
||||
for( j = r_worldBrushModel->numleafs, pleaf = r_worldBrushModel->leafs; j > 0; j--, pleaf++ )
|
||||
{
|
||||
if( pleaf->visFrame != r_frameCount )
|
||||
continue;
|
||||
if( !( Ref.shadowGroup->vis[pleaf->cluster>>3] & ( 1<<( pleaf->cluster&7 ) ) ) )
|
||||
continue;
|
||||
|
||||
cpf = Ref.clipFlags;
|
||||
i = sizeof( Ref.frustum ) / sizeof( Ref.frustum[0] );
|
||||
for( bit = 1, clipplane = Ref.frustum; i > 0; i--, bit<<=1, clipplane++ )
|
||||
{
|
||||
int clipped = BoxOnPlaneSide( pleaf->mins, pleaf->maxs, clipplane );
|
||||
if( clipped == 2 ) break;
|
||||
if( clipped == 1 ) cpf &= ~bit; // leaf is entirely on screen
|
||||
}
|
||||
|
||||
if( !i ) R_MarkShadowLeafSurfaces( pleaf->firstVisSurface, cpf );
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
|
||||
int r_surfQueryKeys[MAX_SURF_QUERIES];
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ClearSurfOcclusionQueryKeys
|
||||
===============
|
||||
*/
|
||||
void R_ClearSurfOcclusionQueryKeys( void )
|
||||
{
|
||||
Mem_Set( r_surfQueryKeys, -1, sizeof( r_surfQueryKeys ));
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SurfOcclusionQueryKey
|
||||
===============
|
||||
*/
|
||||
int R_SurfOcclusionQueryKey( ref_entity_t *e, msurface_t *surf )
|
||||
{
|
||||
int i;
|
||||
int *keys = r_surfQueryKeys;
|
||||
int key = surf - r_worldBrushModel->surfaces;
|
||||
|
||||
if( e != r_worldEntity ) return -1;
|
||||
|
||||
for( i = 0; i < MAX_SURF_QUERIES; i++ )
|
||||
{
|
||||
if( keys[i] >= 0 )
|
||||
{
|
||||
if( keys[i] == key )
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
keys[i] = key;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SurfIssueOcclusionQueries
|
||||
===============
|
||||
*/
|
||||
void R_SurfIssueOcclusionQueries( void )
|
||||
{
|
||||
int i, *keys = r_surfQueryKeys;
|
||||
msurface_t *surf;
|
||||
|
||||
for( i = 0; keys[i] >= 0; i++ )
|
||||
{
|
||||
surf = &r_worldBrushModel->surfaces[keys[i]];
|
||||
R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_CUSTOM, i ), r_worldEntity, surf->mins, surf->maxs );
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CalcDistancesToFogVolumes
|
||||
=============
|
||||
*/
|
||||
static void R_CalcDistancesToFogVolumes( void )
|
||||
{
|
||||
int i;
|
||||
mfog_t *fog;
|
||||
|
||||
for( i = 0, fog = r_worldBrushModel->fogs; i < r_worldBrushModel->numFogs; i++, fog++ )
|
||||
Ref.fog_dist_to_eye[fog - r_worldBrushModel->fogs] = PlaneDiff( Ref.vieworg, fog->visible );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_DrawWorld
|
||||
=============
|
||||
*/
|
||||
void R_DrawWorld( void )
|
||||
{
|
||||
int clipflags, msec = 0;
|
||||
uint dlightbits;
|
||||
|
||||
if( !r_drawworld->integer ) return;
|
||||
if( !r_worldModel ) return;
|
||||
if( Ref.refdef.rdflags & RDF_NOWORLDMODEL )
|
||||
return;
|
||||
|
||||
VectorCopy( Ref.refdef.vieworg, modelorg );
|
||||
|
||||
Ref.m_pPrevEntity = NULL;
|
||||
Ref.m_pCurrentEntity = r_worldEntity;
|
||||
Ref.m_pCurrentModel = Ref.m_pCurrentEntity->model;
|
||||
|
||||
if( !( Ref.params & RP_SHADOWMAPVIEW ) )
|
||||
{
|
||||
R_AllocMeshbufPointers( &Ref );
|
||||
memset( Ref.surfmbuffers, 0, r_worldBrushModel->numsurfaces * sizeof( meshbuffer_t * ));
|
||||
|
||||
R_CalcDistancesToFogVolumes();
|
||||
}
|
||||
|
||||
ClearBounds( Ref.visMins, Ref.visMaxs );
|
||||
R_ClearSky();
|
||||
|
||||
if( r_nocull->integer ) clipflags = 0;
|
||||
else clipflags = Ref.clipFlags;
|
||||
|
||||
if( r_dynamiclights->integer != 1 || r_fullbright->integer )
|
||||
dlightbits = 0;
|
||||
else dlightbits = r_numDLights < 32 ? ( 1 << r_numDLights ) - 1 : -1;
|
||||
|
||||
if( Ref.params & RP_SHADOWMAPVIEW ) R_LinearShadowLeafs ();
|
||||
else R_RecursiveWorldNode( r_worldBrushModel->nodes, clipflags, dlightbits );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_MarkLeaves
|
||||
|
||||
Mark the leaves and nodes that are in the PVS for the current cluster
|
||||
=================
|
||||
===============
|
||||
*/
|
||||
static void R_MarkLeaves( void )
|
||||
void R_MarkLeaves( void )
|
||||
{
|
||||
byte *vis;
|
||||
int i, cluster;
|
||||
node_t *leaf, *parent;
|
||||
byte *vis;
|
||||
int i;
|
||||
mleaf_t *leaf, **pleaf;
|
||||
mnode_t *node;
|
||||
int cluster;
|
||||
|
||||
// lockpvs lets designers walk around to determine the
|
||||
// extent of the current pvs
|
||||
if( r_lockpvs->integer ) return;
|
||||
|
||||
// Current view cluster
|
||||
leaf = R_PointInLeaf( r_refdef.vieworg );
|
||||
cluster = leaf->cluster;
|
||||
|
||||
// if the cluster is the same and the area visibility matrix
|
||||
// hasn't changed, we don't need to mark everything again
|
||||
|
||||
// if r_showcluster was just turned on, remark everything
|
||||
if( r_viewCluster == cluster && !r_areabitsChanged && !r_showcluster->modified )
|
||||
if( Ref.refdef.rdflags & RDF_NOWORLDMODEL )
|
||||
return;
|
||||
if( r_oldViewCluster == r_viewCluster && ( Ref.refdef.rdflags & RDF_OLDAREABITS ) && !r_novis->integer && r_viewCluster != -1 )
|
||||
return;
|
||||
if( Ref.params & RP_SHADOWMAPVIEW )
|
||||
return;
|
||||
|
||||
if( r_showcluster->modified || r_showcluster->integer )
|
||||
{
|
||||
r_showcluster->modified = false;
|
||||
if( r_showcluster->integer )
|
||||
Msg( "cluster:%i area:%i\n", cluster, leaf->area );
|
||||
}
|
||||
// development aid to let you run around and see exactly where the pvs ends
|
||||
if( r_lockpvs->integer ) return;
|
||||
|
||||
r_visFrameCount++;
|
||||
r_viewCluster = cluster;
|
||||
|
||||
if( r_novis->integer || r_viewCluster == -1 )
|
||||
r_oldViewCluster = r_viewCluster;
|
||||
|
||||
if( r_novis->integer || r_viewCluster == -1 || !r_worldBrushModel->vis )
|
||||
{
|
||||
for( i = 0; i < r_worldModel->numNodes; i++ )
|
||||
{
|
||||
if( r_worldModel->nodes[i].contents != CONTENTS_SOLID )
|
||||
r_worldModel->nodes[i].visFrame = r_visFrameCount;
|
||||
}
|
||||
// mark everything
|
||||
for( pleaf = r_worldBrushModel->visleafs, leaf = *pleaf; leaf; leaf = *pleaf++ )
|
||||
leaf->visFrame = r_visFrameCount;
|
||||
for( i = 0, node = r_worldBrushModel->nodes; i < r_worldBrushModel->numnodes; i++, node++ )
|
||||
node->visFrame = r_visFrameCount;
|
||||
return;
|
||||
}
|
||||
|
||||
vis = R_ClusterPVS( r_viewCluster );
|
||||
|
||||
for( i = 0, leaf = r_worldModel->nodes; i < r_worldModel->numNodes; i++, leaf++ )
|
||||
for( pleaf = r_worldBrushModel->visleafs, leaf = *pleaf; leaf; leaf = *pleaf++ )
|
||||
{
|
||||
cluster = leaf->cluster;
|
||||
if( cluster < 0 || cluster >= r_worldModel->numClusters )
|
||||
continue;
|
||||
|
||||
// check general pvs
|
||||
if(!(vis[cluster>>3] & (1<<(cluster&7))))
|
||||
continue;
|
||||
|
||||
// check for door connection
|
||||
if((r_refdef.areabits[leaf->area>>3] & (1<<(leaf->area & 7 ))))
|
||||
continue; // not visible
|
||||
|
||||
parent = (node_t *)leaf;
|
||||
do {
|
||||
if( parent->visFrame == r_visFrameCount )
|
||||
break;
|
||||
parent->visFrame = r_visFrameCount;
|
||||
parent = parent->parent;
|
||||
} while( parent );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveWorldNode
|
||||
=================
|
||||
*/
|
||||
static void R_RecursiveWorldNode( node_t *node, int planeBits, int dlightBits )
|
||||
{
|
||||
cplane_t *plane;
|
||||
surface_t *surf, **mark;
|
||||
int i, clipped;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int newDlights[2];
|
||||
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
return; // solid
|
||||
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
return;
|
||||
|
||||
// if the bounding volume is outside the frustum, nothing
|
||||
// inside can be visible OPTIMIZE: don't do this all the way to leafs?
|
||||
// g-cont. because we throw node->firstface and node->numfaces !!!!
|
||||
if( planeBits )
|
||||
// check for door connected areas
|
||||
if( Ref.refdef.areabits )
|
||||
{
|
||||
for( i = 0, plane = r_frustum; i < 4; i++, plane++ )
|
||||
if(!( Ref.refdef.areabits[leaf->area>>3] & (1<<( leaf->area&7 ))))
|
||||
continue; // not visible
|
||||
}
|
||||
|
||||
if( vis[cluster>>3] & (1<<( cluster&7 )))
|
||||
{
|
||||
node = (mnode_t *)leaf;
|
||||
do
|
||||
{
|
||||
if(!(planeBits & (1<<i))) continue;
|
||||
|
||||
clipped = BoxOnPlaneSide( node->mins, node->maxs, plane );
|
||||
if( clipped == 2 ) return;
|
||||
if( clipped == 1 ) planeBits &= ~(1<<i);
|
||||
if( node->visFrame == r_visFrameCount )
|
||||
break;
|
||||
node->visFrame = r_visFrameCount;
|
||||
node = node->parent;
|
||||
}
|
||||
while( node );
|
||||
}
|
||||
|
||||
if( node->contents != CONTENTS_NODE ) break;
|
||||
|
||||
// node is just a decision point, so go down both sides
|
||||
// since we don't care about sort orders, just go positive to negative
|
||||
|
||||
// determine which dlights are needed
|
||||
newDlights[0] = 0;
|
||||
newDlights[1] = 0;
|
||||
if( dlightBits )
|
||||
{
|
||||
for( i = 0; i < r_numDLights; i++ )
|
||||
{
|
||||
dlight_t *dl;
|
||||
float dist;
|
||||
|
||||
if( dlightBits & (1<<i ))
|
||||
{
|
||||
dl = &r_dlights[i];
|
||||
dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist;
|
||||
|
||||
if( dist > -dl->intensity ) newDlights[0] |= (1<<i);
|
||||
if( dist < dl->intensity ) newDlights[1] |= (1<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recurse down the children, front side first
|
||||
R_RecursiveWorldNode( node->children[0], planeBits, newDlights[0] );
|
||||
|
||||
// tail recurse
|
||||
node = node->children[1];
|
||||
dlightBits = newDlights[1];
|
||||
}
|
||||
|
||||
// add to world mins/maxs
|
||||
AddPointToBounds( node->mins, r_worldMins, r_worldMaxs );
|
||||
AddPointToBounds( node->maxs, r_worldMins, r_worldMaxs );
|
||||
|
||||
r_stats.numLeafs++;
|
||||
|
||||
// add the individual surfaces
|
||||
for( i = 0, mark = node->firstMarkSurface; i < node->numMarkSurfaces; i++, mark++ )
|
||||
{
|
||||
surf = *mark;
|
||||
|
||||
if( surf->visFrame == r_frameCount )
|
||||
continue; // already added this surface from another leaf
|
||||
surf->visFrame = r_frameCount;
|
||||
|
||||
// FIXME: apply dynamic
|
||||
/*
|
||||
if( surf->dlightFrame != r_frameCount )
|
||||
{
|
||||
surf->dlightFrame = r_frameCount;
|
||||
surf->dlightBits = dlightBits;
|
||||
}
|
||||
else surf->dlightBits |= dlightBits;
|
||||
*/
|
||||
|
||||
// cull
|
||||
if( R_CullSurface( surf, r_refdef.vieworg, planeBits ))
|
||||
continue;
|
||||
|
||||
// clip sky surfaces
|
||||
if( surf->texInfo->flags & SURF_SKY )
|
||||
{
|
||||
R_ClipSkySurface( surf );
|
||||
continue;
|
||||
}
|
||||
|
||||
// add the surface
|
||||
R_AddSurfaceToList( surf, r_worldEntity );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AddWorldToList
|
||||
=================
|
||||
*/
|
||||
void R_AddWorldToList( void )
|
||||
{
|
||||
int planeBits;
|
||||
int dlightBits;
|
||||
|
||||
if( r_refdef.rdflags & RDF_NOWORLDMODEL )
|
||||
return;
|
||||
|
||||
if( !r_drawworld->integer )
|
||||
return;
|
||||
|
||||
if( r_nocull->integer ) planeBits = 0;
|
||||
else planeBits = MAX_CLIPFLAGS;
|
||||
|
||||
if( !r_dynamiclights->integer ) dlightBits = 0;
|
||||
else dlightBits = (1<<r_numDLights ) - 1;
|
||||
|
||||
// bump frame count
|
||||
r_frameCount++;
|
||||
|
||||
// auto cycle the world frame for texture animation
|
||||
r_worldEntity->frame = (int)(r_refdef.time * 2);
|
||||
r_stats.numDLights += r_numDLights;
|
||||
|
||||
// clear world mins/maxs
|
||||
ClearBounds( r_worldMins, r_worldMaxs );
|
||||
|
||||
R_MarkLeaves();
|
||||
R_ClearSky(); // S.T.A.L.K.E.R ClearSky
|
||||
|
||||
R_RecursiveWorldNode( r_worldModel->nodes, planeBits, dlightBits );
|
||||
R_AddSkyToList();
|
||||
}
|
||||
}
|
|
@ -6,8 +6,10 @@
|
|||
#include "r_local.h"
|
||||
#include "byteorder.h"
|
||||
#include "mathlib.h"
|
||||
#include "const.h"
|
||||
|
||||
#define NUM_TEXTURE_FILTERS (sizeof( r_textureFilters ) / sizeof( textureFilter_t ))
|
||||
#define TEXTURES_HASHSIZE 1024
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -16,8 +18,9 @@ typedef struct
|
|||
int mag;
|
||||
} textureFilter_t;
|
||||
|
||||
static texture_t r_textures[MAX_TEXTURES];
|
||||
static int r_numTextures;
|
||||
static texture_t *r_texturesHash[TEXTURES_HASHSIZE];
|
||||
static texture_t *r_textures[MAX_TEXTURES];
|
||||
static int r_numTextures;
|
||||
|
||||
static textureFilter_t r_textureFilters[] =
|
||||
{
|
||||
|
@ -94,8 +97,18 @@ texture_t *r_blackTexture;
|
|||
texture_t *r_rawTexture;
|
||||
texture_t *r_dlightTexture;
|
||||
texture_t *r_normalizeTexture;
|
||||
texture_t *r_cintexture; // cinematic texture
|
||||
texture_t *r_portaltexture; // portal view
|
||||
texture_t *r_portaltexture2; // refraction image for distortions
|
||||
texture_t *r_radarMap;
|
||||
texture_t *r_aroundMap;
|
||||
texture_t *r_particleTexture; // little dot for particles
|
||||
texture_t *r_blankBumpTexture;
|
||||
texture_t *r_fogTexture;
|
||||
texture_t *r_coronaTexture;
|
||||
texture_t *r_shadowmapTextures[MAX_SHADOWGROUPS];
|
||||
texture_t *r_lightmapTextures[MAX_TEXTURES];
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -138,10 +151,15 @@ void R_TextureFilter( void )
|
|||
// change all the existing texture objects
|
||||
for( i = 0; i < r_numTextures; i++ )
|
||||
{
|
||||
texture = &r_textures[i];
|
||||
texture = r_textures[i];
|
||||
GL_BindTexture( texture );
|
||||
|
||||
if( texture->flags & TF_MIPMAPS )
|
||||
if( texture->flags & TF_NOMIPMAP )
|
||||
{
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MIN_FILTER, r_textureFilterMag );
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MAG_FILTER, r_textureFilterMag );
|
||||
}
|
||||
else
|
||||
{
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MIN_FILTER, r_textureFilterMin );
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MAG_FILTER, r_textureFilterMag );
|
||||
|
@ -149,11 +167,6 @@ void R_TextureFilter( void )
|
|||
if( GL_Support( R_ANISOTROPY_EXT ))
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_texturefilteranisotropy->value );
|
||||
}
|
||||
else
|
||||
{
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MIN_FILTER, r_textureFilterMag );
|
||||
pglTexParameterf( texture->target, GL_TEXTURE_MAG_FILTER, r_textureFilterMag );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +233,7 @@ void R_TextureList_f( void )
|
|||
|
||||
for( i = 0; i < r_numTextures; i++ )
|
||||
{
|
||||
texture = &r_textures[i];
|
||||
texture = r_textures[i];
|
||||
|
||||
if( texture->target == GL_TEXTURE_2D )
|
||||
texels += (texture->width * texture->height);
|
||||
|
@ -247,9 +260,9 @@ void R_TextureList_f( void )
|
|||
break;
|
||||
}
|
||||
|
||||
if( texture->flags & TF_MIPMAPS )
|
||||
Msg(" yes ");
|
||||
else Msg(" no ");
|
||||
if( texture->flags & TF_NOMIPMAP )
|
||||
Msg(" no ");
|
||||
else Msg(" yes ");
|
||||
|
||||
if( texture->flags & TF_CLAMP )
|
||||
Msg( "clmp " );
|
||||
|
@ -288,7 +301,7 @@ void RB_ShowTextures( void )
|
|||
|
||||
for( i = j = 0; i < r_numTextures; i++ )
|
||||
{
|
||||
texture = &r_textures[i];
|
||||
texture = r_textures[i];
|
||||
|
||||
// FIXME: make cases for system, 2d, bsp, sprite and model textures
|
||||
|
||||
|
@ -334,7 +347,8 @@ void RB_ShowTextures( void )
|
|||
|
||||
=============================================================
|
||||
*/
|
||||
static byte *r_imagepool;
|
||||
static byte *r_imagepool; // scaled, rotated, converted images
|
||||
static byte *r_texpool; // loaded textures chain
|
||||
bool use_gl_extension = false;
|
||||
|
||||
/*
|
||||
|
@ -535,7 +549,7 @@ bool R_GetPixelFormat( rgbdata_t *pic, uint tex_flags, float bumpScale )
|
|||
w = (w+1)>>1, h = (h+1)>>1, d = (d+1)>>1;
|
||||
}
|
||||
|
||||
if( tex_flags & ( TF_IMAGE2D|TF_SKYSIDE|TF_SKYSIDE_FLIP ))
|
||||
if( tex_flags & ( TF_NOMIPMAP|TF_SKYBOX ))
|
||||
{
|
||||
// don't build mips for sky and hud pics
|
||||
image_desc.flags &= ~IMAGE_GEN_MIPS;
|
||||
|
@ -546,12 +560,10 @@ bool R_GetPixelFormat( rgbdata_t *pic, uint tex_flags, float bumpScale )
|
|||
// .dds, .wal or .mip image
|
||||
image_desc.flags &= ~IMAGE_GEN_MIPS;
|
||||
image_desc.MipCount = pic->numMips;
|
||||
image_desc.tflags |= TF_MIPMAPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// so it normal texture without mips
|
||||
image_desc.tflags |= TF_MIPMAPS;
|
||||
image_desc.flags |= IMAGE_GEN_MIPS;
|
||||
image_desc.MipCount = pic->numMips;
|
||||
}
|
||||
|
@ -561,7 +573,7 @@ bool R_GetPixelFormat( rgbdata_t *pic, uint tex_flags, float bumpScale )
|
|||
|
||||
// check for permanent images
|
||||
if( image_desc.format == PF_RGBA_GN ) image_desc.tflags |= TF_STATIC;
|
||||
if( tex_flags & TF_IMAGE2D ) image_desc.tflags |= TF_STATIC;
|
||||
if( tex_flags & TF_NOMIPMAP ) image_desc.tflags |= TF_STATIC;
|
||||
}
|
||||
|
||||
// restore temp dimensions
|
||||
|
@ -667,7 +679,6 @@ R_ShutdownTextures
|
|||
*/
|
||||
void R_ShutdownTextures( void )
|
||||
{
|
||||
texture_t *texture;
|
||||
int i;
|
||||
|
||||
if( gl_config.texRectangle )
|
||||
|
@ -675,9 +686,11 @@ void R_ShutdownTextures( void )
|
|||
|
||||
for( i = 0; i < r_numTextures; i++ )
|
||||
{
|
||||
texture = &r_textures[i];
|
||||
pglDeleteTextures( 1, &texture->texnum );
|
||||
if( !r_textures[i] ) continue;
|
||||
pglDeleteTextures( 1, &r_textures[i]->texnum );
|
||||
}
|
||||
|
||||
memset( r_texturesHash, 0, sizeof( r_texturesHash ));
|
||||
memset( r_textures, 0, sizeof( r_textures ));
|
||||
r_numTextures = 0;
|
||||
}
|
||||
|
@ -689,11 +702,10 @@ void R_ShutdownTextures( void )
|
|||
*/
|
||||
static void R_CreateBuiltInTextures( void )
|
||||
{
|
||||
byte data2D[256*256*4];
|
||||
rgbdata_t r_generic;
|
||||
vec3_t normal;
|
||||
int i, x, y;
|
||||
float s, t;
|
||||
static byte data2D[256*256*4];
|
||||
rgbdata_t r_generic;
|
||||
vec3_t normal;
|
||||
int i, x, y;
|
||||
|
||||
// FIXME: too many hardcoded values in this function
|
||||
|
||||
|
@ -746,9 +758,10 @@ static void R_CreateBuiltInTextures( void )
|
|||
|
||||
if( GL_Support( R_TEXTURECUBEMAP_EXT ))
|
||||
{
|
||||
byte data3D[128*128*4*6]; // full cubemap size
|
||||
byte *dataCM = (byte *)data3D;
|
||||
|
||||
static byte data3D[128*128*4*6]; // 384 kByte (full cubemap size)
|
||||
byte *dataCM = (byte *)data3D;
|
||||
float s, t;
|
||||
|
||||
// normalize texture
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
|
@ -813,7 +826,8 @@ void R_InitTextures( void )
|
|||
int i, j;
|
||||
float f;
|
||||
|
||||
r_imagepool = Mem_AllocPool( "Texture Pool" ); // for scaling and resampling
|
||||
r_imagepool = Mem_AllocPool( "Image Pool" ); // for scaling and resampling
|
||||
r_texpool = Mem_AllocPool( "Texture Pool" );
|
||||
pglGetIntegerv( GL_MAX_TEXTURE_SIZE, &gl_config.max_2d_texture_size );
|
||||
|
||||
r_numTextures = 0;
|
||||
|
@ -859,8 +873,8 @@ bool R_ResampleTexture( uint *in, int inwidth, int inheight, uint *out, int outw
|
|||
if( outheight == 0 || outwidth == 0 ) return false;
|
||||
|
||||
// apply intensity if needed
|
||||
if((image_desc.tflags & TF_MIPMAPS) && !(image_desc.tflags & TF_NORMALMAP))
|
||||
R_IntensityScaleTexture( in, inwidth, inheight );
|
||||
if(!(image_desc.tflags & TF_NORMALMAP|TF_NOMIPMAP))
|
||||
R_IntensityScaleTexture( in, inwidth, inheight );
|
||||
|
||||
if( image_desc.tflags & TF_LUMA )
|
||||
{
|
||||
|
@ -1634,7 +1648,7 @@ bool R_LoadImageFloat( byte *data, GLuint target )
|
|||
|
||||
/*
|
||||
===============
|
||||
R_FindImage
|
||||
R_FindTexture
|
||||
|
||||
Finds or loads the given image
|
||||
===============
|
||||
|
@ -1643,22 +1657,26 @@ texture_t *R_FindTexture( const char *name, const byte *buffer, size_t size, uin
|
|||
{
|
||||
texture_t *image;
|
||||
rgbdata_t *pic = NULL;
|
||||
int i;
|
||||
uint hashKey;
|
||||
|
||||
if( !name ) return r_defaultTexture;
|
||||
|
||||
// look for it
|
||||
for( i = 0; i < r_numTextures; i++ )
|
||||
|
||||
// see if already loaded
|
||||
hashKey = Com_HashKey( name, TEXTURES_HASHSIZE );
|
||||
|
||||
for( image = r_texturesHash[hashKey]; image; image = image->hash )
|
||||
{
|
||||
image = &r_textures[i];
|
||||
if( !com.stricmp( name, image->name ))
|
||||
if( !com.stricmp( image->name, name ))
|
||||
{
|
||||
// prolonge registration
|
||||
image->registration_sequence = registration_sequence;
|
||||
return image;
|
||||
if( image->flags == flags && image->bumpScale == bumpScale )
|
||||
{
|
||||
// prolonge registration
|
||||
image->sequence = registration_sequence;
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pic = FS_LoadImage( name, buffer, size ); // loading form disk or buffer
|
||||
if( pic )
|
||||
{
|
||||
|
@ -1729,25 +1747,28 @@ texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, uint flags, float bu
|
|||
texture_t *image;
|
||||
bool iResult = true;
|
||||
int i, numsides = 1, width, height;
|
||||
uint offset = 0, target = GL_TEXTURE_2D;
|
||||
uint hashKey, offset = 0, target = GL_TEXTURE_2D;
|
||||
byte *buf;
|
||||
|
||||
// find a free texture_t
|
||||
for( i = 0; i < r_numTextures; i++ )
|
||||
{
|
||||
image = &r_textures[i];
|
||||
if( !r_textures[i] ) break;
|
||||
}
|
||||
|
||||
if( i == r_numTextures )
|
||||
{
|
||||
// allocate a new one
|
||||
if( r_numTextures == MAX_TEXTURES )
|
||||
{
|
||||
MsgDev(D_ERROR, "R_LoadTexture: r_textures limit is out\n");
|
||||
return r_defaultTexture;
|
||||
}
|
||||
r_numTextures++;
|
||||
}
|
||||
|
||||
image = &r_textures[r_numTextures++];
|
||||
if( com.strlen( name ) >= sizeof(image->name)) MsgDev( D_WARN, "R_LoadImage: \"%s\" is too long", name);
|
||||
r_textures[i] = image = Mem_Alloc( r_texpool, sizeof( texture_t ));
|
||||
if( com.strlen( name ) >= sizeof(image->name)) MsgDev( D_WARN, "R_LoadImage: \"%s\" is too long", name );
|
||||
|
||||
// nothing to load
|
||||
if( !pic || !pic->buffer )
|
||||
|
@ -1755,24 +1776,18 @@ texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, uint flags, float bu
|
|||
// create notexture with another name
|
||||
Mem_Copy( image, r_defaultTexture, sizeof( texture_t ));
|
||||
com.strncpy( image->name, name, sizeof( image->name ));
|
||||
image->registration_sequence = registration_sequence;
|
||||
image->sequence = registration_sequence;
|
||||
return image;
|
||||
}
|
||||
|
||||
com.strncpy( image->name, name, sizeof( image->name ));
|
||||
image->registration_sequence = registration_sequence;
|
||||
|
||||
image->sequence = registration_sequence;
|
||||
|
||||
if( flags & TF_CUBEMAP )
|
||||
{
|
||||
if( pic->flags & IMAGE_CUBEMAP )
|
||||
{
|
||||
numsides = 6;
|
||||
if( pic->flags & IMAGE_CUBEMAP_FLIP )
|
||||
{
|
||||
// change draworder for not packed cubemaps
|
||||
flags &= ~TF_CUBEMAP;
|
||||
flags |= TF_CUBEMAP_FLIP;
|
||||
}
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
|
||||
}
|
||||
else
|
||||
|
@ -1781,26 +1796,6 @@ texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, uint flags, float bu
|
|||
flags &= ~TF_CUBEMAP;
|
||||
}
|
||||
}
|
||||
else if( flags & TF_SKYBOX )
|
||||
{
|
||||
//FIXME: get to work
|
||||
if( pic->flags & IMAGE_CUBEMAP )
|
||||
{
|
||||
numsides = 6;
|
||||
if( pic->flags & IMAGE_CUBEMAP_FLIP )
|
||||
{
|
||||
// change draworder for skies
|
||||
flags |= TF_SKYSIDE_FLIP;
|
||||
}
|
||||
else flags |= TF_SKYSIDE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MsgDev( D_WARN, "texture %s it's not a skybox set\n", name );
|
||||
flags &= ~TF_SKYBOX;
|
||||
}
|
||||
Host_Error("TF_SKYBOX not implemeneted\n");
|
||||
}
|
||||
|
||||
image->width = width = pic->width;
|
||||
image->height = height = pic->height;
|
||||
|
@ -1811,6 +1806,7 @@ texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, uint flags, float bu
|
|||
R_GetPixelFormat( pic, flags, bumpScale );
|
||||
|
||||
pglGenTextures( 1, &image->texnum );
|
||||
|
||||
image->target = image_desc.glTarget;
|
||||
image->flags = image_desc.tflags; // merged by R_GetPixelFormat
|
||||
image->type = image_desc.format;
|
||||
|
@ -1827,6 +1823,13 @@ texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, uint flags, float bu
|
|||
else MsgDev( D_LOAD, "%s [%s] \n", name, PFDesc[image_desc.format].name );
|
||||
R_UploadTexture( buf, pic->type, target + i );
|
||||
}
|
||||
|
||||
// add to hash table
|
||||
hashKey = Com_HashKey( image->name, TEXTURES_HASHSIZE );
|
||||
|
||||
image->hash = r_texturesHash[hashKey];
|
||||
r_texturesHash[hashKey] = image;
|
||||
|
||||
// check for errors
|
||||
if( !iResult )
|
||||
{
|
||||
|
@ -1848,16 +1851,18 @@ void R_ImageFreeUnused( void )
|
|||
{
|
||||
texture_t *image;
|
||||
int i;
|
||||
return; //FIXME
|
||||
for( i = 0, image = r_textures; i < r_numTextures; i++, image++ )
|
||||
|
||||
for( i = 0; i < r_numTextures; i++ )
|
||||
{
|
||||
// used this sequence
|
||||
if( image->registration_sequence == registration_sequence ) continue;
|
||||
if( image->flags & TF_STATIC || !image->name[0] ) // static or already freed
|
||||
continue;
|
||||
Msg("release texture %s\n", image->name );
|
||||
image = r_textures[i];
|
||||
|
||||
if( !image || image->flags & TF_STATIC ) continue;
|
||||
if( image->sequence == registration_sequence ) continue;
|
||||
|
||||
Msg("release texture %s[%i != sequence %i]\n", image->name, image->sequence, registration_sequence );
|
||||
pglDeleteTextures( 1, &image->texnum );
|
||||
memset( image, 0, sizeof( *image ));
|
||||
Mem_Free( image );
|
||||
image = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
293
render/r_utils.c
293
render/r_utils.c
|
@ -5,134 +5,51 @@
|
|||
|
||||
#include "r_local.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
vec3_t axisDefault[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
|
||||
#include "matrixlib.h"
|
||||
|
||||
/*
|
||||
=================
|
||||
AxisCopy
|
||||
=================
|
||||
=============
|
||||
R_TransformWorldToScreen
|
||||
=============
|
||||
*/
|
||||
void AxisCopy( const vec3_t in[3], vec3_t out[3] )
|
||||
void R_TransformWorldToScreen( vec3_t in, vec3_t out )
|
||||
{
|
||||
out[0][0] = in[0][0];
|
||||
out[0][1] = in[0][1];
|
||||
out[0][2] = in[0][2];
|
||||
out[1][0] = in[1][0];
|
||||
out[1][1] = in[1][1];
|
||||
out[1][2] = in[1][2];
|
||||
out[2][0] = in[2][0];
|
||||
out[2][1] = in[2][1];
|
||||
out[2][2] = in[2][2];
|
||||
vec4_t temp, temp2;
|
||||
|
||||
Vector4Set( temp, in[0], in[1], in[2], 1.0f );
|
||||
Matrix4x4_Transform( Ref.worldProjectionMatrix, temp, temp2 );
|
||||
|
||||
if( !temp2[3] ) return;
|
||||
|
||||
out[0] = (temp2[0] / temp2[3] + 1.0f) * 0.5f * Ref.refdef.rect.width;
|
||||
out[1] = (temp2[1] / temp2[3] + 1.0f) * 0.5f * Ref.refdef.rect.height;
|
||||
out[2] = (temp2[2] / temp2[3] + 1.0f) * 0.5f;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
AxisClear
|
||||
=================
|
||||
=============
|
||||
R_TransformVectorToScreen
|
||||
=============
|
||||
*/
|
||||
void AxisClear( vec3_t axis[3] )
|
||||
void R_TransformVectorToScreen( const refdef_t *rd, const vec3_t in, vec2_t out )
|
||||
{
|
||||
axis[0][0] = 1;
|
||||
axis[0][1] = 0;
|
||||
axis[0][2] = 0;
|
||||
axis[1][0] = 0;
|
||||
axis[1][1] = 1;
|
||||
axis[1][2] = 0;
|
||||
axis[2][0] = 0;
|
||||
axis[2][1] = 0;
|
||||
axis[2][2] = 1;
|
||||
}
|
||||
matrix4x4 p, m;
|
||||
vec4_t temp, temp2;
|
||||
|
||||
/*
|
||||
=================
|
||||
AnglesToAxis
|
||||
=================
|
||||
*/
|
||||
void AnglesToAxis ( const vec3_t angles )
|
||||
{
|
||||
static float sp, sy, sr, cp, cy, cr;
|
||||
float angle;
|
||||
if( !rd || !in || !out ) return;
|
||||
|
||||
angle = DEG2RAD(angles[PITCH]);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = DEG2RAD(angles[YAW]);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = DEG2RAD(angles[ROLL]);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
Vector4Set( temp, in[0], in[1], in[2], 1.0f );
|
||||
|
||||
r_forward[0] = cp*cy;
|
||||
r_forward[1] = cp*sy;
|
||||
r_forward[2] = -sp;
|
||||
r_right[0] = sr*sp*cy+cr*-sy;
|
||||
r_right[1] = sr*sp*sy+cr*cy;
|
||||
r_right[2] = sr*cp;
|
||||
r_up[0] = cr*sp*cy+-sr*-sy;
|
||||
r_up[1] = cr*sp*sy+-sr*cy;
|
||||
r_up[2] = cr*cp;
|
||||
}
|
||||
R_SetupProjectionMatrix( rd, p );
|
||||
R_SetupModelViewMatrix( rd, m );
|
||||
|
||||
/*
|
||||
=================
|
||||
AnglesToAxis
|
||||
=================
|
||||
*/
|
||||
void AnglesToAxisPrivate (const vec3_t angles, vec3_t axis[3])
|
||||
{
|
||||
Matrix4x4_Transform( m, temp, temp2 );
|
||||
Matrix4x4_Transform( p, temp2, temp );
|
||||
|
||||
static float sp, sy, sr, cp, cy, cr;
|
||||
float angle;
|
||||
if( !temp[3] ) return;
|
||||
|
||||
angle = DEG2RAD(angles[PITCH]);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = DEG2RAD(angles[YAW]);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = DEG2RAD(angles[ROLL]);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
axis[0][0] = cp*cy;
|
||||
axis[0][1] = cp*sy;
|
||||
axis[0][2] = -sp;
|
||||
axis[1][0] = sr*sp*cy+cr*-sy;
|
||||
axis[1][1] = sr*sp*sy+cr*cy;
|
||||
axis[1][2] = sr*cp;
|
||||
axis[2][0] = cr*sp*cy+-sr*-sy;
|
||||
axis[2][1] = cr*sp*sy+-sr*cy;
|
||||
axis[2][2] = cr*cp;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
AxisCompare
|
||||
=================
|
||||
*/
|
||||
bool AxisCompare( const vec3_t axis1[3], const vec3_t axis2[3] )
|
||||
{
|
||||
if (axis1[0][0] != axis2[0][0] || axis1[0][1] != axis2[0][1] || axis1[0][2] != axis2[0][2])
|
||||
return false;
|
||||
if (axis1[1][0] != axis2[1][0] || axis1[1][1] != axis2[1][1] || axis1[1][2] != axis2[1][2])
|
||||
return false;
|
||||
if (axis1[2][0] != axis2[2][0] || axis1[2][1] != axis2[2][1] || axis1[2][2] != axis2[2][2])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorRotate
|
||||
=================
|
||||
*/
|
||||
void VectorRotate ( const vec3_t v, const vec3_t matrix[3], vec3_t out )
|
||||
{
|
||||
out[0] = v[0]*matrix[0][0] + v[1]*matrix[0][1] + v[2]*matrix[0][2];
|
||||
out[1] = v[0]*matrix[1][0] + v[1]*matrix[1][1] + v[2]*matrix[1][2];
|
||||
out[2] = v[0]*matrix[2][0] + v[1]*matrix[2][1] + v[2]*matrix[2][2];
|
||||
out[0] = rd->rect.x + (temp[0] / temp[3] + 1.0f) * rd->rect.width * 0.5f;
|
||||
out[1] = rd->rect.y + (temp[1] / temp[3] + 1.0f) * rd->rect.height * 0.5f;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -237,4 +154,154 @@ uint ShortToFloat( word y )
|
|||
e = e + (127 - 15);
|
||||
m = m << 13;
|
||||
return (s << 31) | (e << 23) | m; // Assemble s, e and m.
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Patch_FlatnessTest
|
||||
|
||||
===============
|
||||
*/
|
||||
static int Patch_FlatnessTest( float maxflat2, const float *point0, const float *point1, const float *point2 )
|
||||
{
|
||||
float d;
|
||||
int ft0, ft1;
|
||||
vec3_t t, n;
|
||||
vec3_t v1, v2, v3;
|
||||
|
||||
VectorSubtract( point2, point0, n );
|
||||
if( !VectorNormalizeLength( n ))
|
||||
return 0;
|
||||
|
||||
VectorSubtract( point1, point0, t );
|
||||
d = -DotProduct( t, n );
|
||||
VectorMA( t, d, n, t );
|
||||
if( DotProduct( t, t ) < maxflat2 )
|
||||
return 0;
|
||||
|
||||
VectorAverage( point1, point0, v1 );
|
||||
VectorAverage( point2, point1, v2 );
|
||||
VectorAverage( v1, v2, v3 );
|
||||
|
||||
ft0 = Patch_FlatnessTest( maxflat2, point0, v1, v3 );
|
||||
ft1 = Patch_FlatnessTest( maxflat2, v3, v2, point2 );
|
||||
|
||||
return 1 + (int)( floor( max( ft0, ft1 )) + 0.5f );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Patch_GetFlatness
|
||||
|
||||
===============
|
||||
*/
|
||||
void Patch_GetFlatness( float maxflat, const float *points, int comp, const int *patch_cp, int *flat )
|
||||
{
|
||||
int i, p, u, v;
|
||||
float maxflat2 = maxflat * maxflat;
|
||||
|
||||
flat[0] = flat[1] = 0;
|
||||
|
||||
for( v = 0; v < patch_cp[1] - 1; v += 2 )
|
||||
{
|
||||
for( u = 0; u < patch_cp[0] - 1; u += 2 )
|
||||
{
|
||||
p = v * patch_cp[0] + u;
|
||||
|
||||
i = Patch_FlatnessTest( maxflat2, &points[p*comp], &points[( p+1 )*comp], &points[( p+2 )*comp] );
|
||||
flat[0] = max( flat[0], i );
|
||||
i = Patch_FlatnessTest( maxflat2, &points[( p+patch_cp[0] )*comp], &points[( p+patch_cp[0]+1 )*comp], &points[( p+patch_cp[0]+2 )*comp] );
|
||||
flat[0] = max( flat[0], i );
|
||||
i = Patch_FlatnessTest( maxflat2, &points[( p+2*patch_cp[0] )*comp], &points[( p+2*patch_cp[0]+1 )*comp], &points[( p+2*patch_cp[0]+2 )*comp] );
|
||||
flat[0] = max( flat[0], i );
|
||||
|
||||
i = Patch_FlatnessTest( maxflat2, &points[p*comp], &points[( p+patch_cp[0] )*comp], &points[( p+2*patch_cp[0] )*comp] );
|
||||
flat[1] = max( flat[1], i );
|
||||
i = Patch_FlatnessTest( maxflat2, &points[( p+1 )*comp], &points[( p+patch_cp[0]+1 )*comp], &points[( p+2*patch_cp[0]+1 )*comp] );
|
||||
flat[1] = max( flat[1], i );
|
||||
i = Patch_FlatnessTest( maxflat2, &points[( p+2 )*comp], &points[( p+patch_cp[0]+2 )*comp], &points[( p+2*patch_cp[0]+2 )*comp] );
|
||||
flat[1] = max( flat[1], i );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Patch_Evaluate_QuadricBezier
|
||||
|
||||
===============
|
||||
*/
|
||||
static void Patch_Evaluate_QuadricBezier( float t, const vec_t *point0, const vec_t *point1, const vec_t *point2, vec_t *out, int comp )
|
||||
{
|
||||
int i;
|
||||
vec_t qt = t * t;
|
||||
vec_t dt = 2.0f * t, tt, tt2;
|
||||
|
||||
tt = 1.0f - dt + qt;
|
||||
tt2 = dt - 2.0f * qt;
|
||||
|
||||
for( i = 0; i < comp; i++ )
|
||||
out[i] = point0[i] * tt + point1[i] * tt2 + point2[i] * qt;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Patch_Evaluate
|
||||
|
||||
===============
|
||||
*/
|
||||
void Patch_Evaluate( const vec_t *p, int *numcp, const int *tess, vec_t *dest, int comp )
|
||||
{
|
||||
int num_patches[2], num_tess[2];
|
||||
int index[3], dstpitch, i, u, v, x, y;
|
||||
float s, t, step[2];
|
||||
vec_t *tvec, *tvec2;
|
||||
const vec_t *pv[3][3];
|
||||
vec4_t v1, v2, v3;
|
||||
|
||||
num_patches[0] = numcp[0] / 2;
|
||||
num_patches[1] = numcp[1] / 2;
|
||||
dstpitch = ( num_patches[0] * tess[0] + 1 ) * comp;
|
||||
|
||||
step[0] = 1.0f / (float)tess[0];
|
||||
step[1] = 1.0f / (float)tess[1];
|
||||
|
||||
for( v = 0; v < num_patches[1]; v++ )
|
||||
{
|
||||
// last patch has one more row
|
||||
if( v < num_patches[1] - 1 )
|
||||
num_tess[1] = tess[1];
|
||||
else num_tess[1] = tess[1] + 1;
|
||||
|
||||
for( u = 0; u < num_patches[0]; u++ )
|
||||
{
|
||||
// last patch has one more column
|
||||
if( u < num_patches[0] - 1 )
|
||||
num_tess[0] = tess[0];
|
||||
else num_tess[0] = tess[0] + 1;
|
||||
|
||||
index[0] = ( v * numcp[0] + u ) * 2;
|
||||
index[1] = index[0] + numcp[0];
|
||||
index[2] = index[1] + numcp[0];
|
||||
|
||||
// current 3x3 patch control points
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
pv[i][0] = &p[( index[0]+i ) * comp];
|
||||
pv[i][1] = &p[( index[1]+i ) * comp];
|
||||
pv[i][2] = &p[( index[2]+i ) * comp];
|
||||
}
|
||||
|
||||
tvec = dest + v * tess[1] * dstpitch + u * tess[0] * comp;
|
||||
for( y = 0, t = 0.0f; y < num_tess[1]; y++, t += step[1], tvec += dstpitch )
|
||||
{
|
||||
Patch_Evaluate_QuadricBezier( t, pv[0][0], pv[0][1], pv[0][2], v1, comp );
|
||||
Patch_Evaluate_QuadricBezier( t, pv[1][0], pv[1][1], pv[1][2], v2, comp );
|
||||
Patch_Evaluate_QuadricBezier( t, pv[2][0], pv[2][1], pv[2][2], v3, comp );
|
||||
|
||||
for( x = 0, tvec2 = tvec, s = 0.0f; x < num_tess[0]; x++, s += step[0], tvec2 += comp )
|
||||
Patch_Evaluate_QuadricBezier( s, v1, v2, v3, tvec2, comp );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -126,6 +126,10 @@ SOURCE=.\r_bloom.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_cull.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_draw.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -138,6 +142,10 @@ SOURCE=.\r_main.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_mesh.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_model.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -146,6 +154,10 @@ SOURCE=.\r_opengl.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_poly.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_program.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
19
todo.log
19
todo.log
|
@ -20,7 +20,24 @@ GLOBAL:
|
|||
|
||||
îïåðàöèÿ "Îòëàäêà: bsp 48
|
||||
0. îòëàäêà qbsp3
|
||||
1. починить подсчет строк для Com_GetToken
|
||||
1. починить подсчет строк для Com_GetToken OK
|
||||
2. подправить рендер с учетом новых констатнт
|
||||
3. переписать менеджер текстур на рендере
|
||||
4. переписать загрузчик текстур с учетом новой идеологии
|
||||
5. раз и навсегда пофиксить R_ImageFreeUnused
|
||||
6. создать Com_Assert в виде дефайна Sys_Break
|
||||
7. Заюзать матрицы 3x3 на сервере
|
||||
|
||||
Новый загрузчик текстур:
|
||||
0. сравнить скорость загрузки видеокартой\софтверным загрузчиком
|
||||
1. все картинки при загрузке распаковываются в PF_RGB_24 (если нет альфы), либо в PF_RGBA_32 (если альфа есть)
|
||||
2. все кубемапы собираются в один большой архив из PF_RGB_24 * 6 (у кубемапов альфы никогда не бывает)
|
||||
3. доступ к стороне осуществляется при помощи функции FS_GetCubemapSide, после загрузки при помощи FS_LoadImage
|
||||
4. доступ осуществляется либо по номеру. либо по суффиксу (но по номеру, ИМХО удобнее)
|
||||
5. при некоторых инстанциях проиндексированные изображения не распаковываются в 32 и 24 битные, поскольку
|
||||
их необходимо сохранить в восьмибитном формате.
|
||||
6. DDS должен разжиматься весь в launch.dll по идее
|
||||
7. Расширение matrixlib - Matrix3x3
|
||||
|
||||
1. r_backend.c:1335
|
||||
2. r_backend.c:1338
|
||||
|
|
Reference in New Issue