diff --git a/Makefile b/Makefile index d7d4c59ec..2e18522b0 100644 --- a/Makefile +++ b/Makefile @@ -2295,6 +2295,7 @@ Q3CGOBJ = \ $(B)/$(BASEGAME)/cgame/cg_servercmds.o \ $(B)/$(BASEGAME)/cgame/cg_snapshot.o \ $(B)/$(BASEGAME)/cgame/cg_spawn.o \ + $(B)/$(BASEGAME)/cgame/cg_surface.o \ $(B)/$(BASEGAME)/cgame/cg_syscalls.o \ $(B)/$(BASEGAME)/cgame/cg_view.o \ $(B)/$(BASEGAME)/cgame/cg_weapons.o \ @@ -2388,6 +2389,7 @@ MPCGOBJ = \ $(B)/$(MISSIONPACK)/cgame/cg_servercmds.o \ $(B)/$(MISSIONPACK)/cgame/cg_snapshot.o \ $(B)/$(MISSIONPACK)/cgame/cg_spawn.o \ + $(B)/$(MISSIONPACK)/cgame/cg_surface.o \ $(B)/$(MISSIONPACK)/cgame/cg_syscalls.o \ $(B)/$(MISSIONPACK)/cgame/cg_view.o \ $(B)/$(MISSIONPACK)/cgame/cg_weapons.o \ diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index cb3ce68b6..bd6ec29dd 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -1663,6 +1663,16 @@ void CG_RestoreSnapshot( void ); playerState_t *CG_LocalClientPlayerStateForClientNum( int clientNum ); +// +// cg_surface.c +// +qboolean CG_AddCustomSurface( const refEntity_t *re ); +void CG_SurfaceSprite( const refEntity_t *re ); +void CG_SurfaceRailRings( const refEntity_t *re ); +void CG_SurfaceRailCore( const refEntity_t *re ); +void CG_SurfaceLightningBolt( const refEntity_t *re ); +void CG_SurfaceBeam( const refEntity_t *re ); + // // cg_spawn.c // diff --git a/code/cgame/cg_public.h b/code/cgame/cg_public.h index 964b656c7..94bab25b0 100644 --- a/code/cgame/cg_public.h +++ b/code/cgame/cg_public.h @@ -36,7 +36,7 @@ Suite 120, Rockville, Maryland 20850 USA. // major 0 means each minor is an API break. // major > 0 means each major is an API break and each minor extends API. #define CG_API_MAJOR_VERSION 0 -#define CG_API_MINOR_VERSION 3 +#define CG_API_MINOR_VERSION 4 #define CMD_BACKUP 64 @@ -271,6 +271,7 @@ typedef enum { CG_R_ADDPOLYBUFFERTOSCENE, CG_R_ALLOCSKINSURFACE, CG_R_ADDSKINTOFRAME, + CG_R_ADDPOLYREFENTITYTOSCENE, // note: these were not originally available in ui CG_R_LOADWORLDMAP = 350, diff --git a/code/cgame/cg_surface.c b/code/cgame/cg_surface.c new file mode 100644 index 000000000..8b2bc0f42 --- /dev/null +++ b/code/cgame/cg_surface.c @@ -0,0 +1,415 @@ +/* +=========================================================================== +Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. + +This file is part of Spearmint Source Code. + +Spearmint Source Code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +Spearmint Source Code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Spearmint Source Code. If not, see . + +In addition, Spearmint Source Code is also subject to certain additional terms. +You should have received a copy of these additional terms immediately following +the terms and conditions of the GNU General Public License. If not, please +request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional +terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., +Suite 120, Rockville, Maryland 20850 USA. +=========================================================================== +*/ +// +// cg_surface.c -- procedurally generated surfaces + +#include "cg_local.h" + +/* +============== +CG_AddCustomSurface +============== +*/ +qboolean CG_AddCustomSurface( const refEntity_t *re ) { + switch ( re->reType ) { +#if 0 // ZTM: sprites don't mirror correctly because they're one sided, also requires using cg.refdef in UI code for player sprites + case RT_SPRITE: + CG_SurfaceSprite( re ); + return qtrue; +#endif + case RT_RAIL_RINGS: + CG_SurfaceRailRings( re ); + return qtrue; + case RT_RAIL_CORE: + CG_SurfaceRailCore( re ); + return qtrue; + case RT_LIGHTNING: + CG_SurfaceLightningBolt( re ); + return qtrue; + case RT_BEAM: + CG_SurfaceBeam( re ); + return qtrue; + default: + return qfalse; + } +} + +/* +============== +CG_SurfaceSprite +============== +*/ +void CG_SurfaceSprite( const refEntity_t *e ) { + polyVert_t verts[4]; + vec3_t left, up; + refEntity_t re; + int j; + + re = *e; + re.reType = RT_POLY; + + // FIXME: cg.refdef.viewaxis doesn't work in UI drawing! + if ( re.rotation == 0 ) { + VectorScale( cg.refdef.viewaxis[1], re.radius, left ); + VectorScale( cg.refdef.viewaxis[2], re.radius, up ); + } else { + float s, c; + float ang; + + ang = M_PI * re.rotation / 180; + s = sin( ang ); + c = cos( ang ); + + VectorScale( cg.refdef.viewaxis[1], c * re.radius, left ); + VectorMA( left, -s * re.radius, cg.refdef.viewaxis[2], left ); + + VectorScale( cg.refdef.viewaxis[2], c * re.radius, up ); + VectorMA( up, s * re.radius, cg.refdef.viewaxis[1], up ); + } + + // + verts[0].xyz[0] = re.origin[0] + left[0] + up[0]; + verts[0].xyz[1] = re.origin[1] + left[1] + up[1]; + verts[0].xyz[2] = re.origin[2] + left[2] + up[2]; + + verts[1].xyz[0] = re.origin[0] - left[0] + up[0]; + verts[1].xyz[1] = re.origin[1] - left[1] + up[1]; + verts[1].xyz[2] = re.origin[2] - left[2] + up[2]; + + verts[2].xyz[0] = re.origin[0] - left[0] - up[0]; + verts[2].xyz[1] = re.origin[1] - left[1] - up[1]; + verts[2].xyz[2] = re.origin[2] - left[2] - up[2]; + + verts[3].xyz[0] = re.origin[0] + left[0] - up[0]; + verts[3].xyz[1] = re.origin[1] + left[1] - up[1]; + verts[3].xyz[2] = re.origin[2] + left[2] - up[2]; + + // standard square texture coordinates + for ( j = 0; j < 4; j++ ) { + verts[j].st[0] = ( j && j != 3 ); + verts[j].st[1] = ( j < 2 ); + + * ( unsigned int * )&verts[j].modulate = * ( unsigned int * )re.shaderRGBA; + } + + trap_R_AddPolyRefEntityToScene( &re, 4, verts, 1 ); +} + +/* +============== +CG_DoRailDiscs +============== +*/ +static void CG_DoRailDiscs( qhandle_t hShader, byte color[4], int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up ) +{ + int i, j; + vec3_t pos[4]; + vec3_t v; + int spanWidth = 16 /*r_railWidth->integer*/; + float c, s; + float scale; + polyVert_t verts[4]; + + if ( numSegs > 1 ) + numSegs--; + if ( !numSegs ) + return; + + scale = 0.25; + + for ( i = 0; i < 4; i++ ) + { + c = cos( DEG2RAD( 45 + i * 90 ) ); + s = sin( DEG2RAD( 45 + i * 90 ) ); + v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth; + v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth; + v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth; + VectorAdd( start, v, pos[i] ); + + if ( numSegs > 1 ) + { + // offset by 1 segment if we're doing a long distance shot + VectorAdd( pos[i], dir, pos[i] ); + } + } + + for ( i = 0; i < numSegs; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + VectorCopy( pos[j], verts[j].xyz ); + verts[j].st[0] = ( j && j != 3 ); + verts[j].st[1] = ( j < 2 ); + verts[j].modulate[0] = color[0]; + verts[j].modulate[1] = color[1]; + verts[j].modulate[2] = color[2]; + verts[j].modulate[3] = 0xff; + + VectorAdd( pos[j], dir, pos[j] ); + } + + trap_R_AddPolysToScene( hShader, 4, verts, 1 ); + } +} + +/* +============== +CG_SurfaceRailRings +============== +*/ +void CG_SurfaceRailRings( const refEntity_t *originEnt ) { + refEntity_t re; + int numSegs; + int len; + vec3_t vec; + vec3_t right, up; + vec3_t start, end; + + re = *originEnt; + + VectorCopy( re.oldorigin, start ); + VectorCopy( re.origin, end ); + + // compute variables + VectorSubtract( end, start, vec ); + len = VectorNormalize( vec ); + MakeNormalVectors( vec, right, up ); + numSegs = ( len ) / 32.0f /*r_railSegmentLength->value*/; + if ( numSegs <= 0 ) { + numSegs = 1; + } + + VectorScale( vec, 32.0f /*r_railSegmentLength->value*/, vec ); + + CG_DoRailDiscs( re.customShader, re.shaderRGBA, numSegs, start, vec, right, up ); +} + +/* +============== +CG_DoRailCore +============== +*/ +static void CG_DoRailCore( polyVert_t *verts, const byte color[4], const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth ) +{ + float spanWidth2; + float t = len / 256.0f; + int numVertexes; + + spanWidth2 = -spanWidth; + numVertexes = 0; + + // FIXME: use quad stamp? + VectorMA( start, spanWidth, up, verts[numVertexes].xyz ); + verts[numVertexes].st[0] = 0; + verts[numVertexes].st[1] = 0; + verts[numVertexes].modulate[0] = color[0] * 0.25; + verts[numVertexes].modulate[1] = color[1] * 0.25; + verts[numVertexes].modulate[2] = color[2] * 0.25; + verts[numVertexes].modulate[3] = 0xff; + numVertexes++; + + VectorMA( start, spanWidth2, up, verts[numVertexes].xyz ); + verts[numVertexes].st[0] = 0; + verts[numVertexes].st[1] = 1; + verts[numVertexes].modulate[0] = color[0]; + verts[numVertexes].modulate[1] = color[1]; + verts[numVertexes].modulate[2] = color[2]; + verts[numVertexes].modulate[3] = 0xff; + numVertexes++; + + VectorMA( end, spanWidth2, up, verts[numVertexes].xyz ); + verts[numVertexes].st[0] = t; + verts[numVertexes].st[1] = 1; + verts[numVertexes].modulate[0] = color[0]; + verts[numVertexes].modulate[1] = color[1]; + verts[numVertexes].modulate[2] = color[2]; + verts[numVertexes].modulate[3] = 0xff; + numVertexes++; + + VectorMA( end, spanWidth, up, verts[numVertexes].xyz ); + verts[numVertexes].st[0] = t; + verts[numVertexes].st[1] = 0; + verts[numVertexes].modulate[0] = color[0]; + verts[numVertexes].modulate[1] = color[1]; + verts[numVertexes].modulate[2] = color[2]; + verts[numVertexes].modulate[3] = 0xff; + numVertexes++; +} + +/* +============== +CG_SurfaceRailCore +============== +*/ +void CG_SurfaceRailCore( const refEntity_t *originEnt ) { + int len; + vec3_t right; + vec3_t vec; + vec3_t start, end; + vec3_t v1, v2; + polyVert_t verts[4]; + refEntity_t re; + + re = *originEnt; + re.reType = RT_POLY; + + VectorCopy( re.oldorigin, start ); + VectorCopy( re.origin, end ); + + VectorSubtract( end, start, vec ); + len = VectorNormalize( vec ); + + // compute side vector + VectorSubtract( start, cg.refdef.vieworg, v1 ); + VectorNormalize( v1 ); + VectorSubtract( end, cg.refdef.vieworg, v2 ); + VectorNormalize( v2 ); + CrossProduct( v1, v2, right ); + VectorNormalize( right ); + + CG_DoRailCore( verts, re.shaderRGBA, start, end, right, len, 6 /*r_railCoreWidth->integer*/ ); + + trap_R_AddPolyRefEntityToScene( &re, 4, verts, 1 ); +} + +/* +============== +CG_SurfaceLightningBolt +============== +*/ +void CG_SurfaceLightningBolt( const refEntity_t *originEnt ) { + int len; + vec3_t right; + vec3_t vec; + vec3_t start, end; + vec3_t v1, v2; + int i; +#define NUM_BOLT_POLYS 4 + polyVert_t verts[NUM_BOLT_POLYS*4]; + refEntity_t re; + + re = *originEnt; + re.reType = RT_POLY; + + VectorCopy( re.oldorigin, end ); + VectorCopy( re.origin, start ); + + // compute variables + VectorSubtract( end, start, vec ); + len = VectorNormalize( vec ); + + // compute side vector + VectorSubtract( start, cg.refdef.vieworg, v1 ); + VectorNormalize( v1 ); + VectorSubtract( end, cg.refdef.vieworg, v2 ); + VectorNormalize( v2 ); + CrossProduct( v1, v2, right ); + VectorNormalize( right ); + + for ( i = 0 ; i < NUM_BOLT_POLYS ; i++ ) { + vec3_t temp; + + CG_DoRailCore( &verts[i*4], re.shaderRGBA, start, end, right, len, 8 ); + RotatePointAroundVector( temp, vec, right, 180.0f / NUM_BOLT_POLYS ); + VectorCopy( temp, right ); + } + + trap_R_AddPolyRefEntityToScene( &re, 4, verts, NUM_BOLT_POLYS ); +} + +/* +============== +CG_SurfaceBeam +============== +*/ +void CG_SurfaceBeam( const refEntity_t *originEnt ) +{ +#define NUM_BEAM_SEGS 6 + refEntity_t re; + int i, j; + vec3_t perpvec; + vec3_t direction, normalized_direction; + vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; + vec3_t oldorigin, origin; + polyVert_t verts[NUM_BEAM_SEGS*4]; + int numVerts; + + re = *originEnt; + + oldorigin[0] = re.oldorigin[0]; + oldorigin[1] = re.oldorigin[1]; + oldorigin[2] = re.oldorigin[2]; + + origin[0] = re.origin[0]; + origin[1] = re.origin[1]; + origin[2] = re.origin[2]; + + normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; + normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; + normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; + + if ( VectorNormalize( normalized_direction ) == 0 ) + return; + + PerpendicularVector( perpvec, normalized_direction ); + + VectorScale( perpvec, 4, perpvec ); + + for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) + { + RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); + VectorAdd( start_points[i], origin, start_points[i] ); // Note: Q3A incorrectly had this disabled, causing all beams to start at map origin + VectorAdd( start_points[i], direction, end_points[i] ); + } + + re.customShader = cgs.media.whiteShader; + + numVerts = 0; + for ( i = 0; i < NUM_BEAM_SEGS; i++ ) { + for ( j = 0; j < 4; j++ ) { + if ( j && j != 3 ) + VectorCopy( end_points[ (i+(j>1)) % NUM_BEAM_SEGS], verts[numVerts].xyz ); + else + VectorCopy( start_points[ (i+(j>1)) % NUM_BEAM_SEGS], verts[numVerts].xyz ); + verts[numVerts].st[0] = ( j < 2 ); + verts[numVerts].st[1] = ( j && j != 3 ); + verts[numVerts].modulate[0] = 0xff; + verts[numVerts].modulate[1] = 0; + verts[numVerts].modulate[2] = 0; + verts[numVerts].modulate[3] = 0xff; + numVerts++; + } + } + + // for acting like Q3A create a custom shader with + // cull none and blendfunc GL_ONE GL_ONE + trap_R_AddPolysToScene( re.customShader, 4, verts, NUM_BEAM_SEGS ); +} + diff --git a/code/cgame/cg_syscalls.c b/code/cgame/cg_syscalls.c index a22979b45..36b7084b6 100644 --- a/code/cgame/cg_syscalls.c +++ b/code/cgame/cg_syscalls.c @@ -34,6 +34,9 @@ Suite 120, Rockville, Maryland 20850 USA. #include "cg_public.h" #include "cg_syscalls.h" +// ZTM: TODO: move usage of this out of this file? +qboolean CG_AddCustomSurface( const refEntity_t *re ); + #ifndef Q3_VM static intptr_t (QDECL *syscall)( intptr_t arg, ... ) = (intptr_t (QDECL *)( intptr_t, ...))-1; @@ -347,7 +350,15 @@ void trap_R_ClearScene( void ) { syscall( CG_R_CLEARSCENE ); } +void trap_R_AddPolyRefEntityToScene( const refEntity_t *re, int numVerts, const polyVert_t *verts, int numPolys ) { + syscall( CG_R_ADDPOLYREFENTITYTOSCENE, re, numVerts, verts, numPolys ); +} + void trap_R_AddRefEntityToScene( const refEntity_t *re ) { + if ( CG_AddCustomSurface( re ) ) { + return; + } + syscall( CG_R_ADDREFENTITYTOSCENE, re ); } diff --git a/code/cgame/cg_syscalls.h b/code/cgame/cg_syscalls.h index 590500e08..551370c51 100644 --- a/code/cgame/cg_syscalls.h +++ b/code/cgame/cg_syscalls.h @@ -159,6 +159,7 @@ void trap_R_AddRefEntityToScene( const refEntity_t *re ); // polys are intended for simple wall marks, not really for doing // significant construction +void trap_R_AddPolyRefEntityToScene( const refEntity_t *re, int numVerts, const polyVert_t *verts, int numPolys ); void trap_R_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ); void trap_R_AddPolysToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ); void trap_R_AddPolyBufferToScene( polyBuffer_t* pPolyBuffer ); diff --git a/code/client/cl_cgame.c b/code/client/cl_cgame.c index 2e2931873..3ccd40f66 100644 --- a/code/client/cl_cgame.c +++ b/code/client/cl_cgame.c @@ -1328,7 +1328,10 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { re.ClearScene(); return 0; case CG_R_ADDREFENTITYTOSCENE: - re.AddRefEntityToScene( VMA(1) ); + re.AddRefEntityToScene( VMA(1), 0, NULL, 0 ); + return 0; + case CG_R_ADDPOLYREFENTITYTOSCENE: + re.AddRefEntityToScene( VMA(1), args[2], VMA(3), args[4] ); return 0; case CG_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[1], args[2], VMA(3), 1 ); diff --git a/code/renderercommon/tr_public.h b/code/renderercommon/tr_public.h index 86f12eb18..e5f951a79 100644 --- a/code/renderercommon/tr_public.h +++ b/code/renderercommon/tr_public.h @@ -77,8 +77,8 @@ typedef struct { // a scene is built up by calls to R_ClearScene and the various R_Add functions. // Nothing is drawn until R_RenderScene is called. void (*ClearScene)( void ); - void (*AddRefEntityToScene)( const refEntity_t *re ); - void (*AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); + void (*AddRefEntityToScene)( const refEntity_t *re, int numVerts, const polyVert_t *verts, int numPolys ); + void (*AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ); void (*AddPolyBufferToScene)( polyBuffer_t* pPolyBuffer ); int (*LightForPoint)( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); void (*AddLightToScene)( const vec3_t org, float radius, float intensity, float r, float g, float b ); diff --git a/code/renderercommon/tr_types.h b/code/renderercommon/tr_types.h index 885abb9ff..e12b93ee7 100644 --- a/code/renderercommon/tr_types.h +++ b/code/renderercommon/tr_types.h @@ -108,13 +108,16 @@ typedef enum { RT_MODEL, RT_POLY, RT_SPRITE, + RT_PORTALSURFACE, // doesn't draw anything, just info for portals + + RT_MAX_REF_ENTITY_TYPE, + + // ZTM: FIXME: these are only used in cgame... RT_BEAM, RT_RAIL_CORE, RT_RAIL_RINGS, - RT_LIGHTNING, - RT_PORTALSURFACE, // doesn't draw anything, just info for portals + RT_LIGHTNING - RT_MAX_REF_ENTITY_TYPE } refEntityType_t; typedef struct { diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index 94ae75a69..38db907c4 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -84,6 +84,11 @@ typedef struct { vec3_t ambientLight; // color normalized to 0-255 int ambientLightInt; // 32 bit rgba packed vec3_t directedLight; + + // for RT_POLY entities + int numPolys; + int numVerts; + polyVert_t *verts; } trRefEntity_t; @@ -1214,6 +1219,7 @@ void R_AddBeamSurfaces( trRefEntity_t *e ); void R_AddRailSurfaces( trRefEntity_t *e, qboolean isUnderwater ); void R_AddLightningBoltSurfaces( trRefEntity_t *e ); +int R_PolyFogNum( srfPoly_t *poly ); void R_AddPolygonSurfaces( void ); void R_AddPolygonBufferSurfaces( void ); @@ -1519,8 +1525,8 @@ void R_InitNextFrame( void ); qhandle_t RE_AddSkinToFrame( int numSurfaces, const qhandle_t *surfaces ); void RE_ClearScene( void ); -void RE_AddRefEntityToScene( const refEntity_t *ent ); -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); +void RE_AddRefEntityToScene( const refEntity_t *ent, int numVerts, const polyVert_t *verts, int numPolys ); +void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ); void RE_AddPolyBufferToScene( polyBuffer_t* pPolyBuffer ); void RE_AddLightToScene( const vec3_t org, float radius, float intensity, float r, float g, float b ); void RE_AddAdditiveLightToScene( const vec3_t org, float radius, float intensity, float r, float g, float b ); diff --git a/code/renderergl1/tr_main.c b/code/renderergl1/tr_main.c index 79ffeb997..dbe7e51fe 100644 --- a/code/renderergl1/tr_main.c +++ b/code/renderergl1/tr_main.c @@ -1460,6 +1460,7 @@ void R_AddEntitySurfaces (void) { trRefEntity_t *ent; shader_t *shader; qboolean onlyRenderShadows; + srfPoly_t polySurf; if ( !r_drawentities->integer ) { return; @@ -1503,15 +1504,23 @@ void R_AddEntitySurfaces (void) { switch ( ent->e.reType ) { case RT_PORTALSURFACE: break; // don't draw anything + case RT_SPRITE: - case RT_BEAM: - case RT_LIGHTNING: - case RT_RAIL_CORE: - case RT_RAIL_RINGS: shader = R_GetShaderByHandle( ent->e.customShader ); R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0 ); break; + case RT_POLY: + // setup poly surface to find fog num + polySurf.surfaceType = SF_POLY; + polySurf.hShader = ent->e.customShader; + polySurf.numVerts = ent->numVerts * ent->numPolys; + polySurf.verts = ent->verts; + + shader = R_GetShaderByHandle( ent->e.customShader ); + R_AddDrawSurf( &entitySurface, shader, R_PolyFogNum( &polySurf ), 0 ); + break; + case RT_MODEL: // we must set up parts of tr.or for model culling R_RotateForEntity( ent, &tr.viewParms, &tr.or ); diff --git a/code/renderergl1/tr_scene.c b/code/renderergl1/tr_scene.c index dbe686666..db7c14df0 100644 --- a/code/renderergl1/tr_scene.c +++ b/code/renderergl1/tr_scene.c @@ -341,7 +341,7 @@ RE_AddRefEntityToScene ===================== */ -void RE_AddRefEntityToScene( const refEntity_t *ent ) { +void RE_AddRefEntityToScene( const refEntity_t *ent, int numVerts, const polyVert_t *verts, int numPolys ) { if ( !tr.registered ) { return; } @@ -361,6 +361,28 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); } + if ( ent->reType == RT_POLY ) { + int totalVerts = numVerts * numPolys; + + if ( !verts || numVerts <= 0 || numPolys <= 0 ) { + ri.Printf( PRINT_WARNING, "WARNING: RE_AddRefEntityToScene: RT_POLY without poly info\n"); + return; + } + + if ( r_numpolyverts + totalVerts > max_polyverts ) { + ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddRefEntityToScene: r_max_polyverts reached\n"); + return; + } + + backEndData->entities[r_numentities].numPolys = numPolys; + backEndData->entities[r_numentities].numVerts = numVerts; + backEndData->entities[r_numentities].verts = &backEndData->polyVerts[r_numpolyverts]; + + Com_Memcpy( backEndData->entities[r_numentities].verts, verts, totalVerts * sizeof( *verts ) ); + + r_numpolyverts += totalVerts; + } + backEndData->entities[r_numentities].e = *ent; backEndData->entities[r_numentities].lightingCalculated = qfalse; diff --git a/code/renderergl1/tr_surface.c b/code/renderergl1/tr_surface.c index aa8e453c8..f0215142b 100644 --- a/code/renderergl1/tr_surface.c +++ b/code/renderergl1/tr_surface.c @@ -427,278 +427,8 @@ static void RB_SurfaceFoliage( srfFoliage_t *srf ) { // RB_DrawBounds( srf->bounds[ 0 ], srf->bounds[ 1 ] ); } - - -/* -============== -RB_SurfaceBeam -============== -*/ -static void RB_SurfaceBeam( void ) -{ -#define NUM_BEAM_SEGS 6 - refEntity_t *e; - int i; - vec3_t perpvec; - vec3_t direction, normalized_direction; - vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; - vec3_t oldorigin, origin; - - e = &backEnd.currentEntity->e; - - oldorigin[0] = e->oldorigin[0]; - oldorigin[1] = e->oldorigin[1]; - oldorigin[2] = e->oldorigin[2]; - - origin[0] = e->origin[0]; - origin[1] = e->origin[1]; - origin[2] = e->origin[2]; - - normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; - normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; - normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; - - if ( VectorNormalize( normalized_direction ) == 0 ) - return; - - PerpendicularVector( perpvec, normalized_direction ); - - VectorScale( perpvec, 4, perpvec ); - - for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) - { - RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); -// VectorAdd( start_points[i], origin, start_points[i] ); - VectorAdd( start_points[i], direction, end_points[i] ); - } - - GL_Bind( tr.whiteImage ); - - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - - qglColor3f( 1, 0, 0 ); - - qglBegin( GL_TRIANGLE_STRIP ); - for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) { - qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] ); - qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] ); - } - qglEnd(); -} - //================================================================================ -static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth ) -{ - float spanWidth2; - int vbase; - float t = len / 256.0f; - - vbase = tess.numVertexes; - - spanWidth2 = -spanWidth; - - // FIXME: use quad stamp? - VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25; - tess.numVertexes++; - - VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; - tess.numVertexes++; - - VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] ); - - tess.texCoords[tess.numVertexes][0][0] = t; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; - tess.numVertexes++; - - VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = t; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; - tess.numVertexes++; - - tess.indexes[tess.numIndexes++] = vbase; - tess.indexes[tess.numIndexes++] = vbase + 1; - tess.indexes[tess.numIndexes++] = vbase + 2; - - tess.indexes[tess.numIndexes++] = vbase + 2; - tess.indexes[tess.numIndexes++] = vbase + 1; - tess.indexes[tess.numIndexes++] = vbase + 3; -} - -static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up ) -{ - int i; - vec3_t pos[4]; - vec3_t v; - int spanWidth = r_railWidth->integer; - float c, s; - float scale; - - if ( numSegs > 1 ) - numSegs--; - if ( !numSegs ) - return; - - scale = 0.25; - - for ( i = 0; i < 4; i++ ) - { - c = cos( DEG2RAD( 45 + i * 90 ) ); - s = sin( DEG2RAD( 45 + i * 90 ) ); - v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth; - v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth; - v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth; - VectorAdd( start, v, pos[i] ); - - if ( numSegs > 1 ) - { - // offset by 1 segment if we're doing a long distance shot - VectorAdd( pos[i], dir, pos[i] ); - } - } - - for ( i = 0; i < numSegs; i++ ) - { - int j; - - RB_CHECKOVERFLOW( 4, 6 ); - - for ( j = 0; j < 4; j++ ) - { - VectorCopy( pos[j], tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = ( j < 2 ); - tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 ); - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; - tess.numVertexes++; - - VectorAdd( pos[j], dir, pos[j] ); - } - - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2; - } -} - -/* -** RB_SurfaceRailRinges -*/ -static void RB_SurfaceRailRings( void ) { - refEntity_t *e; - int numSegs; - int len; - vec3_t vec; - vec3_t right, up; - vec3_t start, end; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, start ); - VectorCopy( e->origin, end ); - - // compute variables - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - MakeNormalVectors( vec, right, up ); - numSegs = ( len ) / r_railSegmentLength->value; - if ( numSegs <= 0 ) { - numSegs = 1; - } - - VectorScale( vec, r_railSegmentLength->value, vec ); - - DoRailDiscs( numSegs, start, vec, right, up ); -} - -/* -** RB_SurfaceRailCore -*/ -static void RB_SurfaceRailCore( void ) { - refEntity_t *e; - int len; - vec3_t right; - vec3_t vec; - vec3_t start, end; - vec3_t v1, v2; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, start ); - VectorCopy( e->origin, end ); - - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - - // compute side vector - VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); - VectorNormalize( v1 ); - VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); - VectorNormalize( v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - DoRailCore( start, end, right, len, r_railCoreWidth->integer ); -} - -/* -** RB_SurfaceLightningBolt -*/ -static void RB_SurfaceLightningBolt( void ) { - refEntity_t *e; - int len; - vec3_t right; - vec3_t vec; - vec3_t start, end; - vec3_t v1, v2; - int i; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, end ); - VectorCopy( e->origin, start ); - - // compute variables - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - - // compute side vector - VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); - VectorNormalize( v1 ); - VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); - VectorNormalize( v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - for ( i = 0 ; i < 4 ; i++ ) { - vec3_t temp; - - DoRailCore( start, end, right, len, 8 ); - RotatePointAroundVector( temp, vec, right, 45 ); - VectorCopy( temp, right ); - } -} - /* ** VectorArrayNormalize * @@ -1283,17 +1013,24 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) { case RT_SPRITE: RB_SurfaceSprite(); break; - case RT_BEAM: - RB_SurfaceBeam(); - break; - case RT_RAIL_CORE: - RB_SurfaceRailCore(); - break; - case RT_RAIL_RINGS: - RB_SurfaceRailRings(); - break; - case RT_LIGHTNING: - RB_SurfaceLightningBolt(); + case RT_POLY: + { + trRefEntity_t *ent; + srfPoly_t polySurf; + int polyNum; + + ent = backEnd.currentEntity; + + polySurf.surfaceType = SF_POLY; //not used by RB_SurfacePolychain + polySurf.hShader = ent->e.customShader; //ditto + + polySurf.numVerts = ent->numVerts; + + for ( polyNum = 0; polyNum < ent->numPolys; polyNum++ ) { + polySurf.verts = &ent->verts[ ent->numVerts * polyNum ]; + RB_SurfacePolychain( &polySurf ); + } + } break; default: RB_SurfaceAxis(); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index c25e23104..50ca97215 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -104,6 +104,11 @@ typedef struct { vec3_t ambientLight; // color normalized to 0-255 int ambientLightInt; // 32 bit rgba packed vec3_t directedLight; + + // for RT_POLY entities + int numPolys; + int numVerts; + polyVert_t *verts; } trRefEntity_t; @@ -1986,6 +1991,7 @@ void R_AddBeamSurfaces( trRefEntity_t *e ); void R_AddRailSurfaces( trRefEntity_t *e, qboolean isUnderwater ); void R_AddLightningBoltSurfaces( trRefEntity_t *e ); +int R_PolyFogNum( srfPoly_t *poly ); void R_AddPolygonSurfaces( void ); void R_AddPolygonBufferSurfaces( void ); @@ -2398,8 +2404,8 @@ void R_InitNextFrame( void ); qhandle_t RE_AddSkinToFrame( int numSurfaces, const qhandle_t *surfaces ); void RE_ClearScene( void ); -void RE_AddRefEntityToScene( const refEntity_t *ent ); -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); +void RE_AddRefEntityToScene( const refEntity_t *ent, int numVerts, const polyVert_t *verts, int numPolys ); +void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ); void RE_AddPolyBufferToScene( polyBuffer_t* pPolyBuffer ); void RE_AddLightToScene( const vec3_t org, float radius, float intensity, float r, float g, float b ); void RE_AddAdditiveLightToScene( const vec3_t org, float radius, float intensity, float r, float g, float b ); diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index 4dc348fae..bb9ac205d 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -2129,6 +2129,7 @@ static void R_AddEntitySurface (int entityNum) trRefEntity_t *ent; shader_t *shader; qboolean onlyRenderShadows; + srfPoly_t polySurf; tr.currentEntityNum = entityNum; @@ -2167,15 +2168,23 @@ static void R_AddEntitySurface (int entityNum) switch ( ent->e.reType ) { case RT_PORTALSURFACE: break; // don't draw anything + case RT_SPRITE: - case RT_BEAM: - case RT_LIGHTNING: - case RT_RAIL_CORE: - case RT_RAIL_RINGS: shader = R_GetShaderByHandle( ent->e.customShader ); R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0, 0, 0 /*cubeMap*/ ); break; + case RT_POLY: + // setup poly surface to find fog num + polySurf.surfaceType = SF_POLY; + polySurf.hShader = ent->e.customShader; + polySurf.numVerts = ent->numVerts * ent->numPolys; + polySurf.verts = ent->verts; + + shader = R_GetShaderByHandle( ent->e.customShader ); + R_AddDrawSurf( &entitySurface, shader, R_PolyFogNum( &polySurf ), 0, 0, 0 /*cubeMap*/ ); + break; + case RT_MODEL: // we must set up parts of tr.or for model culling R_RotateForEntity( ent, &tr.viewParms, &tr.or ); diff --git a/code/renderergl2/tr_scene.c b/code/renderergl2/tr_scene.c index a490c1399..94bf0181d 100644 --- a/code/renderergl2/tr_scene.c +++ b/code/renderergl2/tr_scene.c @@ -341,7 +341,7 @@ RE_AddRefEntityToScene ===================== */ -void RE_AddRefEntityToScene( const refEntity_t *ent ) { +void RE_AddRefEntityToScene( const refEntity_t *ent, int numVerts, const polyVert_t *verts, int numPolys ) { vec3_t cross; if ( !tr.registered ) { @@ -363,6 +363,28 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); } + if ( ent->reType == RT_POLY ) { + int totalVerts = numVerts * numPolys; + + if ( !verts || numVerts <= 0 || numPolys <= 0 ) { + ri.Printf( PRINT_WARNING, "WARNING: RE_AddRefEntityToScene: RT_POLY without poly info\n"); + return; + } + + if ( r_numpolyverts + totalVerts > max_polyverts ) { + ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddRefEntityToScene: r_max_polyverts reached\n"); + return; + } + + backEndData->entities[r_numentities].numPolys = numPolys; + backEndData->entities[r_numentities].numVerts = numVerts; + backEndData->entities[r_numentities].verts = &backEndData->polyVerts[r_numpolyverts]; + + Com_Memcpy( backEndData->entities[r_numentities].verts, verts, totalVerts * sizeof( *verts ) ); + + r_numpolyverts += totalVerts; + } + backEndData->entities[r_numentities].e = *ent; backEndData->entities[r_numentities].lightingCalculated = qfalse; diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c index a3e38058d..be783ec21 100644 --- a/code/renderergl2/tr_surface.c +++ b/code/renderergl2/tr_surface.c @@ -638,312 +638,8 @@ static void RB_SurfaceFoliage( srfFoliage_t *srf ) { // RB_DrawBounds( srf->bounds[ 0 ], srf->bounds[ 1 ] ); } - -/* -============== -RB_SurfaceBeam -============== -*/ -static void RB_SurfaceBeam( void ) -{ -#define NUM_BEAM_SEGS 6 - refEntity_t *e; - shaderProgram_t *sp = &tr.textureColorShader; - int i; - vec3_t perpvec; - vec3_t direction, normalized_direction; - vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; - vec3_t oldorigin, origin; - - e = &backEnd.currentEntity->e; - - oldorigin[0] = e->oldorigin[0]; - oldorigin[1] = e->oldorigin[1]; - oldorigin[2] = e->oldorigin[2]; - - origin[0] = e->origin[0]; - origin[1] = e->origin[1]; - origin[2] = e->origin[2]; - - normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; - normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; - normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; - - if ( VectorNormalize( normalized_direction ) == 0 ) - return; - - PerpendicularVector( perpvec, normalized_direction ); - - VectorScale( perpvec, 4, perpvec ); - - for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) - { - RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); -// VectorAdd( start_points[i], origin, start_points[i] ); - VectorAdd( start_points[i], direction, end_points[i] ); - } - - GL_Bind( tr.whiteImage ); - - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - - // FIXME: Quake3 doesn't use this, so I never tested it - tess.numVertexes = 0; - tess.numIndexes = 0; - tess.firstIndex = 0; - tess.minIndex = 0; - tess.maxIndex = 0; - - for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) { - VectorCopy(start_points[ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]); - VectorCopy(end_points [ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]); - } - - for ( i = 0; i < NUM_BEAM_SEGS; i++ ) { - tess.indexes[tess.numIndexes++] = i * 2; - tess.indexes[tess.numIndexes++] = (i + 1) * 2; - tess.indexes[tess.numIndexes++] = 1 + i * 2; - - tess.indexes[tess.numIndexes++] = 1 + i * 2; - tess.indexes[tess.numIndexes++] = (i + 1) * 2; - tess.indexes[tess.numIndexes++] = 1 + (i + 1) * 2; - } - - tess.minIndex = 0; - tess.maxIndex = tess.numVertexes; - - // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function - RB_UpdateVBOs(ATTR_POSITION); - - GLSL_VertexAttribsState(ATTR_POSITION); - GLSL_BindProgram(sp); - - GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed); - - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); - - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; - tess.minIndex = 0; - tess.maxIndex = 0; -} - //================================================================================ -static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth ) -{ - float spanWidth2; - int vbase; - float t = len / 256.0f; - - vbase = tess.numVertexes; - - spanWidth2 = -spanWidth; - - // FIXME: use quad stamp? - VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25 / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25 / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25 / 255.0f; - tess.numVertexes++; - - VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] ); - - tess.texCoords[tess.numVertexes][0][0] = t; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = t; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - tess.indexes[tess.numIndexes++] = vbase; - tess.indexes[tess.numIndexes++] = vbase + 1; - tess.indexes[tess.numIndexes++] = vbase + 2; - - tess.indexes[tess.numIndexes++] = vbase + 2; - tess.indexes[tess.numIndexes++] = vbase + 1; - tess.indexes[tess.numIndexes++] = vbase + 3; -} - -static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up ) -{ - int i; - vec3_t pos[4]; - vec3_t v; - int spanWidth = r_railWidth->integer; - float c, s; - float scale; - - if ( numSegs > 1 ) - numSegs--; - if ( !numSegs ) - return; - - scale = 0.25; - - for ( i = 0; i < 4; i++ ) - { - c = cos( DEG2RAD( 45 + i * 90 ) ); - s = sin( DEG2RAD( 45 + i * 90 ) ); - v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth; - v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth; - v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth; - VectorAdd( start, v, pos[i] ); - - if ( numSegs > 1 ) - { - // offset by 1 segment if we're doing a long distance shot - VectorAdd( pos[i], dir, pos[i] ); - } - } - - for ( i = 0; i < numSegs; i++ ) - { - int j; - - RB_CHECKOVERFLOW( 4, 6 ); - - for ( j = 0; j < 4; j++ ) - { - VectorCopy( pos[j], tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = ( j < 2 ); - tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 ); - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - VectorAdd( pos[j], dir, pos[j] ); - } - - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2; - } -} - -/* -** RB_SurfaceRailRinges -*/ -static void RB_SurfaceRailRings( void ) { - refEntity_t *e; - int numSegs; - int len; - vec3_t vec; - vec3_t right, up; - vec3_t start, end; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, start ); - VectorCopy( e->origin, end ); - - // compute variables - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - MakeNormalVectors( vec, right, up ); - numSegs = ( len ) / r_railSegmentLength->value; - if ( numSegs <= 0 ) { - numSegs = 1; - } - - VectorScale( vec, r_railSegmentLength->value, vec ); - - DoRailDiscs( numSegs, start, vec, right, up ); -} - -/* -** RB_SurfaceRailCore -*/ -static void RB_SurfaceRailCore( void ) { - refEntity_t *e; - int len; - vec3_t right; - vec3_t vec; - vec3_t start, end; - vec3_t v1, v2; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, start ); - VectorCopy( e->origin, end ); - - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - - // compute side vector - VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); - VectorNormalize( v1 ); - VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); - VectorNormalize( v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - DoRailCore( start, end, right, len, r_railCoreWidth->integer ); -} - -/* -** RB_SurfaceLightningBolt -*/ -static void RB_SurfaceLightningBolt( void ) { - refEntity_t *e; - int len; - vec3_t right; - vec3_t vec; - vec3_t start, end; - vec3_t v1, v2; - int i; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, end ); - VectorCopy( e->origin, start ); - - // compute variables - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - - // compute side vector - VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); - VectorNormalize( v1 ); - VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); - VectorNormalize( v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - for ( i = 0 ; i < 4 ; i++ ) { - vec3_t temp; - - DoRailCore( start, end, right, len, 8 ); - RotatePointAroundVector( temp, vec, right, 45 ); - VectorCopy( temp, right ); - } -} - #if 0 /* ** VectorArrayNormalize @@ -1649,18 +1345,24 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) { case RT_SPRITE: RB_SurfaceSprite(); break; - case RT_BEAM: - RB_SurfaceBeam(); - break; - case RT_RAIL_CORE: - RB_SurfaceRailCore(); - break; - case RT_RAIL_RINGS: - RB_SurfaceRailRings(); - break; - case RT_LIGHTNING: - RB_SurfaceLightningBolt(); - break; + case RT_POLY: + { + trRefEntity_t *ent; + srfPoly_t polySurf; + int polyNum; + + ent = backEnd.currentEntity; + + polySurf.surfaceType = SF_POLY; //not used by RB_SurfacePolychain + polySurf.hShader = ent->e.customShader; //ditto + + polySurf.numVerts = ent->numVerts; + + for ( polyNum = 0; polyNum < ent->numPolys; polyNum++ ) { + polySurf.verts = &ent->verts[ ent->numVerts * polyNum ]; + RB_SurfacePolychain( &polySurf ); + } + } default: RB_SurfaceAxis(); break;