mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
Removed idInteraction.
This commit is contained in:
@@ -298,7 +298,6 @@
|
||||
<ClInclude Include="renderer\glext.h" />
|
||||
<ClInclude Include="renderer\GuiModel.h" />
|
||||
<ClInclude Include="renderer\Image.h" />
|
||||
<ClInclude Include="renderer\Interaction.h" />
|
||||
<ClInclude Include="renderer\Material.h" />
|
||||
<ClInclude Include="renderer\MegaTexture.h" />
|
||||
<ClInclude Include="renderer\Model.h" />
|
||||
@@ -1318,7 +1317,6 @@
|
||||
<ClCompile Include="renderer\Image_load.cpp" />
|
||||
<ClCompile Include="renderer\Image_process.cpp" />
|
||||
<ClCompile Include="renderer\Image_program.cpp" />
|
||||
<ClCompile Include="renderer\Interaction.cpp" />
|
||||
<ClCompile Include="renderer\Material.cpp" />
|
||||
<ClCompile Include="renderer\MegaTexture.cpp" />
|
||||
<ClCompile Include="renderer\Model.cpp" />
|
||||
@@ -1352,12 +1350,9 @@
|
||||
<ClCompile Include="renderer\tr_polytope.cpp" />
|
||||
<ClCompile Include="renderer\tr_render.cpp" />
|
||||
<ClCompile Include="renderer\tr_rendertools.cpp" />
|
||||
<ClCompile Include="renderer\tr_shadowbounds.cpp" />
|
||||
<ClCompile Include="renderer\tr_stencilshadow.cpp" />
|
||||
<ClCompile Include="renderer\tr_subview.cpp" />
|
||||
<ClCompile Include="renderer\tr_trace.cpp" />
|
||||
<ClCompile Include="renderer\tr_trisurf.cpp" />
|
||||
<ClCompile Include="renderer\tr_turboshadow.cpp" />
|
||||
<ClCompile Include="renderer\VertexCache.cpp" />
|
||||
<ClCompile Include="renderer\jpeg-6\jcapimin.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
@@ -2240,7 +2235,6 @@
|
||||
<ClCompile Include="tools\compilers\dmap\optimize_gcc.cpp" />
|
||||
<ClCompile Include="tools\compilers\dmap\output.cpp" />
|
||||
<ClCompile Include="tools\compilers\dmap\portals.cpp" />
|
||||
<ClCompile Include="tools\compilers\dmap\shadowopt3.cpp" />
|
||||
<ClCompile Include="tools\compilers\dmap\tritjunction.cpp" />
|
||||
<ClCompile Include="tools\compilers\dmap\tritools.cpp" />
|
||||
<ClCompile Include="tools\compilers\dmap\ubrush.cpp" />
|
||||
|
||||
@@ -225,9 +225,6 @@
|
||||
<ClInclude Include="renderer\Image.h">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="renderer\Interaction.h">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="renderer\Material.h">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClInclude>
|
||||
@@ -746,9 +743,6 @@
|
||||
<ClCompile Include="renderer\Image_program.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\Interaction.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\Material.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
@@ -848,12 +842,6 @@
|
||||
<ClCompile Include="renderer\tr_rendertools.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\tr_shadowbounds.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\tr_stencilshadow.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\tr_subview.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
@@ -863,9 +851,6 @@
|
||||
<ClCompile Include="renderer\tr_trisurf.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\tr_turboshadow.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renderer\VertexCache.cpp">
|
||||
<Filter>Renderer</Filter>
|
||||
</ClCompile>
|
||||
@@ -1328,9 +1313,6 @@
|
||||
<ClCompile Include="tools\compilers\dmap\portals.cpp">
|
||||
<Filter>Tools\Compilers\DMap</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tools\compilers\dmap\shadowopt3.cpp">
|
||||
<Filter>Tools\Compilers\DMap</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tools\compilers\dmap\tritjunction.cpp">
|
||||
<Filter>Tools\Compilers\DMap</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommandArguments>+set r_fullscreen 0 +set r_mode 6</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerWorkingDirectory>D:\projects\Doom3</LocalDebuggerWorkingDirectory>
|
||||
<LocalDebuggerCommandArgumentsHistory>+set r_fullscreen 0 +set r_mode 6|</LocalDebuggerCommandArgumentsHistory>
|
||||
<LocalDebuggerCommandArgumentsHistory>+set r_fullscreen 1 +set r_mode 6|+set r_fullscreen 0 +set r_mode 6|</LocalDebuggerCommandArgumentsHistory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">
|
||||
<LocalDebuggerCommand>D:\projects\Doom3\Doom3.exe</LocalDebuggerCommand>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 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.
|
||||
|
||||
Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 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 which accompanied the Doom 3 Source Code. 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.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __INTERACTION_H__
|
||||
#define __INTERACTION_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Interaction between entityDef surfaces and a lightDef.
|
||||
|
||||
Interactions with no lightTris and no shadowTris are still
|
||||
valid, because they show that a given entityDef / lightDef
|
||||
do not interact, even though they share one or more areas.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#define LIGHT_TRIS_DEFERRED ((srfTriangles_t *)-1)
|
||||
#define LIGHT_CULL_ALL_FRONT ((byte *)-1)
|
||||
#define LIGHT_CLIP_EPSILON 0.1f
|
||||
|
||||
|
||||
typedef struct {
|
||||
// For each triangle a byte set to 1 if facing the light origin.
|
||||
byte * facing;
|
||||
|
||||
// For each vertex a byte with the bits [0-5] set if the
|
||||
// vertex is at the back side of the corresponding clip plane.
|
||||
// If the 'cullBits' pointer equals LIGHT_CULL_ALL_FRONT all
|
||||
// vertices are at the front of all the clip planes.
|
||||
byte * cullBits;
|
||||
|
||||
// Clip planes in surface space used to calculate the cull bits.
|
||||
idPlane localClipPlanes[6];
|
||||
} srfCullInfo_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
// if lightTris == LIGHT_TRIS_DEFERRED, then the calculation of the
|
||||
// lightTris has been deferred, and must be done if ambientTris is visible
|
||||
srfTriangles_t * lightTris;
|
||||
|
||||
// shadow volume triangle surface
|
||||
srfTriangles_t * shadowTris;
|
||||
|
||||
// so we can check ambientViewCount before adding lightTris, and get
|
||||
// at the shared vertex and possibly shadowVertex caches
|
||||
srfTriangles_t * ambientTris;
|
||||
|
||||
const idMaterial * shader;
|
||||
|
||||
int expCulled; // only for the experimental shadow buffer renderer
|
||||
|
||||
srfCullInfo_t cullInfo;
|
||||
} surfaceInteraction_t;
|
||||
|
||||
|
||||
typedef struct areaNumRef_s {
|
||||
struct areaNumRef_s * next;
|
||||
int areaNum;
|
||||
} areaNumRef_t;
|
||||
|
||||
|
||||
class idRenderEntityLocal;
|
||||
class idRenderLightLocal;
|
||||
|
||||
class idInteraction {
|
||||
public:
|
||||
// this may be 0 if the light and entity do not actually intersect
|
||||
// -1 = an untested interaction
|
||||
int numSurfaces;
|
||||
|
||||
// if there is a whole-entity optimized shadow hull, it will
|
||||
// be present as a surfaceInteraction_t with a NULL ambientTris, but
|
||||
// possibly having a shader to specify the shadow sorting order
|
||||
surfaceInteraction_t * surfaces;
|
||||
|
||||
// get space from here, if NULL, it is a pre-generated shadow volume from dmap
|
||||
idRenderEntityLocal * entityDef;
|
||||
idRenderLightLocal * lightDef;
|
||||
|
||||
idInteraction * lightNext; // for lightDef chains
|
||||
idInteraction * lightPrev;
|
||||
idInteraction * entityNext; // for entityDef chains
|
||||
idInteraction * entityPrev;
|
||||
|
||||
public:
|
||||
idInteraction( void );
|
||||
|
||||
// because these are generated and freed each game tic for active elements all
|
||||
// over the world, we use a custom pool allocater to avoid memory allocation overhead
|
||||
// and fragmentation
|
||||
static idInteraction * AllocAndLink( idRenderEntityLocal *edef, idRenderLightLocal *ldef );
|
||||
|
||||
// unlinks from the entity and light, frees all surfaceInteractions,
|
||||
// and puts it back on the free list
|
||||
void UnlinkAndFree( void );
|
||||
|
||||
// free the interaction surfaces
|
||||
void FreeSurfaces( void );
|
||||
|
||||
// makes the interaction empty for when the light and entity do not actually intersect
|
||||
// all empty interactions are linked at the end of the light's and entity's interaction list
|
||||
void MakeEmpty( void );
|
||||
|
||||
// returns true if the interaction is empty
|
||||
bool IsEmpty( void ) const { return ( numSurfaces == 0 ); }
|
||||
|
||||
// returns true if the interaction is not yet completely created
|
||||
bool IsDeferred( void ) const { return ( numSurfaces == -1 ); }
|
||||
|
||||
// returns true if the interaction has shadows
|
||||
bool HasShadows( void ) const;
|
||||
|
||||
// counts up the memory used by all the surfaceInteractions, which
|
||||
// will be used to determine when we need to start purging old interactions
|
||||
int MemoryUsed( void );
|
||||
|
||||
// makes sure all necessary light surfaces and shadow surfaces are created, and
|
||||
// calls R_LinkLightSurf() for each one
|
||||
void AddActiveInteraction( void );
|
||||
|
||||
private:
|
||||
enum {
|
||||
FRUSTUM_UNINITIALIZED,
|
||||
FRUSTUM_INVALID,
|
||||
FRUSTUM_VALID,
|
||||
FRUSTUM_VALIDAREAS,
|
||||
} frustumState;
|
||||
idFrustum frustum; // frustum which contains the interaction
|
||||
areaNumRef_t * frustumAreas; // numbers of the areas the frustum touches
|
||||
|
||||
int dynamicModelFrameCount; // so we can tell if a callback model animated
|
||||
|
||||
private:
|
||||
// actually create the interaction
|
||||
void CreateInteraction( const idRenderModel *model );
|
||||
|
||||
// unlink from entity and light lists
|
||||
void Unlink( void );
|
||||
|
||||
// try to determine if the entire interaction, including shadows, is guaranteed
|
||||
// to be outside the view frustum
|
||||
bool CullInteractionByViewFrustum( const idFrustum &viewFrustum );
|
||||
|
||||
// determine the minimum scissor rect that will include the interaction shadows
|
||||
// projected to the bounds of the light
|
||||
idScreenRect CalcInteractionScissorRectangle( const idFrustum &viewFrustum );
|
||||
};
|
||||
|
||||
|
||||
void R_CalcInteractionFacing( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo );
|
||||
void R_CalcInteractionCullBits( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo );
|
||||
void R_FreeInteractionCullInfo( srfCullInfo_t &cullInfo );
|
||||
|
||||
void R_ShowInteractionMemory_f( const idCmdArgs &args );
|
||||
|
||||
#endif /* !__INTERACTION_H__ */
|
||||
@@ -49,8 +49,6 @@ idRenderEntityLocal::idRenderEntityLocal() {
|
||||
decals = NULL;
|
||||
overlay = NULL;
|
||||
entityRefs = NULL;
|
||||
firstInteraction = NULL;
|
||||
lastInteraction = NULL;
|
||||
dxrBottomAccelStruct = 0;
|
||||
needsPortalSky = false;
|
||||
}
|
||||
@@ -108,8 +106,6 @@ idRenderLightLocal::idRenderLightLocal() {
|
||||
viewLight = NULL;
|
||||
references = NULL;
|
||||
foggedPortals = NULL;
|
||||
firstInteraction = NULL;
|
||||
lastInteraction = NULL;
|
||||
}
|
||||
|
||||
void idRenderLightLocal::FreeRenderLight() {
|
||||
|
||||
@@ -1864,7 +1864,6 @@ void R_InitCommands( void ) {
|
||||
cmdSystem->AddCommand( "reportSurfaceAreas", R_ReportSurfaceAreas_f, CMD_FL_RENDERER, "lists all used materials sorted by surface area" );
|
||||
cmdSystem->AddCommand( "reportImageDuplication", R_ReportImageDuplication_f, CMD_FL_RENDERER, "checks all referenced images for duplications" );
|
||||
cmdSystem->AddCommand( "regenerateWorld", R_RegenerateWorld_f, CMD_FL_RENDERER, "regenerates all interactions" );
|
||||
cmdSystem->AddCommand( "showInteractionMemory", R_ShowInteractionMemory_f, CMD_FL_RENDERER, "shows memory used by interactions" );
|
||||
cmdSystem->AddCommand( "showTriSurfMemory", R_ShowTriSurfMemory_f, CMD_FL_RENDERER, "shows memory used by triangle surfaces" );
|
||||
cmdSystem->AddCommand( "vid_restart", R_VidRestart_f, CMD_FL_RENDERER, "restarts renderSystem" );
|
||||
cmdSystem->AddCommand( "listRenderEntityDefs", R_ListRenderEntityDefs_f, CMD_FL_RENDERER, "lists the entity defs" );
|
||||
|
||||
@@ -55,13 +55,6 @@ void R_ListRenderLightDefs_f( const idCmdArgs &args ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// count up the interactions
|
||||
int iCount = 0;
|
||||
for ( idInteraction *inter = ldef->firstInteraction; inter != NULL; inter = inter->lightNext ) {
|
||||
iCount++;
|
||||
}
|
||||
totalIntr += iCount;
|
||||
|
||||
// count up the references
|
||||
int rCount = 0;
|
||||
for ( areaReference_t *ref = ldef->references ; ref ; ref = ref->ownerNext ) {
|
||||
@@ -69,7 +62,7 @@ void R_ListRenderLightDefs_f( const idCmdArgs &args ) {
|
||||
}
|
||||
totalRef += rCount;
|
||||
|
||||
common->Printf( "%4i: %3i intr %2i refs %s\n", i, iCount, rCount, ldef->lightShader->GetName());
|
||||
//common->Printf( "%4i: %3i intr %2i refs %s\n", i, iCount, rCount, ldef->lightShader->GetName());
|
||||
active++;
|
||||
}
|
||||
|
||||
@@ -99,13 +92,6 @@ void R_ListRenderEntityDefs_f( const idCmdArgs &args ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// count up the interactions
|
||||
int iCount = 0;
|
||||
for ( idInteraction *inter = mdef->firstInteraction; inter != NULL; inter = inter->entityNext ) {
|
||||
iCount++;
|
||||
}
|
||||
totalIntr += iCount;
|
||||
|
||||
// count up the references
|
||||
int rCount = 0;
|
||||
for ( areaReference_t *ref = mdef->entityRefs ; ref ; ref = ref->ownerNext ) {
|
||||
@@ -113,7 +99,6 @@ void R_ListRenderEntityDefs_f( const idCmdArgs &args ) {
|
||||
}
|
||||
totalRef += rCount;
|
||||
|
||||
common->Printf( "%4i: %3i intr %2i refs %s\n", i, iCount, rCount, mdef->parms.hModel->Name());
|
||||
active++;
|
||||
}
|
||||
|
||||
@@ -130,8 +115,6 @@ idRenderWorldLocal::idRenderWorldLocal(dxrWorldId_t dxrWorldId) {
|
||||
mapTimeStamp = FILE_NOT_FOUND_TIMESTAMP;
|
||||
|
||||
this->dxrWorldId = tr.dxrWorldHandles[dxrWorldId];
|
||||
|
||||
generateAllInteractionsCalled = false;
|
||||
|
||||
areaNodes = NULL;
|
||||
numAreaNodes = 0;
|
||||
@@ -141,10 +124,6 @@ idRenderWorldLocal::idRenderWorldLocal(dxrWorldId_t dxrWorldId) {
|
||||
|
||||
doublePortals = NULL;
|
||||
numInterAreaPortals = 0;
|
||||
|
||||
interactionTable = 0;
|
||||
interactionTableWidth = 0;
|
||||
interactionTableHeight = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -171,8 +150,6 @@ void idRenderWorldLocal::ResizeInteractionTable() {
|
||||
// we overflowed the interaction table, so dump it
|
||||
// we may want to resize this in the future if it turns out to be common
|
||||
common->Printf( "idRenderWorldLocal::ResizeInteractionTable: overflowed interactionTableWidth, dumping\n" );
|
||||
R_StaticFree( interactionTable );
|
||||
interactionTable = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -185,9 +162,6 @@ qhandle_t idRenderWorldLocal::AddEntityDef( const renderEntity_t *re ){
|
||||
int entityHandle = entityDefs.FindNull();
|
||||
if ( entityHandle == -1 ) {
|
||||
entityHandle = entityDefs.Append( NULL );
|
||||
if ( interactionTable && entityDefs.Num() > interactionTableWidth ) {
|
||||
ResizeInteractionTable();
|
||||
}
|
||||
}
|
||||
|
||||
UpdateEntityDef( entityHandle, re );
|
||||
@@ -381,9 +355,6 @@ qhandle_t idRenderWorldLocal::AddLightDef( const renderLight_t *rlight ) {
|
||||
|
||||
if ( lightHandle == -1 ) {
|
||||
lightHandle = lightDefs.Append( NULL );
|
||||
if ( interactionTable && lightDefs.Num() > interactionTableHeight ) {
|
||||
ResizeInteractionTable();
|
||||
}
|
||||
}
|
||||
UpdateLightDef( lightHandle, rlight );
|
||||
|
||||
@@ -1469,8 +1440,6 @@ void idRenderWorldLocal::GenerateAllInteractions() {
|
||||
|
||||
int start = Sys_Milliseconds();
|
||||
|
||||
generateAllInteractionsCalled = false;
|
||||
|
||||
// watch how much memory we allocate
|
||||
tr.staticAllocCount = 0;
|
||||
|
||||
@@ -1490,37 +1459,6 @@ void idRenderWorldLocal::GenerateAllInteractions() {
|
||||
int msec = end - start;
|
||||
|
||||
common->Printf( "idRenderWorld::GenerateAllInteractions, msec = %i, staticAllocCount = %i.\n", msec, tr.staticAllocCount );
|
||||
|
||||
|
||||
// build the interaction table
|
||||
if ( r_useInteractionTable.GetBool() ) {
|
||||
interactionTableWidth = entityDefs.Num() + 100;
|
||||
interactionTableHeight = lightDefs.Num() + 100;
|
||||
int size = interactionTableWidth * interactionTableHeight * sizeof( *interactionTable );
|
||||
interactionTable = (idInteraction **)R_ClearedStaticAlloc( size );
|
||||
|
||||
int count = 0;
|
||||
for ( int i = 0 ; i < this->lightDefs.Num() ; i++ ) {
|
||||
idRenderLightLocal *ldef = this->lightDefs[i];
|
||||
if ( !ldef ) {
|
||||
continue;
|
||||
}
|
||||
idInteraction *inter;
|
||||
for ( inter = ldef->firstInteraction; inter != NULL; inter = inter->lightNext ) {
|
||||
idRenderEntityLocal *edef = inter->entityDef;
|
||||
int index = ldef->index * interactionTableWidth + edef->index;
|
||||
|
||||
interactionTable[ index ] = inter;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
common->Printf( "interactionTable size: %i bytes\n", size );
|
||||
common->Printf( "%i interaction take %i bytes\n", count, count * sizeof( idInteraction ) );
|
||||
}
|
||||
|
||||
// entities flagged as noDynamicInteractions will no longer make any
|
||||
generateAllInteractionsCalled = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1537,10 +1475,7 @@ void idRenderWorldLocal::FreeInteractions() {
|
||||
if ( !def ) {
|
||||
continue;
|
||||
}
|
||||
// free all the interactions
|
||||
while ( def->firstInteraction != NULL ) {
|
||||
def->firstInteraction->UnlinkAndFree();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ void idRenderWorldLocal::FreeWorld() {
|
||||
localModels.Clear();
|
||||
|
||||
areaReferenceAllocator.Shutdown();
|
||||
interactionAllocator.Shutdown();
|
||||
//interactionAllocator.Shutdown();
|
||||
areaNumRefAllocator.Shutdown();
|
||||
|
||||
mapName = "<FREED>";
|
||||
@@ -454,13 +454,6 @@ dump all the interactions
|
||||
void idRenderWorldLocal::FreeDefs() {
|
||||
int i;
|
||||
|
||||
generateAllInteractionsCalled = false;
|
||||
|
||||
if ( interactionTable ) {
|
||||
R_StaticFree( interactionTable );
|
||||
interactionTable = NULL;
|
||||
}
|
||||
|
||||
// free all lightDefs
|
||||
for ( i = 0 ; i < lightDefs.Num() ; i++ ) {
|
||||
idRenderLightLocal *light;
|
||||
|
||||
@@ -79,6 +79,11 @@ struct dxrWorldModel_t {
|
||||
uint32_t topAccelStruct = 0;
|
||||
};
|
||||
|
||||
typedef struct areaNumRef_s {
|
||||
struct areaNumRef_s* next;
|
||||
int areaNum;
|
||||
} areaNumRef_t;
|
||||
|
||||
class idRenderWorldLocal : public idRenderWorld {
|
||||
public:
|
||||
idRenderWorldLocal(dxrWorldId_t dxrWorldId);
|
||||
@@ -159,21 +164,8 @@ public:
|
||||
idList<idRenderLightLocal*> lightDefs;
|
||||
|
||||
idBlockAlloc<areaReference_t, 1024> areaReferenceAllocator;
|
||||
idBlockAlloc<idInteraction, 256> interactionAllocator;
|
||||
idBlockAlloc<areaNumRef_t, 1024> areaNumRefAllocator;
|
||||
|
||||
// all light / entity interactions are referenced here for fast lookup without
|
||||
// having to crawl the doubly linked lists. EnntityDefs are sequential for better
|
||||
// cache access, because the table is accessed by light in idRenderWorldLocal::CreateLightDefInteractions()
|
||||
// Growing this table is time consuming, so we add a pad value to the number
|
||||
// of entityDefs and lightDefs
|
||||
idInteraction ** interactionTable;
|
||||
int interactionTableWidth; // entityDefs
|
||||
int interactionTableHeight; // lightDefs
|
||||
|
||||
|
||||
bool generateAllInteractionsCalled;
|
||||
|
||||
//-----------------------
|
||||
// RenderWorld_load.cpp
|
||||
|
||||
|
||||
@@ -172,17 +172,11 @@ void RB_DXDrawInteractions(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vLight->localInteractions && !vLight->globalInteractions
|
||||
&& !vLight->translucentInteractions)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const renderLight_t& srcLight = vLight->lightDef->parms;
|
||||
const float r = srcLight.shaderParms[SHADERPARM_RED];
|
||||
const float g = srcLight.shaderParms[SHADERPARM_GREEN];
|
||||
const float b = srcLight.shaderParms[SHADERPARM_BLUE];
|
||||
const float intensity = 1.0f;
|
||||
const float intensity = 2.0f;
|
||||
|
||||
glRaytracingLight_t light = {};
|
||||
bool supported = true;
|
||||
|
||||
@@ -544,7 +544,6 @@ void idRenderWorldLocal::CreateLightDefInteractions( idRenderLightLocal *ldef )
|
||||
areaReference_t *lref;
|
||||
idRenderEntityLocal *edef;
|
||||
portalArea_t *area;
|
||||
idInteraction *inter;
|
||||
|
||||
for ( lref = ldef->references ; lref ; lref = lref->ownerNext ) {
|
||||
area = lref->area;
|
||||
@@ -576,53 +575,10 @@ void idRenderWorldLocal::CreateLightDefInteractions( idRenderLightLocal *ldef )
|
||||
|
||||
// some big outdoor meshes are flagged to not create any dynamic interactions
|
||||
// when the level designer knows that nearby moving lights shouldn't actually hit them
|
||||
if ( edef->parms.noDynamicInteractions && edef->world->generateAllInteractionsCalled ) {
|
||||
if ( edef->parms.noDynamicInteractions ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if any of the edef's interaction match this light, we don't
|
||||
// need to consider it.
|
||||
if ( r_useInteractionTable.GetBool() && this->interactionTable ) {
|
||||
// allocating these tables may take several megs on big maps, but it saves 3% to 5% of
|
||||
// the CPU time. The table is updated at interaction::AllocAndLink() and interaction::UnlinkAndFree()
|
||||
int index = ldef->index * this->interactionTableWidth + edef->index;
|
||||
inter = this->interactionTable[ index ];
|
||||
if ( inter ) {
|
||||
// if this entity wasn't in view already, the scissor rect will be empty,
|
||||
// so it will only be used for shadow casting
|
||||
if ( !inter->IsEmpty() ) {
|
||||
R_SetEntityDefViewEntity( edef );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// scan the doubly linked lists, which may have several dozen entries
|
||||
|
||||
// we could check either model refs or light refs for matches, but it is
|
||||
// assumed that there will be less lights in an area than models
|
||||
// so the entity chains should be somewhat shorter (they tend to be fairly close).
|
||||
for ( inter = edef->firstInteraction; inter != NULL; inter = inter->entityNext ) {
|
||||
if ( inter->lightDef == ldef ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we already have an interaction, we don't need to do anything
|
||||
if ( inter != NULL ) {
|
||||
// if this entity wasn't in view already, the scissor rect will be empty,
|
||||
// so it will only be used for shadow casting
|
||||
if ( !inter->IsEmpty() ) {
|
||||
R_SetEntityDefViewEntity( edef );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// create a new interaction, but don't do any work other than bbox to frustum culling
|
||||
//
|
||||
idInteraction *inter = idInteraction::AllocAndLink( edef, ldef );
|
||||
|
||||
// do a check of the entity reference bounds against the light frustum,
|
||||
// trying to avoid creating a viewEntity if it hasn't been already
|
||||
float modelMatrix[16];
|
||||
@@ -636,7 +592,6 @@ void idRenderWorldLocal::CreateLightDefInteractions( idRenderLightLocal *ldef )
|
||||
}
|
||||
|
||||
if ( R_CullLocalBox( edef->referenceBounds, m, 6, ldef->frustum ) ) {
|
||||
inter->MakeEmpty();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1471,7 +1426,6 @@ two or more lights.
|
||||
*/
|
||||
void R_AddModelSurfaces( void ) {
|
||||
viewEntity_t *vEntity;
|
||||
idInteraction *inter, *next;
|
||||
idRenderModel *model;
|
||||
|
||||
// clear the ambient surface list
|
||||
@@ -1537,35 +1491,6 @@ void R_AddModelSurfaces( void ) {
|
||||
tr.pc.c_shadowViewEntities++;
|
||||
}
|
||||
|
||||
//
|
||||
// for all the entity / light interactions on this entity, add them to the view
|
||||
//
|
||||
if ( tr.viewDef->isXraySubview ) {
|
||||
if ( vEntity->entityDef->parms.xrayIndex == 2 ) {
|
||||
for ( inter = vEntity->entityDef->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = next ) {
|
||||
next = inter->entityNext;
|
||||
if ( inter->lightDef->viewCount != tr.viewCount ) {
|
||||
continue;
|
||||
}
|
||||
inter->AddActiveInteraction();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// all empty interactions are at the end of the list so once the
|
||||
// first is encountered all the remaining interactions are empty
|
||||
for ( inter = vEntity->entityDef->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = next ) {
|
||||
next = inter->entityNext;
|
||||
|
||||
// skip any lights that aren't currently visible
|
||||
// this is run after any lights that are turned off have already
|
||||
// been removed from the viewLights list, and had their viewCount cleared
|
||||
if ( inter->lightDef->viewCount != tr.viewCount ) {
|
||||
continue;
|
||||
}
|
||||
inter->AddActiveInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
if ( vEntity->entityDef->parms.timeGroup ) {
|
||||
tr.viewDef->floatTime = oldFloatTime;
|
||||
tr.viewDef->renderView.time = oldTime;
|
||||
|
||||
@@ -432,10 +432,6 @@ void R_DeriveLightData( idRenderLightLocal *light ) {
|
||||
R_FreeLightDefFrustum( light );
|
||||
|
||||
light->frustumTris = R_PolytopeSurface( 6, light->frustum, light->frustumWindings );
|
||||
|
||||
// a projected light will have one shadowFrustum, a point light will have
|
||||
// six unless the light center is outside the box
|
||||
R_MakeShadowFrustums( light );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -601,11 +597,6 @@ void R_FreeLightDefDerivedData( idRenderLightLocal *ldef ) {
|
||||
dp->fogLight = NULL;
|
||||
}
|
||||
|
||||
// free all the interactions
|
||||
while ( ldef->firstInteraction != NULL ) {
|
||||
ldef->firstInteraction->UnlinkAndFree();
|
||||
}
|
||||
|
||||
// free all the references to the light
|
||||
for ( lref = ldef->references ; lref ; lref = nextRef ) {
|
||||
nextRef = lref->ownerNext;
|
||||
@@ -653,11 +644,6 @@ void R_FreeEntityDefDerivedData( idRenderEntityLocal *def, bool keepDecals, bool
|
||||
}
|
||||
}
|
||||
|
||||
// free all the interactions
|
||||
while ( def->firstInteraction != NULL ) {
|
||||
def->firstInteraction->UnlinkAndFree();
|
||||
}
|
||||
|
||||
// clear the dynamic model if present
|
||||
if ( def->dynamicModel ) {
|
||||
def->dynamicModel = NULL;
|
||||
@@ -697,10 +683,6 @@ R_FreeEntityDefDerivedData
|
||||
==================
|
||||
*/
|
||||
void R_ClearEntityDefDynamicModel( idRenderEntityLocal *def ) {
|
||||
// free all the interaction surfaces
|
||||
for( idInteraction *inter = def->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = inter->entityNext ) {
|
||||
inter->FreeSurfaces();
|
||||
}
|
||||
|
||||
// clear the dynamic model if present
|
||||
if ( def->dynamicModel ) {
|
||||
|
||||
+2
-81
@@ -95,8 +95,6 @@ SURFACES
|
||||
|
||||
#include "ModelDecal.h"
|
||||
#include "ModelOverlay.h"
|
||||
#include "Interaction.h"
|
||||
|
||||
|
||||
// drawSurf_t structures command the back end to render surfaces
|
||||
// a given srfTriangles_t may be used with multiple viewEntity_t,
|
||||
@@ -142,8 +140,8 @@ typedef struct areaReference_s {
|
||||
struct areaReference_s *areaNext; // chain in the area
|
||||
struct areaReference_s *areaPrev;
|
||||
struct areaReference_s *ownerNext; // chain on either the entityDef or lightDef
|
||||
idRenderEntityLocal * entity; // only one of entity / light will be non-NULL
|
||||
idRenderLightLocal * light; // only one of entity / light will be non-NULL
|
||||
class idRenderEntityLocal * entity; // only one of entity / light will be non-NULL
|
||||
class idRenderLightLocal * light; // only one of entity / light will be non-NULL
|
||||
struct portalArea_s * area; // so owners can find all the areas they are in
|
||||
} areaReference_t;
|
||||
|
||||
@@ -227,8 +225,6 @@ public:
|
||||
struct viewLight_s * viewLight;
|
||||
|
||||
areaReference_t * references; // each area the light is present in will have a lightRef
|
||||
idInteraction * firstInteraction; // doubly linked list
|
||||
idInteraction * lastInteraction;
|
||||
|
||||
struct doublePortal_s * foggedPortals;
|
||||
};
|
||||
@@ -283,8 +279,6 @@ public:
|
||||
idRenderModelOverlay * overlay; // blood overlays on animated models
|
||||
|
||||
areaReference_t * entityRefs; // chain of all references
|
||||
idInteraction * firstInteraction; // doubly linked list
|
||||
idInteraction * lastInteraction;
|
||||
|
||||
bool needsPortalSky;
|
||||
|
||||
@@ -1387,79 +1381,6 @@ typedef enum {
|
||||
PP_LIGHT_FALLOFF_TQ = 20 // only for NV programs
|
||||
} programParameter_t;
|
||||
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
TR_STENCILSHADOWS
|
||||
|
||||
"facing" should have one more element than tri->numIndexes / 3, which should be set to 1
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
void R_MakeShadowFrustums( idRenderLightLocal *def );
|
||||
|
||||
typedef enum {
|
||||
SG_DYNAMIC, // use infinite projections
|
||||
SG_STATIC, // clip to bounds
|
||||
SG_OFFLINE // perform very time consuming optimizations
|
||||
} shadowGen_t;
|
||||
|
||||
srfTriangles_t *R_CreateShadowVolume( const idRenderEntityLocal *ent,
|
||||
const srfTriangles_t *tri, const idRenderLightLocal *light,
|
||||
shadowGen_t optimize, srfCullInfo_t &cullInfo );
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
TR_TURBOSHADOW
|
||||
|
||||
Fast, non-clipped overshoot shadow volumes
|
||||
|
||||
"facing" should have one more element than tri->numIndexes / 3, which should be set to 1
|
||||
calling this function may modify "facing" based on culling
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent,
|
||||
const srfTriangles_t *tri, const idRenderLightLocal *light,
|
||||
srfCullInfo_t &cullInfo );
|
||||
|
||||
srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
|
||||
const srfTriangles_t *tri, const idRenderLightLocal *light,
|
||||
srfCullInfo_t &cullInfo );
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
util/shadowopt3
|
||||
|
||||
dmap time optimization of shadow volumes, called from R_CreateShadowVolume
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
idVec3 *verts; // includes both front and back projections, caller should free
|
||||
int numVerts;
|
||||
glIndex_t *indexes; // caller should free
|
||||
|
||||
// indexes must be sorted frontCap, rearCap, silPlanes so the caps can be removed
|
||||
// when the viewer is in a position that they don't need to see them
|
||||
int numFrontCapIndexes;
|
||||
int numRearCapIndexes;
|
||||
int numSilPlaneIndexes;
|
||||
int totalIndexes;
|
||||
} optimizedShadow_t;
|
||||
|
||||
optimizedShadow_t SuperOptimizeOccluders( idVec4 *verts, glIndex_t *indexes, int numIndexes,
|
||||
idPlane projectionPlane, idVec3 projectionOrigin );
|
||||
|
||||
void CleanupOptimizedShadowTris( srfTriangles_t *tri );
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
|
||||
@@ -1,638 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 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.
|
||||
|
||||
Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 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 which accompanied the Doom 3 Source Code. 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.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
|
||||
|
||||
// Compute conservative shadow bounds as the intersection
|
||||
// of the object's bounds' shadow volume and the light's bounds.
|
||||
//
|
||||
// --cass
|
||||
|
||||
|
||||
template <class T, int N>
|
||||
struct MyArray
|
||||
{
|
||||
MyArray() : s(0) {}
|
||||
|
||||
MyArray( const MyArray<T,N> & cpy ) : s(cpy.s)
|
||||
{
|
||||
for(int i=0; i < s; i++)
|
||||
v[i] = cpy.v[i];
|
||||
}
|
||||
|
||||
void push_back(const T & i) {
|
||||
v[s] = i;
|
||||
s++;
|
||||
//if(s > max_size)
|
||||
// max_size = int(s);
|
||||
}
|
||||
|
||||
T & operator[](int i) {
|
||||
return v[i];
|
||||
}
|
||||
|
||||
const T & operator[](int i) const {
|
||||
return v[i];
|
||||
}
|
||||
|
||||
unsigned int size() const {
|
||||
return s;
|
||||
}
|
||||
|
||||
void empty() {
|
||||
s = 0;
|
||||
}
|
||||
|
||||
T v[N];
|
||||
int s;
|
||||
// static int max_size;
|
||||
};
|
||||
|
||||
typedef MyArray<int, 4> MyArrayInt;
|
||||
//int MyArrayInt::max_size = 0;
|
||||
typedef MyArray<idVec4, 16> MyArrayVec4;
|
||||
//int MyArrayVec4::max_size = 0;
|
||||
|
||||
struct poly
|
||||
{
|
||||
MyArrayInt vi;
|
||||
MyArrayInt ni;
|
||||
idVec4 plane;
|
||||
};
|
||||
|
||||
typedef MyArray<poly, 9> MyArrayPoly;
|
||||
//int MyArrayPoly::max_size = 0;
|
||||
|
||||
struct edge
|
||||
{
|
||||
int vi[2];
|
||||
int pi[2];
|
||||
};
|
||||
|
||||
typedef MyArray<edge, 15> MyArrayEdge;
|
||||
//int MyArrayEdge::max_size = 0;
|
||||
|
||||
MyArrayInt four_ints(int a, int b, int c, int d)
|
||||
{
|
||||
MyArrayInt vi;
|
||||
vi.push_back(a);
|
||||
vi.push_back(b);
|
||||
vi.push_back(c);
|
||||
vi.push_back(d);
|
||||
return vi;
|
||||
}
|
||||
|
||||
idVec3 homogeneous_difference(idVec4 a, idVec4 b)
|
||||
{
|
||||
idVec3 v;
|
||||
v.x = b.x * a.w - a.x * b.w;
|
||||
v.y = b.y * a.w - a.y * b.w;
|
||||
v.z = b.z * a.w - a.z * b.w;
|
||||
return v;
|
||||
}
|
||||
|
||||
// handles positive w only
|
||||
idVec4 compute_homogeneous_plane(idVec4 a, idVec4 b, idVec4 c)
|
||||
{
|
||||
idVec4 v, t;
|
||||
|
||||
if(a[3] == 0)
|
||||
{ t = a; a = b; b = c; c = t; }
|
||||
if(a[3] == 0)
|
||||
{ t = a; a = b; b = c; c = t; }
|
||||
|
||||
// can't handle 3 infinite points
|
||||
if( a[3] == 0 )
|
||||
return v;
|
||||
|
||||
idVec3 vb = homogeneous_difference(a, b);
|
||||
idVec3 vc = homogeneous_difference(a, c);
|
||||
|
||||
idVec3 n = vb.Cross(vc);
|
||||
n.Normalize();
|
||||
|
||||
v.x = n.x;
|
||||
v.y = n.y;
|
||||
v.z = n.z;
|
||||
|
||||
v.w = - (n * idVec3(a.x, a.y, a.z)) / a.w ;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
struct polyhedron
|
||||
{
|
||||
MyArrayVec4 v;
|
||||
MyArrayPoly p;
|
||||
MyArrayEdge e;
|
||||
|
||||
void add_quad( int va, int vb, int vc, int vd )
|
||||
{
|
||||
poly pg;
|
||||
pg.vi = four_ints(va, vb, vc, vd);
|
||||
pg.ni = four_ints(-1, -1, -1, -1);
|
||||
pg.plane = compute_homogeneous_plane(v[va], v[vb], v[vc]);
|
||||
p.push_back(pg);
|
||||
}
|
||||
|
||||
void discard_neighbor_info()
|
||||
{
|
||||
for(unsigned int i = 0; i < p.size(); i++ )
|
||||
{
|
||||
MyArrayInt & ni = p[i].ni;
|
||||
for(unsigned int j = 0; j < ni.size(); j++)
|
||||
ni[j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void compute_neighbors()
|
||||
{
|
||||
e.empty();
|
||||
|
||||
discard_neighbor_info();
|
||||
|
||||
bool found;
|
||||
int P = p.size();
|
||||
// for each polygon
|
||||
for(int i = 0; i < P-1; i++ )
|
||||
{
|
||||
const MyArrayInt & vi = p[i].vi;
|
||||
MyArrayInt & ni = p[i].ni;
|
||||
int Si = vi.size();
|
||||
|
||||
// for each edge of that polygon
|
||||
for(int ii=0; ii < Si; ii++)
|
||||
{
|
||||
int ii0 = ii;
|
||||
int ii1 = (ii+1) % Si;
|
||||
|
||||
// continue if we've already found this neighbor
|
||||
if(ni[ii] != -1)
|
||||
continue;
|
||||
found = false;
|
||||
// check all remaining polygons
|
||||
for(int j = i+1; j < P; j++ )
|
||||
{
|
||||
const MyArrayInt & vj = p[j].vi;
|
||||
MyArrayInt & nj = p[j].ni;
|
||||
int Sj = vj.size();
|
||||
|
||||
for( int jj = 0; jj < Sj; jj++ )
|
||||
{
|
||||
int jj0 = jj;
|
||||
int jj1 = (jj+1) % Sj;
|
||||
if(vi[ii0] == vj[jj1] && vi[ii1] == vj[jj0])
|
||||
{
|
||||
edge ed;
|
||||
ed.vi[0] = vi[ii0];
|
||||
ed.vi[1] = vi[ii1];
|
||||
ed.pi[0] = i;
|
||||
ed.pi[1] = j;
|
||||
e.push_back(ed);
|
||||
ni[ii] = j;
|
||||
nj[jj] = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else if ( vi[ii0] == vj[jj0] && vi[ii1] == vj[jj1] )
|
||||
{
|
||||
fprintf(stderr,"why am I here?\n");
|
||||
}
|
||||
}
|
||||
if( found )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void recompute_planes()
|
||||
{
|
||||
// for each polygon
|
||||
for(unsigned int i = 0; i < p.size(); i++ )
|
||||
{
|
||||
p[i].plane = compute_homogeneous_plane(v[p[i].vi[0]], v[p[i].vi[1]], v[p[i].vi[2]]);
|
||||
}
|
||||
}
|
||||
|
||||
void transform(const idMat4 & m)
|
||||
{
|
||||
for(unsigned int i=0; i < v.size(); i++ )
|
||||
v[i] = m * v[i];
|
||||
recompute_planes();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// make a unit cube
|
||||
polyhedron PolyhedronFromBounds( const idBounds & b )
|
||||
{
|
||||
|
||||
// 3----------2
|
||||
// |\ /|
|
||||
// | \ / |
|
||||
// | 7--6 |
|
||||
// | | | |
|
||||
// | 4--5 |
|
||||
// | / \ |
|
||||
// | / \ |
|
||||
// 0----------1
|
||||
//
|
||||
|
||||
static polyhedron p;
|
||||
|
||||
if( p.e.size() == 0 ) {
|
||||
|
||||
p.v.push_back(idVec4( -1, -1, 1, 1));
|
||||
p.v.push_back(idVec4( 1, -1, 1, 1));
|
||||
p.v.push_back(idVec4( 1, 1, 1, 1));
|
||||
p.v.push_back(idVec4( -1, 1, 1, 1));
|
||||
p.v.push_back(idVec4( -1, -1, -1, 1));
|
||||
p.v.push_back(idVec4( 1, -1, -1, 1));
|
||||
p.v.push_back(idVec4( 1, 1, -1, 1));
|
||||
p.v.push_back(idVec4( -1, 1, -1, 1));
|
||||
|
||||
p.add_quad( 0, 1, 2, 3 );
|
||||
p.add_quad( 7, 6, 5, 4 );
|
||||
p.add_quad( 1, 0, 4, 5 );
|
||||
p.add_quad( 2, 1, 5, 6 );
|
||||
p.add_quad( 3, 2, 6, 7 );
|
||||
p.add_quad( 0, 3, 7, 4 );
|
||||
|
||||
p.compute_neighbors();
|
||||
p.recompute_planes();
|
||||
p.v.empty(); // no need to copy this data since it'll be replaced
|
||||
}
|
||||
|
||||
polyhedron p2(p);
|
||||
|
||||
const idVec3 & min = b[0];
|
||||
const idVec3 & max = b[1];
|
||||
|
||||
p2.v.empty();
|
||||
p2.v.push_back(idVec4( min.x, min.y, max.z, 1));
|
||||
p2.v.push_back(idVec4( max.x, min.y, max.z, 1));
|
||||
p2.v.push_back(idVec4( max.x, max.y, max.z, 1));
|
||||
p2.v.push_back(idVec4( min.x, max.y, max.z, 1));
|
||||
p2.v.push_back(idVec4( min.x, min.y, min.z, 1));
|
||||
p2.v.push_back(idVec4( max.x, min.y, min.z, 1));
|
||||
p2.v.push_back(idVec4( max.x, max.y, min.z, 1));
|
||||
p2.v.push_back(idVec4( min.x, max.y, min.z, 1));
|
||||
|
||||
p2.recompute_planes();
|
||||
return p2;
|
||||
}
|
||||
|
||||
|
||||
polyhedron make_sv(const polyhedron & oc, idVec4 light)
|
||||
{
|
||||
static polyhedron lut[64];
|
||||
int index = 0;
|
||||
|
||||
for(unsigned int i = 0; i < 6; i++) {
|
||||
if( ( oc.p[i].plane * light ) > 0 )
|
||||
index |= 1<<i;
|
||||
}
|
||||
|
||||
if( lut[index].e.size() == 0 )
|
||||
{
|
||||
polyhedron & ph = lut[index];
|
||||
ph = oc;
|
||||
|
||||
int V = ph.v.size();
|
||||
for( int j = 0; j < V; j++ )
|
||||
{
|
||||
idVec3 proj = homogeneous_difference( light, ph.v[j] );
|
||||
ph.v.push_back( idVec4(proj.x, proj.y, proj.z, 0) );
|
||||
}
|
||||
|
||||
ph.p.empty();
|
||||
|
||||
for(unsigned int i=0; i < oc.p.size(); i++)
|
||||
{
|
||||
if( (oc.p[i].plane * light) > 0)
|
||||
{
|
||||
ph.p.push_back(oc.p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(ph.p.size() == 0)
|
||||
return ph = polyhedron();
|
||||
|
||||
ph.compute_neighbors();
|
||||
|
||||
MyArrayPoly vpg;
|
||||
int I = ph.p.size();
|
||||
|
||||
for(int i=0; i < I; i++)
|
||||
{
|
||||
MyArrayInt & vi = ph.p[i].vi;
|
||||
MyArrayInt & ni = ph.p[i].ni;
|
||||
int S = vi.size();
|
||||
|
||||
for(int j = 0; j < S; j++)
|
||||
{
|
||||
if( ni[j] == -1 )
|
||||
{
|
||||
poly pg;
|
||||
int a = vi[(j+1)%S];
|
||||
int b = vi[j];
|
||||
pg.vi = four_ints( a, b, b+V, a+V);
|
||||
pg.ni = four_ints(-1, -1, -1, -1);
|
||||
vpg.push_back(pg);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(unsigned int i = 0; i < vpg.size(); i++)
|
||||
ph.p.push_back(vpg[i]);
|
||||
|
||||
ph.compute_neighbors();
|
||||
ph.v.empty(); // no need to copy this data since it'll be replaced
|
||||
}
|
||||
|
||||
polyhedron ph2 = lut[index];
|
||||
|
||||
// initalize vertices
|
||||
ph2.v = oc.v;
|
||||
int V = ph2.v.size();
|
||||
for( int j = 0; j < V; j++ )
|
||||
{
|
||||
idVec3 proj = homogeneous_difference( light, ph2.v[j] );
|
||||
ph2.v.push_back( idVec4(proj.x, proj.y, proj.z, 0) );
|
||||
}
|
||||
|
||||
// need to compute planes for the shadow volume (sv)
|
||||
ph2.recompute_planes();
|
||||
|
||||
return ph2;
|
||||
}
|
||||
|
||||
typedef MyArray<idVec4, 36> MySegments;
|
||||
//int MySegments::max_size = 0;
|
||||
|
||||
void polyhedron_edges(polyhedron & a, MySegments & e)
|
||||
{
|
||||
e.empty();
|
||||
if(a.e.size() == 0 && a.p.size() != 0)
|
||||
a.compute_neighbors();
|
||||
|
||||
for(unsigned int i = 0; i < a.e.size(); i++)
|
||||
{
|
||||
e.push_back(a.v[a.e[i].vi[0]]);
|
||||
e.push_back(a.v[a.e[i].vi[1]]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// clip the segments of e by the planes of polyhedron a.
|
||||
void clip_segments(const polyhedron & ph, MySegments & is, MySegments & os)
|
||||
{
|
||||
const MyArrayPoly & p = ph.p;
|
||||
|
||||
for(unsigned int i = 0; i < is.size(); i+=2 )
|
||||
{
|
||||
idVec4 a = is[i ];
|
||||
idVec4 b = is[i+1];
|
||||
idVec4 c;
|
||||
|
||||
bool discard = false;
|
||||
|
||||
for(unsigned int j = 0; j < p.size(); j++ )
|
||||
{
|
||||
float da = a * p[j].plane;
|
||||
float db = b * p[j].plane;
|
||||
float rdw = 1/(da - db);
|
||||
|
||||
int code = 0;
|
||||
if( da > 0 )
|
||||
code = 2;
|
||||
if( db > 0 )
|
||||
code |= 1;
|
||||
|
||||
|
||||
switch ( code )
|
||||
{
|
||||
case 3:
|
||||
discard = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
c = -db * rdw * a + da * rdw * b;
|
||||
a = c;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
c = -db * rdw * a + da * rdw * b;
|
||||
b = c;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
common->Printf("bad clip code!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if( discard )
|
||||
break;
|
||||
}
|
||||
|
||||
if( ! discard )
|
||||
{
|
||||
os.push_back(a);
|
||||
os.push_back(b);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
idMat4 make_idMat4(const float * m)
|
||||
{
|
||||
return idMat4( m[ 0], m[ 4], m[ 8], m[12],
|
||||
m[ 1], m[ 5], m[ 9], m[13],
|
||||
m[ 2], m[ 6], m[10], m[14],
|
||||
m[ 3], m[ 7], m[11], m[15] );
|
||||
}
|
||||
|
||||
idVec3 v4to3(const idVec4 & v)
|
||||
{
|
||||
return idVec3(v.x/v.w, v.y/v.w, v.z/v.w);
|
||||
}
|
||||
|
||||
void draw_polyhedron( const viewDef_t *viewDef, const polyhedron & p, idVec4 color )
|
||||
{
|
||||
for(unsigned int i = 0; i < p.e.size(); i++)
|
||||
{
|
||||
viewDef->renderWorld->DebugLine( color, v4to3(p.v[p.e[i].vi[0]]), v4to3(p.v[p.e[i].vi[1]]));
|
||||
}
|
||||
}
|
||||
|
||||
void draw_segments( const viewDef_t *viewDef, const MySegments & s, idVec4 color )
|
||||
{
|
||||
for(unsigned int i = 0; i < s.size(); i+=2)
|
||||
{
|
||||
viewDef->renderWorld->DebugLine( color, v4to3(s[i]), v4to3(s[i+1]));
|
||||
}
|
||||
}
|
||||
|
||||
void world_to_hclip( const viewDef_t *viewDef, const idVec4 &global, idVec4 &clip ) {
|
||||
int i;
|
||||
idVec4 view;
|
||||
|
||||
for ( i = 0 ; i < 4 ; i ++ ) {
|
||||
view[i] =
|
||||
global[0] * viewDef->worldSpace.modelViewMatrix[ i + 0 * 4 ] +
|
||||
global[1] * viewDef->worldSpace.modelViewMatrix[ i + 1 * 4 ] +
|
||||
global[2] * viewDef->worldSpace.modelViewMatrix[ i + 2 * 4 ] +
|
||||
global[3] * viewDef->worldSpace.modelViewMatrix[ i + 3 * 4 ];
|
||||
}
|
||||
|
||||
|
||||
for ( i = 0 ; i < 4 ; i ++ ) {
|
||||
clip[i] =
|
||||
view[0] * viewDef->projectionMatrix[ i + 0 * 4 ] +
|
||||
view[1] * viewDef->projectionMatrix[ i + 1 * 4 ] +
|
||||
view[2] * viewDef->projectionMatrix[ i + 2 * 4 ] +
|
||||
view[3] * viewDef->projectionMatrix[ i + 3 * 4 ];
|
||||
}
|
||||
}
|
||||
|
||||
idScreenRect R_CalcIntersectionScissor( const idRenderLightLocal * lightDef,
|
||||
const idRenderEntityLocal * entityDef,
|
||||
const viewDef_t * viewDef ) {
|
||||
|
||||
idMat4 omodel = make_idMat4( entityDef->modelMatrix );
|
||||
idMat4 lmodel = make_idMat4( lightDef->modelMatrix );
|
||||
|
||||
// compute light polyhedron
|
||||
polyhedron lvol = PolyhedronFromBounds( lightDef->frustumTris->bounds );
|
||||
// transform it into world space
|
||||
//lvol.transform( lmodel );
|
||||
|
||||
// debug //
|
||||
if ( r_useInteractionScissors.GetInteger() == -2 ) {
|
||||
draw_polyhedron( viewDef, lvol, colorRed );
|
||||
}
|
||||
|
||||
// compute object polyhedron
|
||||
polyhedron vol = PolyhedronFromBounds( entityDef->referenceBounds );
|
||||
|
||||
//viewDef->renderWorld->DebugBounds( colorRed, lightDef->frustumTris->bounds );
|
||||
//viewDef->renderWorld->DebugBox( colorBlue, idBox( model->Bounds(), entityDef->parms.origin, entityDef->parms.axis ) );
|
||||
|
||||
// transform it into world space
|
||||
vol.transform( omodel );
|
||||
|
||||
// debug //
|
||||
if ( r_useInteractionScissors.GetInteger() == -2 ) {
|
||||
draw_polyhedron( viewDef, vol, colorBlue );
|
||||
}
|
||||
|
||||
// transform light position into world space
|
||||
idVec4 lightpos = idVec4(lightDef->globalLightOrigin.x,
|
||||
lightDef->globalLightOrigin.y,
|
||||
lightDef->globalLightOrigin.z,
|
||||
1.0f );
|
||||
|
||||
// generate shadow volume "polyhedron"
|
||||
polyhedron sv = make_sv(vol, lightpos);
|
||||
|
||||
MySegments in_segs, out_segs;
|
||||
|
||||
// get shadow volume edges
|
||||
polyhedron_edges(sv, in_segs);
|
||||
// clip them against light bounds planes
|
||||
clip_segments(lvol, in_segs, out_segs);
|
||||
|
||||
// get light bounds edges
|
||||
polyhedron_edges(lvol, in_segs);
|
||||
// clip them by the shadow volume
|
||||
clip_segments(sv, in_segs, out_segs);
|
||||
|
||||
// debug //
|
||||
if ( r_useInteractionScissors.GetInteger() == -2 ) {
|
||||
draw_segments( viewDef, out_segs, colorGreen );
|
||||
}
|
||||
|
||||
idBounds outbounds;
|
||||
outbounds.Clear();
|
||||
for( unsigned int i = 0; i < out_segs.size(); i++ ) {
|
||||
|
||||
idVec4 v;
|
||||
world_to_hclip( viewDef, out_segs[i], v );
|
||||
|
||||
if( v.w <= 0.0f ) {
|
||||
return lightDef->viewLight->scissorRect;
|
||||
}
|
||||
|
||||
idVec3 rv(v.x, v.y, v.z);
|
||||
rv /= v.w;
|
||||
|
||||
outbounds.AddPoint( rv );
|
||||
}
|
||||
|
||||
// limit the bounds to avoid an inside out scissor rectangle due to floating point to short conversion
|
||||
if ( outbounds[0].x < -1.0f ) {
|
||||
outbounds[0].x = -1.0f;
|
||||
}
|
||||
if ( outbounds[1].x > 1.0f ) {
|
||||
outbounds[1].x = 1.0f;
|
||||
}
|
||||
if ( outbounds[0].y < -1.0f ) {
|
||||
outbounds[0].y = -1.0f;
|
||||
}
|
||||
if ( outbounds[1].y > 1.0f ) {
|
||||
outbounds[1].y = 1.0f;
|
||||
}
|
||||
|
||||
float w2 = ( viewDef->viewport.x2 - viewDef->viewport.x1 + 1 ) / 2.0f;
|
||||
float x = viewDef->viewport.x1;
|
||||
float h2 = ( viewDef->viewport.y2 - viewDef->viewport.y1 + 1 ) / 2.0f;
|
||||
float y = viewDef->viewport.y1;
|
||||
|
||||
idScreenRect rect;
|
||||
rect.x1 = outbounds[0].x * w2 + w2 + x;
|
||||
rect.x2 = outbounds[1].x * w2 + w2 + x;
|
||||
rect.y1 = outbounds[0].y * h2 + h2 + y;
|
||||
rect.y2 = outbounds[1].y * h2 + h2 + y;
|
||||
rect.Expand();
|
||||
|
||||
rect.Intersect( lightDef->viewLight->scissorRect );
|
||||
|
||||
// debug //
|
||||
if ( r_useInteractionScissors.GetInteger() == -2 && !rect.IsEmpty() ) {
|
||||
viewDef->renderWorld->DebugScreenRect( colorYellow, rect, viewDef );
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -294,11 +294,6 @@ int R_TriSurfMemory( const srfTriangles_t *tri ) {
|
||||
return total;
|
||||
}
|
||||
|
||||
// used as a flag in interations
|
||||
if ( tri == LIGHT_TRIS_DEFERRED ) {
|
||||
return total;
|
||||
}
|
||||
|
||||
if ( tri->shadowVertexes != NULL ) {
|
||||
total += tri->numVerts * sizeof( tri->shadowVertexes[0] );
|
||||
} else if ( tri->verts != NULL ) {
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 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.
|
||||
|
||||
Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 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 which accompanied the Doom 3 Source Code. 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.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
int c_turboUsedVerts;
|
||||
int c_turboUnusedVerts;
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
R_CreateVertexProgramTurboShadowVolume
|
||||
|
||||
are dangling edges that are outside the light frustum still making planes?
|
||||
=====================
|
||||
*/
|
||||
srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent,
|
||||
const srfTriangles_t *tri, const idRenderLightLocal *light,
|
||||
srfCullInfo_t &cullInfo ) {
|
||||
int i, j;
|
||||
srfTriangles_t *newTri;
|
||||
silEdge_t *sil;
|
||||
const glIndex_t *indexes;
|
||||
const byte *facing;
|
||||
|
||||
R_CalcInteractionFacing( ent, tri, light, cullInfo );
|
||||
if ( r_useShadowProjectedCull.GetBool() ) {
|
||||
R_CalcInteractionCullBits( ent, tri, light, cullInfo );
|
||||
}
|
||||
|
||||
int numFaces = tri->numIndexes / 3;
|
||||
int numShadowingFaces = 0;
|
||||
facing = cullInfo.facing;
|
||||
|
||||
// if all the triangles are inside the light frustum
|
||||
if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
|
||||
|
||||
// count the number of shadowing faces
|
||||
for ( i = 0; i < numFaces; i++ ) {
|
||||
numShadowingFaces += facing[i];
|
||||
}
|
||||
numShadowingFaces = numFaces - numShadowingFaces;
|
||||
|
||||
} else {
|
||||
|
||||
// make all triangles that are outside the light frustum "facing", so they won't cast shadows
|
||||
indexes = tri->indexes;
|
||||
byte *modifyFacing = cullInfo.facing;
|
||||
const byte *cullBits = cullInfo.cullBits;
|
||||
for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
|
||||
if ( !modifyFacing[j] ) {
|
||||
int i1 = indexes[i+0];
|
||||
int i2 = indexes[i+1];
|
||||
int i3 = indexes[i+2];
|
||||
if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
|
||||
modifyFacing[j] = 1;
|
||||
} else {
|
||||
numShadowingFaces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !numShadowingFaces ) {
|
||||
// no faces are inside the light frustum and still facing the right way
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
|
||||
newTri = R_AllocStaticTriSurf();
|
||||
|
||||
newTri->numVerts = tri->numVerts * 2;
|
||||
|
||||
// alloc the max possible size
|
||||
#ifdef USE_TRI_DATA_ALLOCATOR
|
||||
R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
|
||||
glIndex_t *tempIndexes = newTri->indexes;
|
||||
glIndex_t *shadowIndexes = newTri->indexes;
|
||||
#else
|
||||
glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
|
||||
glIndex_t *shadowIndexes = tempIndexes;
|
||||
#endif
|
||||
|
||||
// create new triangles along sil planes
|
||||
for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
|
||||
|
||||
int f1 = facing[sil->p1];
|
||||
int f2 = facing[sil->p2];
|
||||
|
||||
if ( !( f1 ^ f2 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int v1 = sil->v1 << 1;
|
||||
int v2 = sil->v2 << 1;
|
||||
|
||||
// set the two triangle winding orders based on facing
|
||||
// without using a poorly-predictable branch
|
||||
|
||||
shadowIndexes[0] = v1;
|
||||
shadowIndexes[1] = v2 ^ f1;
|
||||
shadowIndexes[2] = v2 ^ f2;
|
||||
shadowIndexes[3] = v1 ^ f2;
|
||||
shadowIndexes[4] = v1 ^ f1;
|
||||
shadowIndexes[5] = v2 ^ 1;
|
||||
|
||||
shadowIndexes += 6;
|
||||
}
|
||||
|
||||
int numShadowIndexes = shadowIndexes - tempIndexes;
|
||||
|
||||
// we aren't bothering to separate front and back caps on these
|
||||
newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
|
||||
newTri->numShadowIndexesNoCaps = numShadowIndexes;
|
||||
newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
|
||||
|
||||
#ifdef USE_TRI_DATA_ALLOCATOR
|
||||
// decrease the size of the memory block to only store the used indexes
|
||||
R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
|
||||
#else
|
||||
// allocate memory for the indexes
|
||||
R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
|
||||
// copy the indexes we created for the sil planes
|
||||
SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
|
||||
#endif
|
||||
|
||||
// these have no effect, because they extend to infinity
|
||||
newTri->bounds.Clear();
|
||||
|
||||
// put some faces on the model and some on the distant projection
|
||||
indexes = tri->indexes;
|
||||
shadowIndexes = newTri->indexes + numShadowIndexes;
|
||||
for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
|
||||
if ( facing[j] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int i0 = indexes[i+0] << 1;
|
||||
shadowIndexes[2] = i0;
|
||||
shadowIndexes[3] = i0 ^ 1;
|
||||
int i1 = indexes[i+1] << 1;
|
||||
shadowIndexes[1] = i1;
|
||||
shadowIndexes[4] = i1 ^ 1;
|
||||
int i2 = indexes[i+2] << 1;
|
||||
shadowIndexes[0] = i2;
|
||||
shadowIndexes[5] = i2 ^ 1;
|
||||
|
||||
shadowIndexes += 6;
|
||||
}
|
||||
|
||||
return newTri;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
R_CreateTurboShadowVolume
|
||||
=====================
|
||||
*/
|
||||
srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
|
||||
const srfTriangles_t *tri, const idRenderLightLocal *light,
|
||||
srfCullInfo_t &cullInfo ) {
|
||||
int i, j;
|
||||
idVec3 localLightOrigin;
|
||||
srfTriangles_t *newTri;
|
||||
silEdge_t *sil;
|
||||
const glIndex_t *indexes;
|
||||
const byte *facing;
|
||||
|
||||
R_CalcInteractionFacing( ent, tri, light, cullInfo );
|
||||
if ( r_useShadowProjectedCull.GetBool() ) {
|
||||
R_CalcInteractionCullBits( ent, tri, light, cullInfo );
|
||||
}
|
||||
|
||||
int numFaces = tri->numIndexes / 3;
|
||||
int numShadowingFaces = 0;
|
||||
facing = cullInfo.facing;
|
||||
|
||||
// if all the triangles are inside the light frustum
|
||||
if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
|
||||
|
||||
// count the number of shadowing faces
|
||||
for ( i = 0; i < numFaces; i++ ) {
|
||||
numShadowingFaces += facing[i];
|
||||
}
|
||||
numShadowingFaces = numFaces - numShadowingFaces;
|
||||
|
||||
} else {
|
||||
|
||||
// make all triangles that are outside the light frustum "facing", so they won't cast shadows
|
||||
indexes = tri->indexes;
|
||||
byte *modifyFacing = cullInfo.facing;
|
||||
const byte *cullBits = cullInfo.cullBits;
|
||||
for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
|
||||
if ( !modifyFacing[j] ) {
|
||||
int i1 = indexes[i+0];
|
||||
int i2 = indexes[i+1];
|
||||
int i3 = indexes[i+2];
|
||||
if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
|
||||
modifyFacing[j] = 1;
|
||||
} else {
|
||||
numShadowingFaces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !numShadowingFaces ) {
|
||||
// no faces are inside the light frustum and still facing the right way
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newTri = R_AllocStaticTriSurf();
|
||||
|
||||
#ifdef USE_TRI_DATA_ALLOCATOR
|
||||
R_AllocStaticTriSurfShadowVerts( newTri, tri->numVerts * 2 );
|
||||
shadowCache_t *shadowVerts = newTri->shadowVertexes;
|
||||
#else
|
||||
shadowCache_t *shadowVerts = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowVerts[0] ) );
|
||||
#endif
|
||||
|
||||
R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
|
||||
|
||||
int *vertRemap = (int *)_alloca16( tri->numVerts * sizeof( vertRemap[0] ) );
|
||||
|
||||
SIMDProcessor->Memset( vertRemap, -1, tri->numVerts * sizeof( vertRemap[0] ) );
|
||||
|
||||
for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
|
||||
if ( facing[j] ) {
|
||||
continue;
|
||||
}
|
||||
// this may pull in some vertexes that are outside
|
||||
// the frustum, because they connect to vertexes inside
|
||||
vertRemap[tri->silIndexes[i+0]] = 0;
|
||||
vertRemap[tri->silIndexes[i+1]] = 0;
|
||||
vertRemap[tri->silIndexes[i+2]] = 0;
|
||||
}
|
||||
|
||||
newTri->numVerts = SIMDProcessor->CreateShadowCache( &shadowVerts->xyz, vertRemap, localLightOrigin, tri->verts, tri->numVerts );
|
||||
|
||||
c_turboUsedVerts += newTri->numVerts;
|
||||
c_turboUnusedVerts += tri->numVerts * 2 - newTri->numVerts;
|
||||
|
||||
#ifdef USE_TRI_DATA_ALLOCATOR
|
||||
R_ResizeStaticTriSurfShadowVerts( newTri, newTri->numVerts );
|
||||
#else
|
||||
R_AllocStaticTriSurfShadowVerts( newTri, newTri->numVerts );
|
||||
SIMDProcessor->Memcpy( newTri->shadowVertexes, shadowVerts, newTri->numVerts * sizeof( shadowVerts[0] ) );
|
||||
#endif
|
||||
|
||||
// alloc the max possible size
|
||||
#ifdef USE_TRI_DATA_ALLOCATOR
|
||||
R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
|
||||
glIndex_t *tempIndexes = newTri->indexes;
|
||||
glIndex_t *shadowIndexes = newTri->indexes;
|
||||
#else
|
||||
glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
|
||||
glIndex_t *shadowIndexes = tempIndexes;
|
||||
#endif
|
||||
|
||||
// create new triangles along sil planes
|
||||
for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
|
||||
|
||||
int f1 = facing[sil->p1];
|
||||
int f2 = facing[sil->p2];
|
||||
|
||||
if ( !( f1 ^ f2 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int v1 = vertRemap[sil->v1];
|
||||
int v2 = vertRemap[sil->v2];
|
||||
|
||||
// set the two triangle winding orders based on facing
|
||||
// without using a poorly-predictable branch
|
||||
|
||||
shadowIndexes[0] = v1;
|
||||
shadowIndexes[1] = v2 ^ f1;
|
||||
shadowIndexes[2] = v2 ^ f2;
|
||||
shadowIndexes[3] = v1 ^ f2;
|
||||
shadowIndexes[4] = v1 ^ f1;
|
||||
shadowIndexes[5] = v2 ^ 1;
|
||||
|
||||
shadowIndexes += 6;
|
||||
}
|
||||
|
||||
int numShadowIndexes = shadowIndexes - tempIndexes;
|
||||
|
||||
// we aren't bothering to separate front and back caps on these
|
||||
newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
|
||||
newTri->numShadowIndexesNoCaps = numShadowIndexes;
|
||||
newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
|
||||
|
||||
#ifdef USE_TRI_DATA_ALLOCATOR
|
||||
// decrease the size of the memory block to only store the used indexes
|
||||
R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
|
||||
#else
|
||||
// allocate memory for the indexes
|
||||
R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
|
||||
// copy the indexes we created for the sil planes
|
||||
SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
|
||||
#endif
|
||||
|
||||
// these have no effect, because they extend to infinity
|
||||
newTri->bounds.Clear();
|
||||
|
||||
// put some faces on the model and some on the distant projection
|
||||
indexes = tri->silIndexes;
|
||||
shadowIndexes = newTri->indexes + numShadowIndexes;
|
||||
for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
|
||||
if ( facing[j] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int i0 = vertRemap[indexes[i+0]];
|
||||
shadowIndexes[2] = i0;
|
||||
shadowIndexes[3] = i0 ^ 1;
|
||||
int i1 = vertRemap[indexes[i+1]];
|
||||
shadowIndexes[1] = i1;
|
||||
shadowIndexes[4] = i1 ^ 1;
|
||||
int i2 = vertRemap[indexes[i+2]];
|
||||
shadowIndexes[0] = i2;
|
||||
shadowIndexes[5] = i2 ^ 1;
|
||||
|
||||
shadowIndexes += 6;
|
||||
}
|
||||
|
||||
return newTri;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -885,7 +885,7 @@ static void BuildLightShadows( uEntity_t *e, mapLight_t *light ) {
|
||||
}
|
||||
|
||||
// take the shadower group list and create a beam tree and shadow volume
|
||||
light->shadowTris = CreateLightShadow( shadowerGroups, light );
|
||||
//light->shadowTris = CreateLightShadow( shadowerGroups, light );
|
||||
|
||||
if ( light->shadowTris && hasPerforatedSurface ) {
|
||||
// can't ever remove front faces, because we can see through some of them
|
||||
|
||||
Reference in New Issue
Block a user