13 Oct 2008

This commit is contained in:
g-cont 2008-10-13 00:00:00 +04:00 committed by Alibek Omarov
parent c735574f4c
commit 92c5a0e536
62 changed files with 12898 additions and 5854 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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 );

View File

@ -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];

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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 ));
}
}
}

View File

@ -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;

View File

@ -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

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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 );

View File

@ -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++;

View File

@ -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 --

View File

@ -625,7 +625,7 @@ void PF_stopcredits( void )
=========
PF_creditsactive
void creditsactive( void )
float creditsactive( void )
=========
*/
void PF_creditsactive( void )

View File

@ -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
}
/*

View File

@ -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;

View File

@ -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 );
//

View File

@ -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;
}

View File

@ -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 "";

View File

@ -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 );

View File

@ -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

View File

@ -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;

View File

@ -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 );

View File

@ -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 );

View File

@ -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 )

View File

@ -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

View File

@ -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];

View File

@ -60,7 +60,7 @@ bool CM_ParseMaterial( void )
cm.num_materials++;
// material will be parsed sucessfully
// done
return true;
}

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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;
/*
==============================================================================

View File

@ -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 );

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

493
render/r_cull.c Normal file
View File

@ -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;
}

View File

@ -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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1187
render/r_mesh.c Normal file

File diff suppressed because it is too large Load Diff

171
render/r_meshbuffer.h Normal file
View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
{

777
render/r_poly.c Normal file
View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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" );

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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 );
}
}
}
}

View File

@ -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

View File

@ -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