From c5b542d38c75a1c2d3d458b0b2dd3f92a3407d54 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Thu, 14 May 2026 12:41:17 +0200 Subject: [PATCH] unify(ww3d2): Move dx8fvf, dx8indexbuffer, dx8vertexbuffer to Core --- .../Source/WWVegas/WW3D2/CMakeLists.txt | 16 +- .../Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp | 0 .../Libraries/Source/WWVegas/WW3D2/dx8fvf.h | 0 .../Source/WWVegas/WW3D2/dx8indexbuffer.cpp | 0 .../Source/WWVegas/WW3D2/dx8indexbuffer.h | 0 .../Source/WWVegas/WW3D2/dx8renderer.cpp | 0 .../Source/WWVegas/WW3D2/dx8renderer.h | 0 .../Source/WWVegas/WW3D2/dx8vertexbuffer.cpp | 0 .../Source/WWVegas/WW3D2/dx8vertexbuffer.h | 0 .../Source/WWVegas/WW3D2/CMakeLists.txt | 16 +- .../Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp | 103 - .../Libraries/Source/WWVegas/WW3D2/dx8fvf.h | 281 -- .../Source/WWVegas/WW3D2/dx8indexbuffer.cpp | 541 ---- .../Source/WWVegas/WW3D2/dx8indexbuffer.h | 197 -- .../Source/WWVegas/WW3D2/dx8renderer.cpp | 2287 ----------------- .../Source/WWVegas/WW3D2/dx8renderer.h | 351 --- .../Source/WWVegas/WW3D2/dx8vertexbuffer.cpp | 904 ------- .../Source/WWVegas/WW3D2/dx8vertexbuffer.h | 253 -- .../Source/WWVegas/WW3D2/CMakeLists.txt | 16 +- scripts/cpp/unify_move_files.py | 9 + 20 files changed, 33 insertions(+), 4941 deletions(-) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8fvf.h (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8renderer.h (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp (100%) rename {GeneralsMD/Code => Core}/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h (100%) delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.h delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8renderer.h delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp delete mode 100644 Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index 9ff4754aec9..69f7f239492 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -45,21 +45,21 @@ set(WW3D2_SRC dllist.h dx8caps.cpp dx8caps.h - #dx8fvf.cpp - #dx8fvf.h - #dx8indexbuffer.cpp - #dx8indexbuffer.h + dx8fvf.cpp + dx8fvf.h + dx8indexbuffer.cpp + dx8indexbuffer.h dx8list.h dx8polygonrenderer.cpp dx8polygonrenderer.h - #dx8renderer.cpp - #dx8renderer.h + dx8renderer.cpp + dx8renderer.h dx8rendererdebugger.cpp dx8rendererdebugger.h dx8texman.cpp dx8texman.h - #dx8vertexbuffer.cpp - #dx8vertexbuffer.h + dx8vertexbuffer.cpp + dx8vertexbuffer.h dx8webbrowser.cpp dx8webbrowser.h dx8wrapper.cpp diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp rename to Core/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.h b/Core/Libraries/Source/WWVegas/WW3D2/dx8fvf.h similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.h rename to Core/Libraries/Source/WWVegas/WW3D2/dx8fvf.h diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp rename to Core/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h b/Core/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h rename to Core/Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp rename to Core/Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8renderer.h b/Core/Libraries/Source/WWVegas/WW3D2/dx8renderer.h similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8renderer.h rename to Core/Libraries/Source/WWVegas/WW3D2/dx8renderer.h diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp rename to Core/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h b/Core/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h similarity index 100% rename from GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h rename to Core/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Generals/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index d1fb7a8dbf1..a63287dcd88 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -45,19 +45,19 @@ set(WW3D2_SRC #dllist.h # dx8caps.cpp # dx8caps.h - dx8fvf.cpp - dx8fvf.h - dx8indexbuffer.cpp - dx8indexbuffer.h +# dx8fvf.cpp +# dx8fvf.h +# dx8indexbuffer.cpp +# dx8indexbuffer.h #dx8list.h #dx8polygonrenderer.cpp #dx8polygonrenderer.h - dx8renderer.cpp - dx8renderer.h +# dx8renderer.cpp +# dx8renderer.h #dx8texman.cpp #dx8texman.h - dx8vertexbuffer.cpp - dx8vertexbuffer.h +# dx8vertexbuffer.cpp +# dx8vertexbuffer.h #dx8webbrowser.cpp #dx8webbrowser.h # dx8wrapper.cpp diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp deleted file mode 100644 index b24c295d3d5..00000000000 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program 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. -** -** This program 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 this program. If not, see . -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8fvf.h $* - * * - * Original Author:: Jani Penttinen * - * * - * $Author:: Kenny Mitchell * - * * - * $Modtime:: 06/26/02 5:06p $* - * * - * $Revision:: 7 $* - * * - * 06/26/02 KM VB Vertex format update for shaders * - * 07/17/02 KM VB Vertex format update for displacement mapping * - * 08/01/02 KM VB Vertex format update for cube mapping * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -#include "dx8fvf.h" -#include "wwstring.h" -#include - -static unsigned Get_FVF_Vertex_Size(unsigned FVF) -{ - return D3DXGetFVFVertexSize(FVF); -} - -FVFInfoClass::FVFInfoClass(unsigned FVF_) - : - FVF(FVF_), - fvf_size(Get_FVF_Vertex_Size(FVF)) -{ - location_offset=0; - blend_offset=location_offset; - - if ((FVF&D3DFVF_XYZ)==D3DFVF_XYZ) blend_offset+=3*sizeof(float); - normal_offset=blend_offset; - - if ( ((FVF&D3DFVF_XYZB4)==D3DFVF_XYZB4) && - ((FVF&D3DFVF_LASTBETA_UBYTE4)==D3DFVF_LASTBETA_UBYTE4) ) normal_offset+=3*sizeof(float)+sizeof(DWORD); - diffuse_offset=normal_offset; - - if ((FVF&D3DFVF_NORMAL)==D3DFVF_NORMAL) diffuse_offset+=3*sizeof(float); - specular_offset=diffuse_offset; - - if ((FVF&D3DFVF_DIFFUSE)==D3DFVF_DIFFUSE) specular_offset+=sizeof(DWORD); - texcoord_offset[0]=specular_offset; - - if ((FVF&D3DFVF_SPECULAR)==D3DFVF_SPECULAR) texcoord_offset[0]+=sizeof(DWORD); - - for (unsigned int i=1; i. -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8fvf.h $* - * * - * Original Author:: Jani Penttinen * - * * - * $Author:: Kenny Mitchell * - * * - * $Modtime:: 06/26/02 5:06p $* - * * - * $Revision:: 7 $* - * * - * 06/26/02 KM VB Vertex format update for shaders * - * 07/17/02 KM VB Vertex format update for displacement mapping * - * 08/01/02 KM VB Vertex format update for cube mapping * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -#pragma once - -#include "always.h" -#include -#ifdef WWDEBUG -#include "wwdebug.h" -#endif - -class StringClass; - -enum { - DX8_FVF_XYZ = D3DFVF_XYZ, - DX8_FVF_XYZN = D3DFVF_XYZ|D3DFVF_NORMAL, - DX8_FVF_XYZNUV1 = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, - DX8_FVF_XYZNUV2 = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2, - DX8_FVF_XYZNDUV1 = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1|D3DFVF_DIFFUSE, - DX8_FVF_XYZNDUV2 = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2|D3DFVF_DIFFUSE, - DX8_FVF_XYZDUV1 = D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_DIFFUSE, - DX8_FVF_XYZDUV2 = D3DFVF_XYZ|D3DFVF_TEX2|D3DFVF_DIFFUSE, - DX8_FVF_XYZUV1 = D3DFVF_XYZ|D3DFVF_TEX1, - DX8_FVF_XYZUV2 = D3DFVF_XYZ|D3DFVF_TEX2, - DX8_FVF_XYZNDUV1TG3 = (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE3(1)|D3DFVF_TEXCOORDSIZE3(2)|D3DFVF_TEXCOORDSIZE3(3)), - DX8_FVF_XYZNUV2DMAP = (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1) | D3DFVF_TEXCOORDSIZE2(2) ), - DX8_FVF_XYZNDCUBEMAP = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE //|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE3(0) -}; - -// ---------------------------------------------------------------------------- -// -// Util structures for vertex buffer handling. Cast the void pointer returned -// by the vertex buffer to one of these structures. -// -// ---------------------------------------------------------------------------- - -struct VertexFormatXYZ -{ - float x; - float y; - float z; -}; - -struct VertexFormatXYZNUV1 -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - float u1; - float v1; -}; - -struct VertexFormatXYZNUV2 -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - float u1; - float v1; - float u2; - float v2; -}; - -struct VertexFormatXYZN -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; -}; - -struct VertexFormatXYZNDUV1 -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - unsigned diffuse; - float u1; - float v1; -}; - -struct VertexFormatXYZNDUV2 -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - unsigned diffuse; - float u1; - float v1; - float u2; - float v2; -}; - -struct VertexFormatXYZDUV1 -{ - float x; - float y; - float z; - unsigned diffuse; - float u1; - float v1; -}; - -struct VertexFormatXYZDUV2 -{ - float x; - float y; - float z; - unsigned diffuse; - float u1; - float v1; - float u2; - float v2; -}; - -struct VertexFormatXYZUV1 -{ - float x; - float y; - float z; - float u1; - float v1; -}; - -struct VertexFormatXYZUV2 -{ - float x; - float y; - float z; - float u1; - float v1; - float u2; - float v2; -}; - -// todo KJM compress -struct VertexFormatXYZNDUV1TG3 -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - unsigned diffuse; - float u1; - float v1; - float Sx; - float Sy; - float Sz; - float Tx; - float Ty; - float Tz; - float SxTx; - float SxTy; - float SxTz; -}; - - -// displacement mapping format -struct VertexFormatXYZNUV2DMAP -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - float T1x; - float T1y; - float T1z; - float T1w; - float T2x; - float T2y; -}; - -// cube map format (texcoords are normally generated) -struct VertexFormatXYZNDCUBEMAP -{ - float x; - float y; - float z; - float nx; - float ny; - float nz; - unsigned diffuse; -// float u1; -// float v1; -// float w1; -}; - -// FVF info class can be created for any legal FVF. It constructs information -// of offsets to various elements in the vertex buffer. - -class FVFInfoClass -{ - W3DMPO_CODE(FVFInfoClass) - - mutable unsigned FVF; - mutable unsigned fvf_size; - - unsigned location_offset; - unsigned normal_offset; - unsigned blend_offset; - unsigned texcoord_offset[D3DDP_MAXTEXCOORD]; - unsigned diffuse_offset; - unsigned specular_offset; -public: - FVFInfoClass(unsigned FVF); - - unsigned Get_Location_Offset() const { return location_offset; } - unsigned Get_Normal_Offset() const { return normal_offset; } -#ifdef WWDEBUG - inline unsigned Get_Tex_Offset(unsigned int n) const { WWASSERT(n. -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8indexbuffer.cpp $* - * * - * Original Author:: Jani Penttinen * - * * - * $Author:: Jani_p $* - * * - * $Modtime:: 11/09/01 3:12p $* - * * - * $Revision:: 26 $* - * * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -//#define INDEX_BUFFER_LOG - -#include "dx8indexbuffer.h" -#include "dx8wrapper.h" -#include "dx8caps.h" -#include "sphere.h" -#include "thread.h" -#include "wwmemlog.h" - -#define DEFAULT_IB_SIZE 5000 - -static bool _DynamicSortingIndexArrayInUse=false; -static SortingIndexBufferClass* _DynamicSortingIndexArray; -static unsigned short _DynamicSortingIndexArraySize=0; -static unsigned short _DynamicSortingIndexArrayOffset=0; - -static bool _DynamicDX8IndexBufferInUse=false; -static DX8IndexBufferClass* _DynamicDX8IndexBuffer=nullptr; -static unsigned short _DynamicDX8IndexBufferSize=DEFAULT_IB_SIZE; -static unsigned short _DynamicDX8IndexBufferOffset=0; - -static int _IndexBufferCount; -static int _IndexBufferTotalIndices; -static int _IndexBufferTotalSize; - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -IndexBufferClass::IndexBufferClass(unsigned type_, unsigned short index_count_) - : - index_count(index_count_), - type(type_), - engine_refs(0) -{ - WWASSERT(type==BUFFER_TYPE_DX8 || type==BUFFER_TYPE_SORTING); - WWASSERT(index_count); - - _IndexBufferCount++; - _IndexBufferTotalIndices+=index_count; - _IndexBufferTotalSize+=index_count*sizeof(unsigned short); -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("New IB, %d indices, size %d bytes",index_count,index_count*sizeof(unsigned short))); - WWDEBUG_SAY(("Total IB count: %d, total %d indices, total size %d bytes", - _IndexBufferCount, - _IndexBufferTotalIndices, - _IndexBufferTotalSize)); -#endif -} - -IndexBufferClass::~IndexBufferClass() -{ - _IndexBufferCount--; - _IndexBufferTotalIndices-=index_count; - _IndexBufferTotalSize-=index_count*sizeof(unsigned short); -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("Delete IB, %d indices, size %d bytes",index_count,index_count*sizeof(unsigned short))); - WWDEBUG_SAY(("Total IB count: %d, total %d indices, total size %d bytes", - _IndexBufferCount, - _IndexBufferTotalIndices, - _IndexBufferTotalSize)); -#endif -} - -unsigned IndexBufferClass::Get_Total_Buffer_Count() -{ - return _IndexBufferCount; -} - -unsigned IndexBufferClass::Get_Total_Allocated_Indices() -{ - return _IndexBufferTotalIndices; -} - -unsigned IndexBufferClass::Get_Total_Allocated_Memory() -{ - return _IndexBufferTotalSize; -} - -void IndexBufferClass::Add_Engine_Ref() const -{ - engine_refs++; -} - -void IndexBufferClass::Release_Engine_Ref() const -{ - engine_refs--; - WWASSERT(engine_refs>=0); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -void IndexBufferClass::Copy(unsigned int* indices,unsigned first_index,unsigned count) -{ - WWASSERT(indices); - - if (first_index) { - DX8IndexBufferClass::AppendLockClass l(this,first_index,count); - unsigned short* inds=l.Get_Index_Array(); - for (unsigned v=0;vEngine_Refs()); - index_buffer->Add_Ref(); - switch (index_buffer->Type()) { - case BUFFER_TYPE_DX8: - DX8_Assert(); - DX8_ErrorCode(static_cast(index_buffer)->Get_DX8_Index_Buffer()->Lock( - 0, - index_buffer->Get_Index_Count()*sizeof(WORD), - (unsigned char**)&indices, - flags)); - break; - case BUFFER_TYPE_SORTING: - indices=static_cast(index_buffer)->index_buffer; - break; - default: - WWASSERT(0); - break; - } -} - -// ---------------------------------------------------------------------------- -// -// -// ---------------------------------------------------------------------------- - -IndexBufferClass::WriteLockClass::~WriteLockClass() -{ - DX8_THREAD_ASSERT(); - switch (index_buffer->Type()) { - case BUFFER_TYPE_DX8: - DX8_Assert(); - DX8_ErrorCode(static_cast(index_buffer)->index_buffer->Unlock()); - break; - case BUFFER_TYPE_SORTING: - break; - default: - WWASSERT(0); - break; - } - index_buffer->Release_Ref(); -} - -// ---------------------------------------------------------------------------- - -IndexBufferClass::AppendLockClass::AppendLockClass(IndexBufferClass* index_buffer_,unsigned start_index, unsigned index_range) - : - index_buffer(index_buffer_) -{ - DX8_THREAD_ASSERT(); - WWASSERT(start_index+index_range<=index_buffer->Get_Index_Count()); - WWASSERT(index_buffer); - WWASSERT(!index_buffer->Engine_Refs()); - index_buffer->Add_Ref(); - switch (index_buffer->Type()) { - case BUFFER_TYPE_DX8: - DX8_Assert(); - DX8_ErrorCode(static_cast(index_buffer)->index_buffer->Lock( - start_index*sizeof(unsigned short), - index_range*sizeof(unsigned short), - (unsigned char**)&indices, - 0)); - break; - case BUFFER_TYPE_SORTING: - indices=static_cast(index_buffer)->index_buffer+start_index; - break; - default: - WWASSERT(0); - break; - } -} - -// ---------------------------------------------------------------------------- - -IndexBufferClass::AppendLockClass::~AppendLockClass() -{ - DX8_THREAD_ASSERT(); - switch (index_buffer->Type()) { - case BUFFER_TYPE_DX8: - DX8_Assert(); - DX8_ErrorCode(static_cast(index_buffer)->index_buffer->Unlock()); - break; - case BUFFER_TYPE_SORTING: - break; - default: - WWASSERT(0); - break; - } - index_buffer->Release_Ref(); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -DX8IndexBufferClass::DX8IndexBufferClass(unsigned short index_count_,UsageType usage) - : - IndexBufferClass(BUFFER_TYPE_DX8,index_count_) -{ - DX8_THREAD_ASSERT(); - WWASSERT(index_count); - unsigned usage_flags= - D3DUSAGE_WRITEONLY| - ((usage&USAGE_DYNAMIC) ? D3DUSAGE_DYNAMIC : 0)| - ((usage&USAGE_NPATCHES) ? D3DUSAGE_NPATCHES : 0)| - ((usage&USAGE_SOFTWAREPROCESSING) ? D3DUSAGE_SOFTWAREPROCESSING : 0); - if (!DX8Wrapper::Get_Current_Caps()->Support_TnL()) { - usage_flags|=D3DUSAGE_SOFTWAREPROCESSING; - } - - HRESULT ret=DX8Wrapper::_Get_D3D_Device8()->CreateIndexBuffer( - sizeof(WORD)*index_count, - usage_flags, - D3DFMT_INDEX16, - (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, - &index_buffer); - - if (SUCCEEDED(ret)) { - return; - } - - WWDEBUG_SAY(("Index buffer creation failed, trying to release assets...")); - - // Index buffer creation failed, so try releasing least used textures and flushing the mesh cache. - - // Free all textures that haven't been used in the last 5 seconds - TextureClass::Invalidate_Old_Unused_Textures(5000); - - // Invalidate the mesh cache - WW3D::_Invalidate_Mesh_Cache(); - - // Try again... - ret=DX8Wrapper::_Get_D3D_Device8()->CreateIndexBuffer( - sizeof(WORD)*index_count, - usage_flags, - D3DFMT_INDEX16, - (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, - &index_buffer); - - if (SUCCEEDED(ret)) { - WWDEBUG_SAY(("...Index buffer creation successful")); - } - - // If it still fails it is fatal - DX8_ErrorCode(ret); -} - -// ---------------------------------------------------------------------------- - -DX8IndexBufferClass::~DX8IndexBufferClass() -{ - index_buffer->Release(); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -SortingIndexBufferClass::SortingIndexBufferClass(unsigned short index_count_) - : - IndexBufferClass(BUFFER_TYPE_SORTING,index_count_) -{ - WWMEMLOG(MEM_RENDERER); - WWASSERT(index_count); - - index_buffer=W3DNEWARRAY unsigned short[index_count]; -} - -// ---------------------------------------------------------------------------- - -SortingIndexBufferClass::~SortingIndexBufferClass() -{ - delete[] index_buffer; -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -DynamicIBAccessClass::DynamicIBAccessClass(unsigned short type_, unsigned short index_count_) - : - IndexCount(index_count_), - IndexBuffer(nullptr), - Type(type_) -{ - WWASSERT(Type==BUFFER_TYPE_DYNAMIC_DX8 || Type==BUFFER_TYPE_DYNAMIC_SORTING); - if (Type==BUFFER_TYPE_DYNAMIC_DX8) { - Allocate_DX8_Dynamic_Buffer(); - } - else { - Allocate_Sorting_Dynamic_Buffer(); - } -} - -DynamicIBAccessClass::~DynamicIBAccessClass() -{ - REF_PTR_RELEASE(IndexBuffer); - if (Type==BUFFER_TYPE_DYNAMIC_DX8) { - _DynamicDX8IndexBufferInUse=false; - _DynamicDX8IndexBufferOffset+=IndexCount; - } - else { - _DynamicSortingIndexArrayInUse=false; - _DynamicSortingIndexArrayOffset+=IndexCount; - } -} - -void DynamicIBAccessClass::_Deinit() -{ - WWASSERT ((_DynamicDX8IndexBuffer == nullptr) || (_DynamicDX8IndexBuffer->Num_Refs() == 1)); - REF_PTR_RELEASE(_DynamicDX8IndexBuffer); - _DynamicDX8IndexBufferInUse=false; - _DynamicDX8IndexBufferSize=DEFAULT_IB_SIZE; - _DynamicDX8IndexBufferOffset=0; - - WWASSERT ((_DynamicSortingIndexArray == nullptr) || (_DynamicSortingIndexArray->Num_Refs() == 1)); - REF_PTR_RELEASE(_DynamicSortingIndexArray); - _DynamicSortingIndexArrayInUse=false; - _DynamicSortingIndexArraySize=0; - _DynamicSortingIndexArrayOffset=0; -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -DynamicIBAccessClass::WriteLockClass::WriteLockClass(DynamicIBAccessClass* ib_access_) - : - DynamicIBAccess(ib_access_) -{ - DX8_THREAD_ASSERT(); - DynamicIBAccess->IndexBuffer->Add_Ref(); - switch (DynamicIBAccess->Get_Type()) { - case BUFFER_TYPE_DYNAMIC_DX8: - WWASSERT(DynamicIBAccess); -// WWASSERT(!dynamic_dx8_index_buffer->Engine_Refs()); - DX8_Assert(); - DX8_ErrorCode( - static_cast(DynamicIBAccess->IndexBuffer)->Get_DX8_Index_Buffer()->Lock( - DynamicIBAccess->IndexBufferOffset*sizeof(WORD), - DynamicIBAccess->Get_Index_Count()*sizeof(WORD), - (unsigned char**)&Indices, - !DynamicIBAccess->IndexBufferOffset ? D3DLOCK_DISCARD : D3DLOCK_NOOVERWRITE)); - break; - case BUFFER_TYPE_DYNAMIC_SORTING: - Indices=static_cast(DynamicIBAccess->IndexBuffer)->index_buffer; - Indices+=DynamicIBAccess->IndexBufferOffset; - break; - default: - WWASSERT(0); - break; - } -} - -DynamicIBAccessClass::WriteLockClass::~WriteLockClass() -{ - DX8_THREAD_ASSERT(); - switch (DynamicIBAccess->Get_Type()) { - case BUFFER_TYPE_DYNAMIC_DX8: - DX8_Assert(); - DX8_ErrorCode(static_cast(DynamicIBAccess->IndexBuffer)->Get_DX8_Index_Buffer()->Unlock()); - break; - case BUFFER_TYPE_DYNAMIC_SORTING: - break; - default: - WWASSERT(0); - break; - } - DynamicIBAccess->IndexBuffer->Release_Ref(); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -void DynamicIBAccessClass::Allocate_DX8_Dynamic_Buffer() -{ - WWMEMLOG(MEM_RENDERER); - WWASSERT(!_DynamicDX8IndexBufferInUse); - _DynamicDX8IndexBufferInUse=true; - - // If requesting more indices than dynamic index buffer can fit, delete the ib - // and adjust the size to the new count. - if (IndexCount>_DynamicDX8IndexBufferSize) { - REF_PTR_RELEASE(_DynamicDX8IndexBuffer); - _DynamicDX8IndexBufferSize=IndexCount; - if (_DynamicDX8IndexBufferSizeSupport_NPatches()) { - usage|=DX8IndexBufferClass::USAGE_NPATCHES; - } - - _DynamicDX8IndexBuffer=NEW_REF(DX8IndexBufferClass,( - _DynamicDX8IndexBufferSize, - (DX8IndexBufferClass::UsageType)usage)); - _DynamicDX8IndexBufferOffset=0; - } - - // Any room at the end of the buffer? - if (((unsigned)IndexCount+_DynamicDX8IndexBufferOffset)>_DynamicDX8IndexBufferSize) { - _DynamicDX8IndexBufferOffset=0; - } - - REF_PTR_SET(IndexBuffer,_DynamicDX8IndexBuffer); - IndexBufferOffset=_DynamicDX8IndexBufferOffset; -} - -void DynamicIBAccessClass::Allocate_Sorting_Dynamic_Buffer() -{ - WWMEMLOG(MEM_RENDERER); - WWASSERT(!_DynamicSortingIndexArrayInUse); - _DynamicSortingIndexArrayInUse=true; - - unsigned new_index_count=_DynamicSortingIndexArrayOffset+IndexCount; - WWASSERT(new_index_count<65536); - if (new_index_count>_DynamicSortingIndexArraySize) { - REF_PTR_RELEASE(_DynamicSortingIndexArray); - _DynamicSortingIndexArraySize=new_index_count; - if (_DynamicSortingIndexArraySize. -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8indexbuffer.h $* - * * - * Original Author:: Greg Hjelstrom * - * * - * $Author:: Jani_p $* - * * - * $Modtime:: 7/10/01 12:27p $* - * * - * $Revision:: 12 $* - * * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -#pragma once - -#include "always.h" -#include "wwdebug.h" -#include "sphere.h" - -class DX8Wrapper; -class SortingRendererClass; -struct IDirect3DIndexBuffer8; -class DX8IndexBufferClass; -class SortingIndexBufferClass; - -// ---------------------------------------------------------------------------- - -class IndexBufferClass : public RefCountClass -{ -protected: - virtual ~IndexBufferClass() override; -public: - IndexBufferClass(unsigned type, unsigned short index_count); - - void Copy(unsigned int* indices,unsigned start_index,unsigned index_count); - void Copy(unsigned short* indices,unsigned start_index,unsigned index_count); - - unsigned short Get_Index_Count() const { return index_count; } - - unsigned Type() const { return type; } - - void Add_Engine_Ref() const; - void Release_Engine_Ref() const; - unsigned Engine_Refs() const { return engine_refs; } - - class WriteLockClass - { - IndexBufferClass* index_buffer; - unsigned short* indices; - public: - WriteLockClass(IndexBufferClass* index_buffer, int flags=0); - ~WriteLockClass(); - - unsigned short* Get_Index_Array() { return indices; } - }; - - class AppendLockClass - { - IndexBufferClass* index_buffer; - unsigned short* indices; - public: - AppendLockClass(IndexBufferClass* index_buffer,unsigned start_index, unsigned index_range); - ~AppendLockClass(); - - unsigned short* Get_Index_Array() { return indices; } - }; - - static unsigned Get_Total_Buffer_Count(); - static unsigned Get_Total_Allocated_Indices(); - static unsigned Get_Total_Allocated_Memory(); - -protected: - mutable int engine_refs; - unsigned short index_count; // number of indices - unsigned type; -}; - - -// HY 2/14/01 -// Created -class DynamicIBAccessClass -{ - W3DMPO_CODE(DynamicIBAccessClass) - - friend DX8Wrapper; - friend SortingRendererClass; - - unsigned Type; - unsigned short IndexCount; - unsigned short IndexBufferOffset; - IndexBufferClass* IndexBuffer; - - void Allocate_Sorting_Dynamic_Buffer(); - void Allocate_DX8_Dynamic_Buffer(); - -public: - DynamicIBAccessClass(unsigned short type, unsigned short index_count); - ~DynamicIBAccessClass(); - - unsigned Get_Type() const { return Type; } - unsigned short Get_Index_Count() const { return IndexCount; } - - // Call at the end of the execution, or at whatever time you wish to release - // the recycled dynamic index buffer. - static void _Deinit(); - static void _Reset(bool frame_changed); - static unsigned short Get_Default_Index_Count(); ///. -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8renderer.cpp $* - * * - * Original Author:: Greg Hjelstrom * - * * - * Author : Kenny Mitchell * - * * - * $Modtime:: 06/27/02 1:27p $* - * * - * $Revision:: 111 $* - * * - * 06/27/02 KM Changes to max texture stage caps * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -//#define ENABLE_CATEGORY_LOG -//#define ENABLE_STRIPING - -#include "dx8renderer.h" -#include "dx8wrapper.h" -#include "dx8polygonrenderer.h" -#include "dx8vertexbuffer.h" -#include "dx8indexbuffer.h" -#include "dx8fvf.h" -#include "dx8caps.h" -#include "dx8rendererdebugger.h" -#include "wwdebug.h" -#include "wwprofile.h" -#include "wwmemlog.h" -#include "rinfo.h" -#include "statistics.h" -#include "meshmdl.h" -#include "vp.h" -#include "decalmsh.h" -#include "matpass.h" -#include "camera.h" -#include "stripoptimizer.h" -#include "meshgeometry.h" - -/* -** Global Instance of the DX8MeshRender -*/ -DX8MeshRendererClass TheDX8MeshRenderer; -bool DX8TextureCategoryClass::m_gForceMultiply = false; // Forces opaque materials to use the multiply blend - pseudo transparent effect. jba. -// ---------------------------------------------------------------------------- - -static DynamicVectorClass _TempVertexBuffer; -static DynamicVectorClass _TempNormalBuffer; - -static MultiListClass _RegisteredMeshList; -static TextureCategoryList texture_category_delete_list; -static FVFCategoryList fvf_category_container_delete_list; - -// helper data structure -class PolyRemover : public MultiListObjectClass -{ -public: - DX8TextureCategoryClass * src; - DX8TextureCategoryClass * dest; - DX8PolygonRendererClass * pr; -}; - -typedef MultiListClass PolyRemoverList; -typedef MultiListIterator PolyRemoverListIterator; - -#define VERTEX_BUFFER_OVERFLOW 0xffff //'Generals' flag to signal when a mesh didn't fit in streaming vertex buffer. - -/** -** PolyRenderTaskClass -** This is a record of a polyrendere that needs to be rendered -** for this frame. Since MeshClass instances can share meshmodels -** (and therefore their dx8 polygon renderers) this record contains -** a pointer to the polygon renderer and the MeshClass instance that -** it is being rendered for. -*/ -class PolyRenderTaskClass : public AutoPoolClass -{ -public: - PolyRenderTaskClass(DX8PolygonRendererClass * p_renderer,MeshClass * p_mesh) : - Renderer(p_renderer), - Mesh(p_mesh), - NextVisible(nullptr) - { - WWASSERT(Renderer != nullptr); - WWASSERT(Mesh != nullptr); - Mesh->Add_Ref(); - } - - ~PolyRenderTaskClass() - { - Mesh->Release_Ref(); - } - - DX8PolygonRendererClass * Peek_Polygon_Renderer() { return Renderer; } - MeshClass * Peek_Mesh() { return Mesh; } - - PolyRenderTaskClass * Get_Next_Visible() { return NextVisible; } - void Set_Next_Visible(PolyRenderTaskClass * prtc) { NextVisible = prtc; } - -protected: - - DX8PolygonRendererClass * Renderer; - MeshClass * Mesh; - PolyRenderTaskClass * NextVisible; - -}; - -DEFINE_AUTO_POOL(PolyRenderTaskClass, 256); - -/** -** MatPassTaskClass -** This is the record of a material pass that needs to be rendered on -** a particular mesh. These are linked into the FVF container which -** contains the mesh model. They are also pooled to remove memory -** allocation overhead. -*/ -class MatPassTaskClass : public AutoPoolClass -{ -public: - MatPassTaskClass(MaterialPassClass * pass,MeshClass * mesh) : - MaterialPass(pass), - Mesh(mesh), - NextVisible(nullptr) - { - WWASSERT(MaterialPass != nullptr); - WWASSERT(Mesh != nullptr); - MaterialPass->Add_Ref(); - Mesh->Add_Ref(); - } - - ~MatPassTaskClass() - { - MaterialPass->Release_Ref(); - Mesh->Release_Ref(); - } - - MaterialPassClass * Peek_Material_Pass() { return MaterialPass; } - MeshClass * Peek_Mesh() { return Mesh; } - - MatPassTaskClass * Get_Next_Visible() { return NextVisible; } - void Set_Next_Visible(MatPassTaskClass * mpr) { NextVisible = mpr; } - -private: - - MaterialPassClass * MaterialPass; - MeshClass * Mesh; - MatPassTaskClass * NextVisible; -}; - -DEFINE_AUTO_POOL(MatPassTaskClass, 256); - - -// ---------------------------------------------------------------------------- - - -inline static bool Equal_Material(const VertexMaterialClass* mat1,const VertexMaterialClass* mat2) -{ - int crc0 = mat1 ? mat1->Get_CRC() : 0; - int crc1 = mat2 ? mat2->Get_CRC() : 0; - return (crc0 == crc1); -} - - -DX8TextureCategoryClass::DX8TextureCategoryClass( - DX8FVFCategoryContainer* container_, - TextureClass** texs, - ShaderClass shd, - VertexMaterialClass* mat, - int pass_) - : - pass(pass_), - shader(shd), - render_task_head(nullptr), - material(mat), - container(container_) -{ - WWASSERT(pass>=0); - WWASSERT(passAdd_Ref(); -} - -DX8TextureCategoryClass::~DX8TextureCategoryClass() -{ - // Unregistering the mesh where polygon renderers are connected to kills all polygon renderers - while (DX8PolygonRendererClass* p_renderer=PolygonRendererList.Get_Head()) { - TheDX8MeshRenderer.Unregister_Mesh_Type(p_renderer->Get_Mesh_Model_Class()); - } - for (int a=0;aSet_Next_Visible(render_task_head); - render_task_head = new_prt; - - container->Add_Visible_Texture_Category(this,pass); -} - -void DX8TextureCategoryClass::Add_Polygon_Renderer(DX8PolygonRendererClass* p_renderer,DX8PolygonRendererClass* add_after_this) -{ - WWASSERT(p_renderer!=nullptr); - WWASSERT(!PolygonRendererList.Contains(p_renderer)); - - if (add_after_this != nullptr) { - bool res = PolygonRendererList.Add_After(p_renderer,add_after_this,false); - WWASSERT(res); - } else { - PolygonRendererList.Add(p_renderer); - } - - p_renderer->Set_Texture_Category(this); -} - -void DX8TextureCategoryClass::Remove_Polygon_Renderer(DX8PolygonRendererClass* p_renderer) -{ - PolygonRendererList.Remove(p_renderer); - p_renderer->Set_Texture_Category(nullptr); - if (PolygonRendererList.Peek_Head() == nullptr) { - container->Remove_Texture_Category(this); - texture_category_delete_list.Add_Tail(this); - } -} - - -void DX8FVFCategoryContainer::Remove_Texture_Category(DX8TextureCategoryClass* tex_category) -{ - unsigned pass=0; - for (;passSet_Next_Visible(new_mpr); - } - - visible_matpass_tail = new_mpr; - AnythingToRender=true; -} - -void DX8FVFCategoryContainer::Render_Procedural_Material_Passes() -{ - // additional passes - MatPassTaskClass * mpr = visible_matpass_head; - MatPassTaskClass * last_mpr = nullptr; - bool renderTasksRemaining=false; - - while (mpr != nullptr) { - SNAPSHOT_SAY(("Render_Procedural_Material_Pass")); - - MeshClass * mesh = mpr->Peek_Mesh(); - - if (mesh->Get_Base_Vertex_Offset() == VERTEX_BUFFER_OVERFLOW) //check if this mesh is valid - { //skip this mesh so it gets rendered later after vertices are filled in. - last_mpr = mpr; - mpr = mpr->Get_Next_Visible(); - renderTasksRemaining = true; - continue; - } - - mpr->Peek_Mesh()->Render_Material_Pass(mpr->Peek_Material_Pass(),index_buffer); - MatPassTaskClass * next_mpr = mpr->Get_Next_Visible(); - - // remove from list, then delete - if (last_mpr == nullptr) { - visible_matpass_head = next_mpr; - } else { - last_mpr->Set_Next_Visible(next_mpr); - } - - delete mpr; - mpr = next_mpr; - } - - visible_matpass_tail = renderTasksRemaining ? last_mpr : nullptr; -} - -void DX8RigidFVFCategoryContainer::Add_Delayed_Visible_Material_Pass(MaterialPassClass * pass, MeshClass * mesh) -{ - MatPassTaskClass * new_mpr = new MatPassTaskClass(pass,mesh); - - if (delayed_matpass_head == nullptr) { - WWASSERT(delayed_matpass_tail == nullptr); - delayed_matpass_head = new_mpr; - } else { - WWASSERT(delayed_matpass_tail != nullptr); - delayed_matpass_tail->Set_Next_Visible(new_mpr); - } - - delayed_matpass_tail = new_mpr; - AnyDelayedPassesToRender=true; -} - -void DX8RigidFVFCategoryContainer::Render_Delayed_Procedural_Material_Passes() -{ - if (!Any_Delayed_Passes_To_Render()) return; - AnyDelayedPassesToRender=false; - - DX8Wrapper::Set_Vertex_Buffer(vertex_buffer); - DX8Wrapper::Set_Index_Buffer(index_buffer,0); - - SNAPSHOT_SAY(("DX8RigidFVFCategoryContainer::Render_Delayed_Procedural_Material_Passes()")); - - // additional passes - MatPassTaskClass * mpr = delayed_matpass_head; - while (mpr != nullptr) { - - mpr->Peek_Mesh()->Render_Material_Pass(mpr->Peek_Material_Pass(),index_buffer); - MatPassTaskClass * next_mpr = mpr->Get_Next_Visible(); - - delete mpr; - mpr = next_mpr; - } - - delayed_matpass_head = delayed_matpass_tail = nullptr; -} - - -void DX8TextureCategoryClass::Log(bool only_visible) -{ -#ifdef ENABLE_CATEGORY_LOG - StringClass work(255,true); - work.Format(" DX8TextureCategoryClass"); - - StringClass work2(255,true); - for (int stage=0;stageGet_Name() : "-"); - work+=work2; - } - work2.Format("\n material: %x (%s)\n shader: %x", material, material ? material->Get_Name() : "-", shader); - work+=work2; - WWDEBUG_SAY((work)); - - work.Format(" %8s %8s %6s %6s %6s %5s %s", - "idx_cnt", - "poly_cnt", - "i_offs", - "min_vi", - "vi_rng", - "ident", - "name"); - WWDEBUG_SAY((work)); - - DX8PolygonRendererListIterator it(&PolygonRendererList); - while (!it.Is_Done()) { - - DX8PolygonRendererClass* p_renderer = it.Peek_Obj(); - - PolyRenderTaskClass * prtc=render_task_head; - while (prtc) { - if (prtc->Peek_Polygon_Renderer()==p_renderer) break; - prtc = prtc->Get_Next_Visible(); - } - - if (prtc != nullptr) { - WWDEBUG_SAY(("+")); - p_renderer->Log(); - } else { - if (!only_visible) { - WWDEBUG_SAY(("-")); - p_renderer->Log(); - } - } - it.Next(); - } -#endif -} - -// ---------------------------------------------------------------------------- - -DX8FVFCategoryContainer::DX8FVFCategoryContainer(unsigned FVF_,bool sorting_) - : - FVF(FVF_), - sorting(sorting_), - visible_matpass_head(nullptr), - visible_matpass_tail(nullptr), - index_buffer(nullptr), - used_indices(0), - passes(MAX_PASSES), - uv_coordinate_channels(0), - AnythingToRender(false), - AnyDelayedPassesToRender(false) -{ - if ((FVF&D3DFVF_TEX1)==D3DFVF_TEX1) uv_coordinate_channels=1; - if ((FVF&D3DFVF_TEX2)==D3DFVF_TEX2) uv_coordinate_channels=2; - if ((FVF&D3DFVF_TEX3)==D3DFVF_TEX3) uv_coordinate_channels=3; - if ((FVF&D3DFVF_TEX4)==D3DFVF_TEX4) uv_coordinate_channels=4; - if ((FVF&D3DFVF_TEX5)==D3DFVF_TEX5) uv_coordinate_channels=5; - if ((FVF&D3DFVF_TEX6)==D3DFVF_TEX6) uv_coordinate_channels=6; - if ((FVF&D3DFVF_TEX7)==D3DFVF_TEX7) uv_coordinate_channels=7; - if ((FVF&D3DFVF_TEX8)==D3DFVF_TEX8) uv_coordinate_channels=8; -} - -// ---------------------------------------------------------------------------- - -DX8FVFCategoryContainer::~DX8FVFCategoryContainer() -{ - REF_PTR_RELEASE(index_buffer); - - for (unsigned p=0;pPeek_Texture(stage)==texture) { - // Compare all stage's textures - dest_tex_category=dest_it.Peek_Obj(); - bool all_textures_same = true; - for (unsigned int s = 0; s < MeshMatDescClass::MAX_TEX_STAGES; s++) { - if (stage!=s) { - all_textures_same = all_textures_same && (dest_tex_category->Peek_Texture(s) == ref_category->Peek_Texture(s)); - } - } - if (all_textures_same && - Equal_Material(dest_tex_category->Peek_Material(),ref_category->Peek_Material()) && - dest_tex_category->Get_Shader()==ref_category->Get_Shader()) { - return dest_tex_category; - } - } - dest_it.Next(); - } - return nullptr; -} - -DX8TextureCategoryClass* DX8FVFCategoryContainer::Find_Matching_Texture_Category( - VertexMaterialClass* vmat, - unsigned pass, - DX8TextureCategoryClass* ref_category) -{ - // Find texture category which matches ref_category's properties but has 'vmat' on given pass - DX8TextureCategoryClass* dest_tex_category=nullptr; - TextureCategoryListIterator dest_it(&texture_category_list[pass]); - while (!dest_it.Is_Done()) { - if (Equal_Material(dest_it.Peek_Obj()->Peek_Material(),vmat)) { - // Compare all stage's textures - dest_tex_category=dest_it.Peek_Obj(); - bool all_textures_same = true; - for (unsigned int s = 0; s < MeshMatDescClass::MAX_TEX_STAGES; s++) - all_textures_same = all_textures_same && (dest_tex_category->Peek_Texture(s) == ref_category->Peek_Texture(s)); - if (all_textures_same && - dest_tex_category->Get_Shader()==ref_category->Get_Shader()) { - return dest_tex_category; - } - } - dest_it.Next(); - } - return nullptr; -} - -void DX8FVFCategoryContainer::Change_Polygon_Renderer_Texture( - DX8PolygonRendererList& polygon_renderer_list, - TextureClass* texture, - TextureClass* new_texture, - unsigned pass, - unsigned stage) -{ - WWASSERT(passPeek_Texture(stage)==texture) { - foundtexture=true; - DX8PolygonRendererListIterator poly_it(&polygon_renderer_list); - while (!poly_it.Is_Done()) { - // If source texture category contains polygon renderer, move to destination category - DX8PolygonRendererClass* polygon_renderer=poly_it.Peek_Obj(); - DX8TextureCategoryClass *prc=polygon_renderer->Get_Texture_Category(); - - if (prc==src_tex_category) { - DX8TextureCategoryClass* dest_tex_category=Find_Matching_Texture_Category(new_texture,pass,stage,src_tex_category); - - if (!dest_tex_category) { - TextureClass * tmp_textures[MeshMatDescClass::MAX_TEX_STAGES]; - for (int s=0;sPeek_Texture(s); - } - tmp_textures[stage]=new_texture; - - DX8TextureCategoryClass * new_tex_category=W3DNEW DX8TextureCategoryClass( - this, - tmp_textures, - src_tex_category->Get_Shader(), - const_cast(src_tex_category->Peek_Material()), - pass); - - /* - ** Add the texture category object into the list, immediately after any existing - ** texture category object which uses the same texture. This will result in - ** the list always having matching texture categories next to each other. - */ - bool found_similar_category = false; - TextureCategoryListIterator tex_it(&texture_category_list[pass]); - while (!tex_it.Is_Done()) { - // Categorize according to first stage's texture for now - if (tex_it.Peek_Obj()->Peek_Texture(0) == tmp_textures[0]) { - texture_category_list[pass].Add_After(new_tex_category,tex_it.Peek_Obj()); - found_similar_category = true; - break; - } - tex_it.Next(); - } - - if (!found_similar_category) { - texture_category_list[pass].Add_Tail(new_tex_category); - } - dest_tex_category=new_tex_category; - } - PolyRemover *rem=W3DNEW PolyRemover; - rem->src=src_tex_category; - rem->dest=dest_tex_category; - rem->pr=polygon_renderer; - prl.Add(rem); - } - poly_it.Next(); - } - } - else - // quit loop if we've got a texture change - if (foundtexture) break; - src_it.Next(); - } - - PolyRemoverListIterator prli(&prl); - - while (!prli.Is_Done()) - { - PolyRemover *rem=prli.Peek_Obj(); - rem->src->Remove_Polygon_Renderer(rem->pr); - rem->dest->Add_Polygon_Renderer(rem->pr); - prli.Remove_Current_Object(); - delete rem; - } -} - -void DX8FVFCategoryContainer::Change_Polygon_Renderer_Material( - DX8PolygonRendererList& polygon_renderer_list, - VertexMaterialClass* vmat, - VertexMaterialClass* new_vmat, - unsigned pass) -{ - WWASSERT(passPeek_Material()==vmat) { - DX8PolygonRendererListIterator poly_it(&polygon_renderer_list); - while (!poly_it.Is_Done()) { - // If source texture category contains polygon renderer, move to destination category - DX8PolygonRendererClass* polygon_renderer=poly_it.Peek_Obj(); - DX8TextureCategoryClass *prc=polygon_renderer->Get_Texture_Category(); - if (prc==src_tex_category) { - foundtexture=true; - DX8TextureCategoryClass* dest_tex_category=Find_Matching_Texture_Category(new_vmat,pass,src_tex_category); - - if (!dest_tex_category) { - TextureClass * tmp_textures[MeshMatDescClass::MAX_TEX_STAGES]; - for (int s=0;sPeek_Texture(s); - } - - DX8TextureCategoryClass * new_tex_category=W3DNEW DX8TextureCategoryClass( - this, - tmp_textures, - src_tex_category->Get_Shader(), - const_cast(new_vmat), - pass); - - /* - ** Add the texture category object into the list, immediately after any existing - ** texture category object which uses the same texture. This will result in - ** the list always having matching texture categories next to each other. - */ - bool found_similar_category = false; - TextureCategoryListIterator tex_it(&texture_category_list[pass]); - while (!tex_it.Is_Done()) { - // Categorize according to first stage's texture for now - if (tex_it.Peek_Obj()->Peek_Texture(0) == tmp_textures[0]) { - texture_category_list[pass].Add_After(new_tex_category,tex_it.Peek_Obj()); - found_similar_category = true; - break; - } - tex_it.Next(); - } - - if (!found_similar_category) { - texture_category_list[pass].Add_Tail(new_tex_category); - } - dest_tex_category=new_tex_category; - } - PolyRemover *rem=W3DNEW PolyRemover; - rem->src=src_tex_category; - rem->dest=dest_tex_category; - rem->pr=polygon_renderer; - prl.Add(rem); - } - poly_it.Next(); - } - } - else - if (foundtexture) break; - src_it.Next(); - } - - PolyRemoverListIterator prli(&prl); - - while (!prli.Is_Done()) - { - PolyRemover *rem=prli.Peek_Obj(); - rem->src->Remove_Polygon_Renderer(rem->pr); - rem->dest->Add_Polygon_Renderer(rem->pr); - prli.Remove_Current_Object(); - delete rem; - } -} - -// ---------------------------------------------------------------------------- - -unsigned DX8FVFCategoryContainer::Define_FVF(MeshModelClass* mmc,bool enable_lighting) -{ - if ((!!mmc->Get_Flag(MeshGeometryClass::SORT)) && WW3D::Is_Sorting_Enabled()) { - return dynamic_fvf_type; - } - - unsigned fvf=D3DFVF_XYZ; - - int tex_coord_count=mmc->Get_UV_Array_Count(); - - if (mmc->Get_Color_Array(0,false)) { - fvf|=D3DFVF_DIFFUSE; - } - if (mmc->Get_Color_Array(1,false)) { - fvf|=D3DFVF_SPECULAR; - } - - switch (tex_coord_count) { - default: - case 0: - break; - case 1: fvf|=D3DFVF_TEX1; break; - case 2: fvf|=D3DFVF_TEX2; break; - case 3: fvf|=D3DFVF_TEX3; break; - case 4: fvf|=D3DFVF_TEX4; break; - case 5: fvf|=D3DFVF_TEX5; break; - case 6: fvf|=D3DFVF_TEX6; break; - case 7: fvf|=D3DFVF_TEX7; break; - case 8: fvf|=D3DFVF_TEX8; break; - } - - if (!mmc->Needs_Vertex_Normals()) { //enable_lighting || mmc->Get_Flag(MeshModelClass::PRELIT_MASK)) { - return fvf; - } - - fvf|=D3DFVF_NORMAL; // Realtime-lit - return fvf; -} - -// ---------------------------------------------------------------------------- - -DX8RigidFVFCategoryContainer::DX8RigidFVFCategoryContainer(unsigned FVF,bool sorting_) - : - DX8FVFCategoryContainer(FVF,sorting_), - vertex_buffer(nullptr), - used_vertices(0), - delayed_matpass_head(nullptr), - delayed_matpass_tail(nullptr) -{ -} - -// ---------------------------------------------------------------------------- - -DX8RigidFVFCategoryContainer::~DX8RigidFVFCategoryContainer() -{ - REF_PTR_RELEASE(vertex_buffer); -} - -// ---------------------------------------------------------------------------- - -void DX8RigidFVFCategoryContainer::Log(bool only_visible) -{ -#ifdef ENABLE_CATEGORY_LOG - StringClass work(255,true); - work.Format("DX8RigidFVFCategoryContainer --------------"); - WWDEBUG_SAY((work)); - if (vertex_buffer) { - StringClass fvfname(255,true); - vertex_buffer->FVF_Info().Get_FVF_Name(fvfname); - work.Format("VB size (used/total): %d/%d FVF: %s",used_vertices,vertex_buffer->Get_Vertex_Count(),fvfname); - WWDEBUG_SAY((work)); - } - else { - WWDEBUG_SAY(("EMPTY VB")); - } - if (index_buffer) { - work.Format("IB size (used/total): %d/%d",used_indices,index_buffer->Get_Index_Count()); - WWDEBUG_SAY((work)); - } - else { - WWDEBUG_SAY(("EMPTY IB")); - } - - for (unsigned p=0;pLog(only_visible); - it.Next(); - } - } -#endif -} - -// ---------------------------------------------------------------------------- -// -// Generic render function for rigid meshes -// -// ---------------------------------------------------------------------------- - -void DX8RigidFVFCategoryContainer::Render() -{ - if (!Anything_To_Render()) return; - AnythingToRender=false; - - DX8Wrapper::Set_Vertex_Buffer(vertex_buffer); - DX8Wrapper::Set_Index_Buffer(index_buffer,0); - - SNAPSHOT_SAY(("DX8RigidFVFCategoryContainer::Render()")); - for (unsigned p=0;pRender(); - } - } - - Render_Procedural_Material_Passes(); -} - -// ---------------------------------------------------------------------------- - -bool DX8RigidFVFCategoryContainer::Check_If_Mesh_Fits(MeshModelClass* mmc) -{ - if (!vertex_buffer) return true; // No VB created - mesh will fit as a new vb will be created when inserting - unsigned required_vertices=mmc->Get_Vertex_Count(); - unsigned available_vertices=vertex_buffer->Get_Vertex_Count()-used_vertices; - unsigned required_polygons=mmc->Get_Polygon_Count(); - if (mmc->Get_Gap_Filler()) { - required_polygons+=mmc->Get_Gap_Filler()->Get_Polygon_Count(); - } - unsigned required_indices=required_polygons*3*mmc->Get_Pass_Count(); - unsigned available_indices=index_buffer->Get_Index_Count()-used_indices; - if ( - required_vertices<=available_vertices && - (required_indices)<=available_indices) { - return true; - } - return false; -} - -// ---------------------------------------------------------------------------- - -class Vertex_Split_Table -{ - MeshModelClass* mmc; - bool npatch_enable; - unsigned polygon_count; - TriIndex* polygon_array; - - bool allocated_polygon_array; - -public: - Vertex_Split_Table(MeshModelClass* mmc_) - : - mmc(mmc_), - npatch_enable(false), - allocated_polygon_array(false) - { - if (DX8Wrapper::Get_Current_Caps()->Support_NPatches() && mmc->Needs_Vertex_Normals()) { - if (mmc->Get_Flag(MeshGeometryClass::ALLOW_NPATCHES)) { - npatch_enable=true; - } - } - - const GapFillerClass* gap_filler=mmc->Get_Gap_Filler(); - polygon_count=mmc->Get_Polygon_Count(); - if (gap_filler) polygon_count+=gap_filler->Get_Polygon_Count(); -// if (mmc->Get_Gap_Filler_Polygon_Count()) { - allocated_polygon_array=true; - polygon_array=W3DNEWARRAY TriIndex[polygon_count]; - memcpy( - polygon_array, - mmc->Get_Polygon_Array(), - mmc->Get_Polygon_Count()*sizeof(TriIndex)); - if (gap_filler) { - memcpy( - polygon_array+mmc->Get_Polygon_Count(), - gap_filler->Get_Polygon_Array(), - gap_filler->Get_Polygon_Count()*sizeof(TriIndex)); - } -// } -// else { -// polygon_array=const_cast(mmc->Get_Polygon_Array()); -// } - - } - - ~Vertex_Split_Table() - { - if (allocated_polygon_array) { - delete[] polygon_array; - } - } - - const Vector3* Get_Vertex_Array() const - { - return mmc->Get_Vertex_Array(); - } - - const Vector3* Get_Vertex_Normal_Array() const - { - return mmc->Get_Vertex_Normal_Array(); - } - - const unsigned* Get_Color_Array(unsigned index) const - { - return mmc->Get_Color_Array(index,false); - } - - const Vector2* Get_UV_Array(unsigned uv_array_index) const - { - return mmc->Get_UV_Array_By_Index(uv_array_index); - } - - unsigned Get_Vertex_Count() const - { - return mmc->Get_Vertex_Count(); - } - - unsigned Get_Polygon_Count() const - { - return polygon_count; - } - - unsigned Get_Pass_Count() const - { - return mmc->Get_Pass_Count(); - } - - TextureClass* Peek_Texture(unsigned idx,unsigned pass,unsigned stage) - { - if (mmc->Has_Texture_Array(pass,stage)) { - if (idx>=unsigned(mmc->Get_Polygon_Count())) { - WWASSERT(mmc->Get_Gap_Filler()); - return mmc->Get_Gap_Filler()->Get_Texture_Array(pass,stage)[idx-mmc->Get_Polygon_Count()]; - } - return mmc->Peek_Texture(idx,pass,stage); - } - return mmc->Peek_Single_Texture(pass,stage); - } - - VertexMaterialClass* Peek_Material(unsigned idx,unsigned pass) - { - if (mmc->Has_Material_Array(pass)) { - if (idx>=unsigned(mmc->Get_Polygon_Count())) { - WWASSERT(mmc->Get_Gap_Filler()); - return mmc->Get_Gap_Filler()->Get_Material_Array(pass)[idx-mmc->Get_Polygon_Count()]; - } - return mmc->Peek_Material(mmc->Get_Polygon_Array()[idx][0],pass); - } - return mmc->Peek_Single_Material(pass); - } - - ShaderClass Peek_Shader(unsigned idx,unsigned pass) - { - if (mmc->Has_Shader_Array(pass)) { - ShaderClass shader; - - if (idx>=unsigned(mmc->Get_Polygon_Count())) { - WWASSERT(mmc->Get_Gap_Filler()); - shader=mmc->Get_Gap_Filler()->Get_Shader_Array(pass)[idx-mmc->Get_Polygon_Count()]; - } - else shader=mmc->Get_Shader(idx,pass); - - if (npatch_enable) { - shader.Set_NPatch_Enable(ShaderClass::NPATCH_ENABLE); - } - - return shader; - } - if (!npatch_enable) return mmc->Get_Single_Shader(pass); - ShaderClass shader=mmc->Get_Single_Shader(pass); - shader.Set_NPatch_Enable(ShaderClass::NPATCH_ENABLE); - return shader; - - } - - MeshModelClass* Get_Mesh_Model_Class() - { - return mmc; - } - - unsigned short* Get_Polygon_Array(unsigned pass) - { - return (unsigned short*)polygon_array; - } -}; - -// ---------------------------------------------------------------------------- - -void DX8RigidFVFCategoryContainer::Add_Mesh(MeshModelClass* mmc_) -{ - WWASSERT(Check_If_Mesh_Fits(mmc_)); - - Vertex_Split_Table split_table(mmc_); - int needed_vertices=split_table.Get_Vertex_Count(); - - /* - ** This FVFCategoryContainer doesn't have a vertex buffer yet so allocate one big - ** enough to contain this mesh. - */ - if (!vertex_buffer) { - int vb_size=4000; - if (vb_sizeFVF_Info().Get_FVF()==FVF); // Only one sorting FVF type! - } - else { - vertex_buffer=NEW_REF(DX8VertexBufferClass,( - FVF, - vb_size, - (DX8Wrapper::Get_Current_Caps()->Support_NPatches() && WW3D::Get_NPatches_Level()>1) ? DX8VertexBufferClass::USAGE_NPATCHES : DX8VertexBufferClass::USAGE_DEFAULT)); - } - } - - /* - ** Append this mesh's vertices to the vertex buffer. - */ - - VertexBufferClass::AppendLockClass l(vertex_buffer,used_vertices,split_table.Get_Vertex_Count()); - const FVFInfoClass fi=vertex_buffer->FVF_Info(); - unsigned char *vb=(unsigned char*) l.Get_Vertex_Array(); - unsigned int i; - const Vector3 *locs=split_table.Get_Vertex_Array(); - const Vector3 *norms=split_table.Get_Vertex_Normal_Array(); - const unsigned *diffuse=split_table.Get_Color_Array(0); - const unsigned *specular=split_table.Get_Color_Array(1); - for (i=0; iPeek_Texture(stage) == texs[stage]); - } - if (all_textures_same && Equal_Material(tex_category->Peek_Material(),mat) && tex_category->Get_Shader()==shader) { - used_indices+=tex_category->Add_Mesh(split_table,vertex_offset,used_indices,index_buffer,pass); - fit_in_existing_category = true; - break; - } - it.Next(); - } - - if (!fit_in_existing_category) { - - DX8TextureCategoryClass * new_tex_category=W3DNEW DX8TextureCategoryClass(this,texs,shader,mat,pass); - used_indices+=new_tex_category->Add_Mesh(split_table,vertex_offset,used_indices,index_buffer,pass); - - /* - ** Add the texture category object into the list, immediately after any existing - ** texture category object which uses the same texture. This will result in - ** the list always having matching texture categories next to each other. - */ - bool found_similar_category = false; - TextureCategoryListIterator it(&texture_category_list[pass]); - while (!it.Is_Done()) { - // Categorize according to first stage's texture for now - if (it.Peek_Obj()->Peek_Texture(0) == texs[0]) { - texture_category_list[pass].Add_After(new_tex_category,it.Peek_Obj()); - found_similar_category = true; - break; - } - it.Next(); - } - - if (!found_similar_category) { - texture_category_list[pass].Add_Tail(new_tex_category); - } - } -} - -const unsigned MAX_ADDED_TYPE_COUNT=64; -struct Textures_Material_And_Shader_Booking_Struct -{ - TextureClass* added_textures[MeshMatDescClass::MAX_TEX_STAGES][MAX_ADDED_TYPE_COUNT]; - VertexMaterialClass* added_materials[MAX_ADDED_TYPE_COUNT]; - ShaderClass added_shaders[MAX_ADDED_TYPE_COUNT]; - unsigned added_type_count; - - Textures_Material_And_Shader_Booking_Struct() : added_type_count(0) {} - - bool Add_Textures_Material_And_Shader(TextureClass** texs, VertexMaterialClass* mat, ShaderClass shd) - { - for (unsigned a=0;aSupport_NPatches() && WW3D::Get_NPatches_Level()>1) ? DX8IndexBufferClass::USAGE_NPATCHES : DX8IndexBufferClass::USAGE_DEFAULT)); - } - } - - for (unsigned pass=0;passGet_Index_Count()); - WWDEBUG_SAY((work)); - } - else { - WWDEBUG_SAY(("EMPTY IB")); - } - - for (unsigned pass=0;passLog(only_visible); - it.Next(); - } - } -#endif -} - -// ---------------------------------------------------------------------------- - -void DX8SkinFVFCategoryContainer::Render() -{ - SNAPSHOT_SAY(("DX8SkinFVFCategoryContainer::Render()")); - if (!Anything_To_Render()) { - SNAPSHOT_SAY(("Nothing to render")); - return; - } - AnythingToRender=false; - - DX8Wrapper::Set_Vertex_Buffer(nullptr); // Free up the reference to the current vertex buffer - // (in case it is the dynamic, which may have to be resized) - - //'Generals' customization to allow more than 65535 vertices - unsigned int maxVertexCount=VisibleVertexCount; - if (maxVertexCount > 65535) - { //clamp vertex count to maximum size that can be indexed by 16-bit index - maxVertexCount = 65535; - } - - DynamicVBAccessClass vb( - sorting ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8, - dynamic_fvf_type, - maxVertexCount); - SNAPSHOT_SAY(("DynamicVBAccess - %s - %d vertices",sorting ? "sorting" : "non-sorting",VisibleVertexCount)); - - unsigned int renderedVertexCount=0; - - MeshClass * mesh = VisibleSkinHead; - MeshClass * remainingMesh = VisibleSkinHead; - while (renderedVertexCount < VisibleVertexCount) - { mesh = remainingMesh; - { DynamicVBAccessClass::WriteLockClass l(&vb); - VertexFormatXYZNDUV2 * dest_verts = l.Get_Formatted_Vertex_Array(); - unsigned vertex_offset=0; - remainingMesh = nullptr; - - while (mesh != nullptr) { - - MeshModelClass * mmc = mesh->Peek_Model(); - int mesh_vertex_count=mmc->Get_Vertex_Count(); - //'Generals' mod to deal with cases where not all meshes fit in VB. - if (vertex_offset+mesh_vertex_count > maxVertexCount || remainingMesh) - { //flag mesh so we know it didn't fit in the vertex buffer - mesh->Set_Base_Vertex_Offset(VERTEX_BUFFER_OVERFLOW); - if (remainingMesh == nullptr) - remainingMesh = mesh; //start of meshes that didn't fit in buffer - mesh = mesh->Peek_Next_Visible_Skin(); //skip rendering this mesh - continue; - } - - - // If this assert hits, a skinned mesh has probably been added to the scene more than once. - // Example: A skinned mesh was added to the scene then it was attached to a bone without being removed from the scene. - WWASSERT((vertex_offset+mesh_vertex_count)<=VisibleVertexCount); - DX8_RECORD_SKIN_RENDER(mesh->Get_Num_Polys(),mesh_vertex_count); - - if (_TempVertexBuffer.Length() < mesh_vertex_count) _TempVertexBuffer.Resize(mesh_vertex_count); - if (_TempNormalBuffer.Length() < mesh_vertex_count) _TempNormalBuffer.Resize(mesh_vertex_count); - - Vector3* loc=&(_TempVertexBuffer[0]); - Vector3* norm=&(_TempNormalBuffer[0]); - const Vector2* uv0=mmc->Get_UV_Array_By_Index(0); - const Vector2* uv1=mmc->Get_UV_Array_By_Index(1); - const unsigned* diffuse=mmc->Get_Color_Array(0,false); - - VertexFormatXYZNDUV2* verts=dest_verts+vertex_offset; - - mesh->Get_Deformed_Vertices(loc,norm); - - for (int v=0;vSet_Base_Vertex_Offset(vertex_offset); - vertex_offset+=mesh_vertex_count; - renderedVertexCount += mesh_vertex_count; - - mesh = mesh->Peek_Next_Visible_Skin(); - } - } - - SNAPSHOT_SAY(("Set vb: %x ib: %x",&vb.FVF_Info(),index_buffer)); - - DX8Wrapper::Set_Vertex_Buffer(vb); - DX8Wrapper::Set_Index_Buffer(index_buffer,0); - - //Flush the meshes which fit in the vertex buffer, applying all texture variations - for (unsigned pass=0;passRender(); - it.Next(); - } - } - - Render_Procedural_Material_Passes(); - } - - //remove all the rendered data from queues - for (unsigned pass=0;passGet_Polygon_Count(); - if (mmc->Get_Gap_Filler()) { - required_polygons+=mmc->Get_Gap_Filler()->Get_Polygon_Count(); - } - - if ((required_polygons*3*mmc->Get_Pass_Count())<=index_buffer->Get_Index_Count()-used_indices) { - return true; - } - return false; -} - -void DX8SkinFVFCategoryContainer::clearVisibleSkinList() -{ - while (VisibleSkinHead != nullptr) - { - MeshClass* next = VisibleSkinHead->Peek_Next_Visible_Skin(); - VisibleSkinHead->Set_Next_Visible_Skin(nullptr); - VisibleSkinHead = next; - } - VisibleSkinHead = nullptr; - VisibleSkinTail = nullptr; - VisibleVertexCount = 0; -} - -void DX8SkinFVFCategoryContainer::Add_Visible_Skin(MeshClass * mesh) -{ - if (mesh->Peek_Next_Visible_Skin() != nullptr || mesh == VisibleSkinTail) - { - DEBUG_CRASH(("Mesh %s is already a visible skin, and we tried to add it again... please notify Mark W or Steven J immediately!",mesh->Get_Name())); - return; - } - if (VisibleSkinHead == nullptr) - VisibleSkinTail = mesh; - mesh->Set_Next_Visible_Skin(VisibleSkinHead); - VisibleSkinHead = mesh; - VisibleVertexCount += mesh->Peek_Model()->Get_Vertex_Count(); -} - - -// ---------------------------------------------------------------------------- - -void DX8SkinFVFCategoryContainer::Reset() -{ - clearVisibleSkinList(); - - for (unsigned pass=0;passType()==BUFFER_TYPE_SORTING || index_buffer->Type()==BUFFER_TYPE_DYNAMIC_SORTING) { - stripify=false; - } -#endif // ; - const TriIndex* src_indices=(const TriIndex*)split_table.Get_Polygon_Array(pass);//mmc->Get_Polygon_Array(); - - if (stripify) { - int* triangles=W3DNEWARRAY int[index_count]; - int triangle_index_count=0; - for (int i=0;iSet_Vertex_Index_Range(vmin,vmax-vmin+1); - } - } - delete[] strip; - } - - // Need to check stripify again as it may be changed to false by the previous statement - if (!stripify ) { - DX8PolygonRendererClass* p_renderer=W3DNEW DX8PolygonRendererClass( - index_count, - split_table.Get_Mesh_Model_Class(), - this, - vertex_offset, - index_offset, - false, - pass); - PolygonRendererList.Add_Tail(p_renderer); - - IndexBufferClass::AppendLockClass l(index_buffer,index_offset,index_count); - unsigned short* dst_indices=l.Get_Index_Array(); - - unsigned short vmin=0xffff; - unsigned short vmax=0; - - /* - ** Iterate over the polys for this pass, adding each one that matches this texture+material+shader - */ - for (int i=0;iGet_Vertex_Count()); - - /* - ** Remember the min and max vertex indices that these polygons used (for optimization) - */ - p_renderer->Set_Vertex_Index_Range(vmin,vmax-vmin+1); - WWASSERT(index_count<=unsigned(split_table.Get_Polygon_Count()*3)); - } - } - - return index_count; -} - -// ---------------------------------------------------------------------------- - -void DX8TextureCategoryClass::Render() -{ - #ifdef WWDEBUG - if (!WW3D::Expose_Prelit()) { - #endif - - for (unsigned i=0;iGet_Texture_Name().str() : "null")); - DX8Wrapper::Set_Texture(i,Peek_Texture(i)); - } - - #ifdef WWDEBUG - } - #endif - - SNAPSHOT_SAY(("Set_Material(%s)",Peek_Material() ? Peek_Material()->Get_Name() : "null")); - VertexMaterialClass *vmaterial=(VertexMaterialClass *)Peek_Material(); //ugly cast from const but we'll restore it after changes so okay. -MW - DX8Wrapper::Set_Material(vmaterial); - - SNAPSHOT_SAY(("Set_Shader(%x)",Get_Shader().Get_Bits())); - ShaderClass theShader = Get_Shader(); - - //Setup an alpha blend version of this shader just in case it's needed. -MW - ShaderClass theAlphaShader = theShader; - theAlphaShader.Set_Src_Blend_Func(ShaderClass::SRCBLEND_SRC_ALPHA); - theAlphaShader.Set_Dst_Blend_Func(ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA); - //if we want to allow other translucent polygons behind this mesh, we need to disable z-write but - //this will cause sorting errors on this mesh. - //theAlphaShader.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); - - DX8Wrapper::Set_Shader(theShader); - - if (m_gForceMultiply && theShader.Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ZERO) { - theShader.Set_Dst_Blend_Func(ShaderClass::DSTBLEND_SRC_COLOR); - theShader.Set_Src_Blend_Func(ShaderClass::SRCBLEND_ZERO); - DX8Wrapper::Set_Shader(theShader); - //VertexMaterialClass *material = VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE); - //DX8Wrapper::Set_Material(material); - //REF_PTR_RELEASE(material); - DX8Wrapper::Apply_Render_State_Changes(); - DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR); - } - - - bool renderTasksRemaining=false; - - PolyRenderTaskClass * prt = render_task_head; - PolyRenderTaskClass * last_prt = nullptr; - - while (prt) { - - /* - ** Dig out the parameters for this render task - */ - DX8PolygonRendererClass * renderer = prt->Peek_Polygon_Renderer(); - MeshClass * mesh = prt->Peek_Mesh(); - - if (mesh->Get_Base_Vertex_Offset() == VERTEX_BUFFER_OVERFLOW) //check if this mesh is valid - { //skip this mesh so it gets rendered later after vertices are filled in. - last_prt = prt; - prt = prt->Get_Next_Visible(); - renderTasksRemaining = true; - continue; - } - - SNAPSHOT_SAY(("mesh = %s",mesh->Get_Name())); - - #ifdef WWDEBUG - // Debug rendering: if it exists, expose prelighting on this mesh by disabling all base textures. - if (WW3D::Expose_Prelit()) { - switch (mesh->Peek_Model()->Get_Flag (MeshGeometryClass::PRELIT_MASK)) { - - unsigned i; - - case MeshGeometryClass::PRELIT_VERTEX: - - // Disable texturing on all stages and passes. - for (i = 0; i < MeshMatDescClass::MAX_TEX_STAGES; i++) - { - DX8Wrapper::Set_Texture (i, nullptr); - } - break; - - case MeshGeometryClass::PRELIT_LIGHTMAP_MULTI_PASS: - - // Disable texturing on all but the last pass. - if (pass == mesh->Peek_Model()->Get_Pass_Count() - 1) { - for (i = 0; i < MeshMatDescClass::MAX_TEX_STAGES; i++) - { - DX8Wrapper::Set_Texture (i, Peek_Texture (i)); - } - } else { - for (i = 0; i < MAX_TEXTURE_STAGES; i++) { - DX8Wrapper::Set_Texture (i, nullptr); - } - } - break; - - case MeshGeometryClass::PRELIT_LIGHTMAP_MULTI_TEXTURE: - - // Disable texturing on all but the zeroth stage of each pass. - DX8Wrapper::Set_Texture (0, Peek_Texture (0)); - for (i = 1; i < MeshMatDescClass::MAX_TEX_STAGES; i++) - { - DX8Wrapper::Set_Texture (i, nullptr); - } - break; - - default: - for (i = 0; i < MeshMatDescClass::MAX_TEX_STAGES; i++) - { - DX8Wrapper::Set_Texture (i, Peek_Texture (i)); - } - break; - } - } - #endif - - /* - ** If the user is not installing LightEnvironmentClasses, we leave the lighting render - ** states untouched. This way they can set a couple global lights that affect the entire scene. - */ - LightEnvironmentClass * lenv = mesh->Get_Lighting_Environment(); - if (lenv != nullptr) { - SNAPSHOT_SAY(("LightEnvironment, lights: %d",lenv->Get_Light_Count())); - DX8Wrapper::Set_Light_Environment(lenv); - } - else { - SNAPSHOT_SAY(("No light environment")); - } - - /* - ** Support for ALIGNED and ORIENTED camera modes - */ - const Matrix3D* world_transform = &mesh->Get_Transform(); - bool identity=mesh->Is_Transform_Identity(); - Matrix3D tmp_world; - - if (mesh->Peek_Model()->Get_Flag(MeshModelClass::ALIGNED)) { - SNAPSHOT_SAY(("Camera mode ALIGNED")); - - Vector3 mesh_position; - Vector3 camera_z_vector; - - TheDX8MeshRenderer.Peek_Camera()->Get_Transform().Get_Z_Vector(&camera_z_vector); - mesh->Get_Transform().Get_Translation(&mesh_position); - - tmp_world.Obj_Look_At(mesh_position,mesh_position + camera_z_vector,0.0f); - world_transform = &tmp_world; - - } else if (mesh->Peek_Model()->Get_Flag(MeshModelClass::ORIENTED)) { - SNAPSHOT_SAY(("Camera mode ORIENTED")); - - Vector3 mesh_position; - Vector3 camera_position; - - TheDX8MeshRenderer.Peek_Camera()->Get_Transform().Get_Translation(&camera_position); - mesh->Get_Transform().Get_Translation(&mesh_position); - - tmp_world.Obj_Look_At(mesh_position,camera_position,0.0f); - world_transform = &tmp_world; - - } else if (mesh->Peek_Model()->Get_Flag(MeshModelClass::SKIN)) { - SNAPSHOT_SAY(("Set world identity (for skin)")); - - tmp_world.Make_Identity(); - world_transform = &tmp_world; - identity=true; - } - - - if (identity) { - SNAPSHOT_SAY(("Set_World_Identity")); - DX8Wrapper::Set_World_Identity(); - } - else { - SNAPSHOT_SAY(("Set_World_Transform")); - DX8Wrapper::Set_Transform(D3DTS_WORLD,*world_transform); - } - - -//-------------------------------------------------------------------- - if (mesh->Get_ObjectScale() != 1.0f) - DX8Wrapper::Set_DX8_Render_State(D3DRS_NORMALIZENORMALS, TRUE); -//-------------------------------------------------------------------- - /* - ** Render mesh using either sorting or immediate pipeline - */ - //(gth) this if statement's contents are not tabbed to avoid perforce merge problems... - if (!DX8RendererDebugger::Is_Enabled() || !mesh->Is_Disabled_By_Debugger()) { - - if ((!!mesh->Peek_Model()->Get_Flag(MeshGeometryClass::SORT)) && WW3D::Is_Sorting_Enabled()) { - renderer->Render_Sorted(mesh->Get_Base_Vertex_Offset(),mesh->Get_Bounding_Sphere()); - } else { - //non-transparent mesh that will be rendered immediately. Okay to adjust the shader/material - //if necessary - if (mesh->Get_Alpha_Override() != 1.0 || (mesh->Get_User_Data() && *(int *)mesh->Get_User_Data() == RenderObjClass::USER_DATA_MATERIAL_OVERRIDE)) - { //mesh has material override of some kind - //adjust the opacity of this model - float oldOpacity=vmaterial->Get_Opacity(); - Vector3 oldDiffuse; - Vector2 oldUVOffset; - unsigned int oldUVOffsetSyncTime; - vmaterial->Get_Diffuse(&oldDiffuse); - LinearOffsetTextureMapperClass *oldMapper=(LinearOffsetTextureMapperClass *)vmaterial->Peek_Mapper(); - if ( mesh->Get_User_Data() && *(int *)mesh->Get_User_Data() == RenderObjClass::USER_DATA_MATERIAL_OVERRIDE && oldMapper && oldMapper->Mapper_ID() == TextureMapperClass::MAPPER_ID_LINEAR_OFFSET) - { RenderObjClass::Material_Override *matOverride=(RenderObjClass::Material_Override *)mesh->Get_User_Data(); - oldUVOffsetSyncTime = oldMapper->Get_LastUsedSyncTime(); - oldMapper->Set_LastUsedSyncTime(WW3D::Get_Sync_Time()); //make sure zero time passes for the mapper. - oldMapper->Get_Current_UV_Offset(oldUVOffset); - oldMapper->Set_Current_UV_Offset(matOverride->customUVOffset); - } - else - oldMapper=nullptr; - - if (mesh->Get_Alpha_Override() != 1.0) - { - if (mesh->Is_Additive()) - { //additvie blended mesh can't switch to alpha or we will get a black outline. - //so adjust diffuse color instead. - vmaterial->Set_Diffuse(mesh->Get_Alpha_Override(),mesh->Get_Alpha_Override(),mesh->Get_Alpha_Override()); - theAlphaShader = theShader; //keep using additive blending. - } - vmaterial->Set_Opacity(mesh->Get_Alpha_Override()); - DX8Wrapper::Set_Shader(theAlphaShader); - DX8Wrapper::Apply_Render_State_Changes(); - DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,(int)((float)0x60*mesh->Get_Alpha_Override())); - - renderer->Render(mesh->Get_Base_Vertex_Offset()); - - DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x60); - vmaterial->Set_Opacity(oldOpacity); //restore previous value - vmaterial->Set_Diffuse(oldDiffuse.X,oldDiffuse.Y,oldDiffuse.Z); - DX8Wrapper::Set_Shader(theShader); //restore previous value - } - else - renderer->Render(mesh->Get_Base_Vertex_Offset()); - - if (oldMapper) //did we override the uv offset? - { oldMapper->Set_LastUsedSyncTime(oldUVOffsetSyncTime); - oldMapper->Set_Current_UV_Offset(oldUVOffset); - } - DX8Wrapper::Set_Material(nullptr); //force a reset of vertex material since we secretly changed opacity - DX8Wrapper::Set_Material(vmaterial); //restore previous material. - } - else - renderer->Render(mesh->Get_Base_Vertex_Offset()); - } -//-------------------------------------------------------------------- - if (mesh->Get_ObjectScale() != 1.0f) - DX8Wrapper::Set_DX8_Render_State(D3DRS_NORMALIZENORMALS, FALSE); -//-------------------------------------------------------------------- - - - - - } - - /* - ** Move to the next render task. Note that the delete should be fast because prt's are pooled - */ - PolyRenderTaskClass * next_prt = prt->Get_Next_Visible(); - - // remove from list, then delete - if (last_prt == nullptr) { - render_task_head = next_prt; - } else { - last_prt->Set_Next_Visible(next_prt); - } - - delete prt; - prt = next_prt; - } - - if (!renderTasksRemaining) - { - WWASSERT(!render_task_head); - Clear_Render_List(); - } -} - -void DX8TextureCategoryClass::Clear_Render_List() -{ - while (render_task_head != nullptr) - { - PolyRenderTaskClass* next = render_task_head->Get_Next_Visible(); - delete render_task_head; - render_task_head = next; - } -} - - -DX8MeshRendererClass::DX8MeshRendererClass() - : - camera(nullptr), - enable_lighting(true), - texture_category_container_list_skin(nullptr), - visible_decal_meshes(nullptr) -{ -} - -DX8MeshRendererClass::~DX8MeshRendererClass() -{ - Shutdown(); -} - -void DX8MeshRendererClass::Init() -{ - // DMS - Only allocate one if we have not already (leak fix) - if(!texture_category_container_list_skin) - texture_category_container_list_skin = W3DNEW FVFCategoryList; -} - -void DX8MeshRendererClass::Shutdown() -{ - camera = nullptr; - visible_decal_meshes = nullptr; - Invalidate(true); - Clear_Pending_Delete_Lists(); - _TempVertexBuffer.Clear(); //free memory - _TempNormalBuffer.Clear(); -} - -// ---------------------------------------------------------------------------- - -void DX8MeshRendererClass::Clear_Pending_Delete_Lists() -{ - while (DX8TextureCategoryClass* category=texture_category_delete_list.Remove_Head()) { - delete category; - } - while (DX8FVFCategoryContainer* container=fvf_category_container_delete_list.Remove_Head()) { - delete container; - } -} - -// ---------------------------------------------------------------------------- - -static void Add_Rigid_Mesh_To_Container(FVFCategoryList* container_list,unsigned fvf,MeshModelClass* mmc) -{ - WWASSERT(container_list); - DX8FVFCategoryContainer * container = nullptr; - bool sorting=((!!mmc->Get_Flag(MeshModelClass::SORT)) && WW3D::Is_Sorting_Enabled() && (mmc->Get_Sort_Level() == SORT_LEVEL_NONE)); - - FVFCategoryListIterator it(container_list); - while (!it.Is_Done()) { - container = it.Peek_Obj(); - if (sorting==container->Is_Sorting() && container->Check_If_Mesh_Fits(mmc)) { - container->Add_Mesh(mmc); - return; - } - it.Next(); - } - - container=W3DNEW DX8RigidFVFCategoryContainer(fvf,sorting); - container_list->Add_Tail(container); - container->Add_Mesh(mmc); -} - -// ---------------------------------------------------------------------------- - -void DX8MeshRendererClass::Unregister_Mesh_Type(MeshModelClass* mmc) -{ - while (DX8PolygonRendererClass* n=mmc->PolygonRendererList.Remove_Head()) { - delete n; - } - _RegisteredMeshList.Remove(mmc); - - // Also remove the gap filler! - if (mmc->GapFiller) { - GapFillerClass* gf=mmc->GapFiller; - mmc->GapFiller=nullptr; - delete gf; - } - -} - - -void DX8MeshRendererClass::Register_Mesh_Type(MeshModelClass* mmc) -{ - WWMEMLOG(MEM_GEOMETRY); -#ifdef ENABLE_CATEGORY_LOG - WWDEBUG_SAY(("Registering mesh: %s (%d polys, %d verts + %d gap polygons)",mmc->Get_Name(),mmc->Get_Polygon_Count(),mmc->Get_Vertex_Count(),mmc->Get_Gap_Filler_Polygon_Count())); -#endif - bool skin=(mmc->Get_Flag(MeshModelClass::SKIN) && mmc->VertexBoneLink); - bool sorting=((!!mmc->Get_Flag(MeshModelClass::SORT)) && WW3D::Is_Sorting_Enabled() && (mmc->Get_Sort_Level() == SORT_LEVEL_NONE)); - - if (skin) { - - /* - ** This mesh is a skin. Add it to a DX8SkinFVFCategoryContainer. - */ - WWASSERT(texture_category_container_list_skin); - - FVFCategoryListIterator it(texture_category_container_list_skin); - while (!it.Is_Done()) { - DX8FVFCategoryContainer * container = it.Peek_Obj(); - if (sorting==container->Is_Sorting() && container->Check_If_Mesh_Fits(mmc)) { - container->Add_Mesh(mmc); - return; - } - it.Next(); - } - - DX8FVFCategoryContainer * new_container=W3DNEW DX8SkinFVFCategoryContainer(sorting); - texture_category_container_list_skin->Add_Tail(new_container); - new_container->Add_Mesh(mmc); - - } else { - - /* - ** We should never try to add the same mesh model to the system twice. - */ - WWASSERT_PRINT(_RegisteredMeshList.Contains(mmc) == false,("Mesh name: %s",mmc->Get_Name())); - - /* - ** If the previous step didn't add the mesh, then we have to actually process this mesh - */ - if (!_RegisteredMeshList.Contains(mmc)) { - - unsigned fvf=DX8FVFCategoryContainer::Define_FVF(mmc,enable_lighting); - - /* - ** Search for an existing FVF Category Container that matches this mesh - */ - int i=0; - for (;iPeek_Head(); - if (container && container->Get_FVF()!=fvf) continue; - - Add_Rigid_Mesh_To_Container(list,fvf,mmc); - break; - } - - if (i==texture_category_container_lists_rigid.Count()) { - - /* - ** We couldn't find an existing FVF category container so we have to add one. Future - ** meshes that use this FVF will also be able to use this container. - */ - FVFCategoryList * new_fvf_category = W3DNEW FVFCategoryList(); - texture_category_container_lists_rigid.Add(new_fvf_category); - Add_Rigid_Mesh_To_Container(new_fvf_category,fvf,mmc); - } - - /* - ** Done processing the mesh, add its polygon renderers to the global registered mesh list - */ - if (mmc->PolygonRendererList.Is_Empty() == false) { - _RegisteredMeshList.Add_Tail(mmc); - } - else { - WWDEBUG_SAY(("Error: Register_Mesh_Type failed! file: %s line: %d",__FILE__,__LINE__)); - } - } - } -} - -static unsigned statistics_requested=0; - -void DX8MeshRendererClass::Request_Log_Statistics() -{ - statistics_requested=WW3D::Get_Frame_Count(); -} - - -// --------------------------------------------------------------------------- -// -// Render all meshes that are added to visible lists -// -// --------------------------------------------------------------------------- - -static void Render_FVF_Category_Container_List(FVFCategoryList& list) -{ - FVFCategoryListIterator it(&list); - while (!it.Is_Done()) { - it.Peek_Obj()->Render(); - it.Next(); - } -} - -static void Render_FVF_Category_Container_List_Delayed_Passes(FVFCategoryList& list) -{ - FVFCategoryListIterator it(&list); - while (!it.Is_Done()) { - it.Peek_Obj()->Render_Delayed_Procedural_Material_Passes(); - it.Next(); - } -} - -void DX8MeshRendererClass::Flush() -{ - int i; - - WWPROFILE("DX8MeshRenderer::Flush"); - if (!camera) return; - Log_Statistics_String(true); - - /* - ** Render the FVF categories. Note that it is critical that skins be - ** rendered *after* the rigid meshes. This is caused by the fact that an object may - ** have its base passes disabled and a translucent procedural material pass rendered - ** instead. In this case, technically we have to delay rendering of the material pass but - ** for skins we just render these passes as we go because we can assume that the - ** bulk of the meshes have already been drawn (there would be extra overhead involved - ** in solving this for skins) - */ - for (i=0;iSet_Next_Visible(visible_decal_meshes); - visible_decal_meshes = decalmesh; -} - -void DX8MeshRendererClass::Render_Decal_Meshes() -{ - DecalMeshClass * decal_mesh = visible_decal_meshes; - if (!decal_mesh) return; - - DX8Wrapper::Set_DX8_Render_State(D3DRS_ZBIAS,8); - - while (decal_mesh != nullptr) { - decal_mesh->Render(); - decal_mesh = decal_mesh->Peek_Next_Visible(); - } - visible_decal_meshes = nullptr; - - DX8Wrapper::Set_DX8_Render_State(D3DRS_ZBIAS,0); -} - -// ---------------------------------------------------------------------------- - -static void Log_Container_List(FVFCategoryList& container_list,bool only_visible) -{ - FVFCategoryListIterator it(&container_list); - while (!it.Is_Done()) { - it.Peek_Obj()->Log(only_visible); - it.Next(); - } -} - -void DX8MeshRendererClass::Log_Statistics_String(bool only_visible) -{ - if (statistics_requested!=WW3D::Get_Frame_Count()) return; - - for (int i=0;i. -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8renderer.h $* - * * - * Original Author:: Jani Penttinen * - * * - * Author : Kenny Mitchell * - * * - * $Modtime:: 06/27/02 1:27p $* - * * - * $Revision:: 29 $* - * * - * 06/27/02 KM Changes to max texture stage caps * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -#pragma once - -#include "always.h" -#include "wwstring.h" -#include "simplevec.h" -#include "Vector.h" -#include "dx8list.h" -#include "shader.h" -#include "dx8wrapper.h" -#include "meshmatdesc.h" - -class IndexBufferClass; -class VertexBufferClass; -class DX8RenderTypeArrayClass; -class MeshClass; -class MeshModelClass; -class DX8PolygonRendererClass; -class Vertex_Split_Table; -class DX8FVFCategoryContainer; -class DecalMeshClass; -class MaterialPassClass; -class MatPassTaskClass; -class PolyRenderTaskClass; -class TextureClass; -class VertexMaterialClass; -class CameraClass; - -#define RECORD_RENDER(I,P) render_stats[I].count++; render_stats[I].polys+=P; - -/** -** DX8TextureCategoryClass -** This class is used for each Material-Texture-Shader combination that is encountered during rendering. -** Each polygon_renderer that uses the same 'TextureCategory' will be linked to the 'TextureCategory' object. -** Then, all polygons will be rendered in 'TextureCategory' batches to reduce the number of stage changes -** (and most importantly, texture changes) that we cause in DX8. -*/ -class DX8TextureCategoryClass : public MultiListObjectClass -{ - int pass; - TextureClass * textures[MeshMatDescClass::MAX_TEX_STAGES]; - ShaderClass shader; - VertexMaterialClass * material; - DX8PolygonRendererList PolygonRendererList; - DX8FVFCategoryContainer* container; - - PolyRenderTaskClass * render_task_head; // polygon renderers queued for rendering - static bool m_gForceMultiply; // Forces opaque materials to use the multiply blend - pseudo transparent effect. jba. - -public: - - DX8TextureCategoryClass(DX8FVFCategoryContainer* container,TextureClass** textures, ShaderClass shd, VertexMaterialClass* mat,int pass); - virtual ~DX8TextureCategoryClass() override; - - void Add_Render_Task(DX8PolygonRendererClass * p_renderer,MeshClass * p_mesh); - - void Render(); - bool Anything_To_Render() { return (render_task_head != nullptr); } - void Clear_Render_List(); - - TextureClass * Peek_Texture(int stage) { return textures[stage]; } - const VertexMaterialClass * Peek_Material() { return material; } - ShaderClass Get_Shader() { return shader; } - - DX8PolygonRendererList& Get_Polygon_Renderer_List() { return PolygonRendererList; } - - unsigned Add_Mesh( - Vertex_Split_Table& split_buffer, - unsigned vertex_offset, - unsigned index_offset, - IndexBufferClass* index_buffer, - unsigned pass); - void Log(bool only_visible); - - void Remove_Polygon_Renderer(DX8PolygonRendererClass* p_renderer); - void Add_Polygon_Renderer(DX8PolygonRendererClass* p_renderer,DX8PolygonRendererClass* add_after_this=nullptr); - - - DX8FVFCategoryContainer * Get_Container() { return container; } - - // Force multiply blend on all objects inserted from now on. (Doesn't affect the objects that are already in the lists) - static void SetForceMultiply(bool multiply) { m_gForceMultiply=multiply; } - -}; - -// ---------------------------------------------------------------------------- - -/** -** DX8FVFCategoryContainer -*/ - -class DX8FVFCategoryContainer : public MultiListObjectClass -{ -public: - enum { - MAX_PASSES=4 - }; -protected: - - TextureCategoryList texture_category_list[MAX_PASSES]; - TextureCategoryList visible_texture_category_list[MAX_PASSES]; - - MatPassTaskClass * visible_matpass_head; - MatPassTaskClass * visible_matpass_tail; - - IndexBufferClass * index_buffer; - int used_indices; - unsigned FVF; - unsigned passes; - unsigned uv_coordinate_channels; - bool sorting; - bool AnythingToRender; - bool AnyDelayedPassesToRender; - - void Generate_Texture_Categories(Vertex_Split_Table& split_table,unsigned vertex_offset); - void Insert_To_Texture_Category( - Vertex_Split_Table& split_table, - TextureClass** textures, - VertexMaterialClass* mat, - ShaderClass shader, - int pass, - unsigned vertex_offset); - - bool Anything_To_Render() { return AnythingToRender; } - bool Any_Delayed_Passes_To_Render() { return AnyDelayedPassesToRender; } - - void Render_Procedural_Material_Passes(); - - DX8TextureCategoryClass* Find_Matching_Texture_Category( - TextureClass* texture, - unsigned pass, - unsigned stage, - DX8TextureCategoryClass* ref_category); - - DX8TextureCategoryClass* Find_Matching_Texture_Category( - VertexMaterialClass* vmat, - unsigned pass, - DX8TextureCategoryClass* ref_category); - -public: - - DX8FVFCategoryContainer(unsigned FVF,bool sorting); - virtual ~DX8FVFCategoryContainer() override; - - static unsigned Define_FVF(MeshModelClass* mmc,bool enable_lighting); - bool Is_Sorting() const { return sorting; } - - void Change_Polygon_Renderer_Texture( - DX8PolygonRendererList& polygon_renderer_list, - TextureClass* texture, - TextureClass* new_texture, - unsigned pass, - unsigned stage); - - void Change_Polygon_Renderer_Material( - DX8PolygonRendererList& polygon_renderer_list, - VertexMaterialClass* vmat, - VertexMaterialClass* new_vmat, - unsigned pass); - - void Remove_Texture_Category(DX8TextureCategoryClass* tex_category); - - virtual void Render()=0; - virtual void Add_Mesh(MeshModelClass* mmc)=0; - virtual void Log(bool only_visible)=0; - virtual bool Check_If_Mesh_Fits(MeshModelClass* mmc)=0; - - unsigned Get_FVF() const { return FVF; } - - void Add_Visible_Texture_Category(DX8TextureCategoryClass * tex_category,int pass) - { - WWASSERT(pass texture_category_container_lists_rigid; - FVFCategoryList * texture_category_container_list_skin; - - DecalMeshClass * visible_decal_meshes; - - -}; - -extern DX8MeshRendererClass TheDX8MeshRenderer; diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp deleted file mode 100644 index 756ffd2db20..00000000000 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp +++ /dev/null @@ -1,904 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program 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. -** -** This program 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 this program. If not, see . -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : ww3d * - * * - * $Archive:: /Commando/Code/ww3d2/dx8vertexbuffer.cpp $* - * * - * Original Author:: Jani Penttinen * - * * - * $Author:: Kenny Mitchell * - * * - * $Modtime:: 06/26/02 5:06p $* - * * - * $Revision:: 39 $* - * * - * 06/26/02 KM VB Vertex format size update for shaders * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -//#define VERTEX_BUFFER_LOG - -#include "dx8vertexbuffer.h" -#include "dx8wrapper.h" -#include "dx8fvf.h" -#include "dx8caps.h" -#include "thread.h" -#include "wwmemlog.h" -#include - -#define DEFAULT_VB_SIZE 5000 - -static bool _DynamicSortingVertexArrayInUse=false; -//static VertexFormatXYZNDUV2* _DynamicSortingVertexArray=nullptr; -static SortingVertexBufferClass* _DynamicSortingVertexArray=nullptr; -static unsigned short _DynamicSortingVertexArraySize=0; -static unsigned short _DynamicSortingVertexArrayOffset=0; - -static bool _DynamicDX8VertexBufferInUse=false; -static DX8VertexBufferClass* _DynamicDX8VertexBuffer=nullptr; -static unsigned short _DynamicDX8VertexBufferSize=DEFAULT_VB_SIZE; -static unsigned short _DynamicDX8VertexBufferOffset=0; - -static const FVFInfoClass _DynamicFVFInfo(dynamic_fvf_type); - -static int _DX8VertexBufferCount=0; - -static int _VertexBufferCount; -static int _VertexBufferTotalVertices; -static int _VertexBufferTotalSize; - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -VertexBufferClass::VertexBufferClass(unsigned type_, unsigned FVF, unsigned short vertex_count_) - : - VertexCount(vertex_count_), - type(type_), - engine_refs(0) -{ - WWMEMLOG(MEM_RENDERER); - WWASSERT(VertexCount); - WWASSERT(type==BUFFER_TYPE_DX8 || type==BUFFER_TYPE_SORTING); - WWASSERT(FVF != 0); - fvf_info=W3DNEW FVFInfoClass(FVF); - - _VertexBufferCount++; - _VertexBufferTotalVertices+=VertexCount; - _VertexBufferTotalSize+=VertexCount*fvf_info->Get_FVF_Size(); -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("New VB, %d vertices, size %d bytes",VertexCount,VertexCount*fvf_info->Get_FVF_Size())); - WWDEBUG_SAY(("Total VB count: %d, total %d vertices, total size %d bytes", - _VertexBufferCount, - _VertexBufferTotalVertices, - _VertexBufferTotalSize)); -#endif -} - -// ---------------------------------------------------------------------------- - -VertexBufferClass::~VertexBufferClass() -{ - _VertexBufferCount--; - _VertexBufferTotalVertices-=VertexCount; - _VertexBufferTotalSize-=VertexCount*fvf_info->Get_FVF_Size(); - -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("Delete VB, %d vertices, size %d bytes",VertexCount,VertexCount*fvf_info->Get_FVF_Size())); - WWDEBUG_SAY(("Total VB count: %d, total %d vertices, total size %d bytes", - _VertexBufferCount, - _VertexBufferTotalVertices, - _VertexBufferTotalSize)); -#endif - delete fvf_info; -} - -unsigned VertexBufferClass::Get_Total_Buffer_Count() -{ - return _VertexBufferCount; -} - -unsigned VertexBufferClass::Get_Total_Allocated_Vertices() -{ - return _VertexBufferTotalVertices; -} - -unsigned VertexBufferClass::Get_Total_Allocated_Memory() -{ - return _VertexBufferTotalSize; -} - - -// ---------------------------------------------------------------------------- - -void VertexBufferClass::Add_Engine_Ref() const -{ - engine_refs++; -} - -// ---------------------------------------------------------------------------- - -void VertexBufferClass::Release_Engine_Ref() const -{ - engine_refs--; - WWASSERT(engine_refs>=0); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -VertexBufferClass::WriteLockClass::WriteLockClass(VertexBufferClass* VertexBuffer, int flags) - : - VertexBufferLockClass(VertexBuffer) -{ - DX8_THREAD_ASSERT(); - WWASSERT(VertexBuffer); - WWASSERT(!VertexBuffer->Engine_Refs()); - VertexBuffer->Add_Ref(); - switch (VertexBuffer->Type()) { - case BUFFER_TYPE_DX8: -#ifdef VERTEX_BUFFER_LOG - { - StringClass fvf_name; - VertexBuffer->FVF_Info().Get_FVF_Name(fvf_name); - WWDEBUG_SAY(("VertexBuffer->Lock(start_index: 0, index_range: 0(%d), fvf_size: %d, fvf: %s)", - VertexBuffer->Get_Vertex_Count(), - VertexBuffer->FVF_Info().Get_FVF_Size(), - fvf_name)); - } -#endif - DX8_Assert(); - DX8_ErrorCode(static_cast(VertexBuffer)->Get_DX8_Vertex_Buffer()->Lock( - 0, - 0, - (unsigned char**)&Vertices, - flags)); //flags - break; - case BUFFER_TYPE_SORTING: - Vertices=static_cast(VertexBuffer)->VertexBuffer; - break; - default: - WWASSERT(0); - break; - } -} - -// ---------------------------------------------------------------------------- - -VertexBufferClass::WriteLockClass::~WriteLockClass() -{ - DX8_THREAD_ASSERT(); - switch (VertexBuffer->Type()) { - case BUFFER_TYPE_DX8: -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("VertexBuffer->Unlock()")); -#endif - DX8_Assert(); - DX8_ErrorCode(static_cast(VertexBuffer)->Get_DX8_Vertex_Buffer()->Unlock()); - break; - case BUFFER_TYPE_SORTING: - break; - default: - WWASSERT(0); - break; - } - VertexBuffer->Release_Ref(); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -VertexBufferClass::AppendLockClass::AppendLockClass(VertexBufferClass* VertexBuffer,unsigned start_index, unsigned index_range) - : - VertexBufferLockClass(VertexBuffer) -{ - DX8_THREAD_ASSERT(); - WWASSERT(VertexBuffer); - WWASSERT(!VertexBuffer->Engine_Refs()); - WWASSERT(start_index+index_range<=VertexBuffer->Get_Vertex_Count()); - VertexBuffer->Add_Ref(); - switch (VertexBuffer->Type()) { - case BUFFER_TYPE_DX8: -#ifdef VERTEX_BUFFER_LOG - { - StringClass fvf_name; - VertexBuffer->FVF_Info().Get_FVF_Name(fvf_name); - WWDEBUG_SAY(("VertexBuffer->Lock(start_index: %d, index_range: %d, fvf_size: %d, fvf: %s)", - start_index, - index_range, - VertexBuffer->FVF_Info().Get_FVF_Size(), - fvf_name)); - } -#endif - DX8_Assert(); - DX8_ErrorCode(static_cast(VertexBuffer)->Get_DX8_Vertex_Buffer()->Lock( - start_index*VertexBuffer->FVF_Info().Get_FVF_Size(), - index_range*VertexBuffer->FVF_Info().Get_FVF_Size(), - (unsigned char**)&Vertices, - 0)); // Default (no) flags - break; - case BUFFER_TYPE_SORTING: - Vertices=static_cast(VertexBuffer)->VertexBuffer+start_index; - break; - default: - WWASSERT(0); - break; - } -} - -// ---------------------------------------------------------------------------- - -VertexBufferClass::AppendLockClass::~AppendLockClass() -{ - DX8_THREAD_ASSERT(); - switch (VertexBuffer->Type()) { - case BUFFER_TYPE_DX8: - DX8_Assert(); -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("VertexBuffer->Unlock()")); -#endif - DX8_ErrorCode(static_cast(VertexBuffer)->Get_DX8_Vertex_Buffer()->Unlock()); - break; - case BUFFER_TYPE_SORTING: - break; - default: - WWASSERT(0); - break; - } - VertexBuffer->Release_Ref(); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -SortingVertexBufferClass::SortingVertexBufferClass(unsigned short VertexCount) - : - VertexBufferClass(BUFFER_TYPE_SORTING, dynamic_fvf_type, VertexCount) -{ - WWMEMLOG(MEM_RENDERER); - VertexBuffer=W3DNEWARRAY VertexFormatXYZNDUV2[VertexCount]; -} - -// ---------------------------------------------------------------------------- - -SortingVertexBufferClass::~SortingVertexBufferClass() -{ - delete[] VertexBuffer; -} - - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -// bool dynamic=false,bool softwarevp=false); - -DX8VertexBufferClass::DX8VertexBufferClass(unsigned FVF, unsigned short vertex_count_, UsageType usage) - : - VertexBufferClass(BUFFER_TYPE_DX8, FVF, vertex_count_), - VertexBuffer(nullptr) -{ - Create_Vertex_Buffer(usage); -} - -// ---------------------------------------------------------------------------- - -DX8VertexBufferClass::DX8VertexBufferClass( - const Vector3* vertices, - const Vector3* normals, - const Vector2* tex_coords, - unsigned short VertexCount, - UsageType usage) - : - VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_NORMAL, VertexCount), - VertexBuffer(nullptr) -{ - WWASSERT(vertices); - WWASSERT(normals); - WWASSERT(tex_coords); - - Create_Vertex_Buffer(usage); - Copy(vertices,normals,tex_coords,0,VertexCount); -} - -// ---------------------------------------------------------------------------- - -DX8VertexBufferClass::DX8VertexBufferClass( - const Vector3* vertices, - const Vector3* normals, - const Vector4* diffuse, - const Vector2* tex_coords, - unsigned short VertexCount, - UsageType usage) - : - VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_NORMAL|D3DFVF_DIFFUSE, VertexCount), - VertexBuffer(nullptr) -{ - WWASSERT(vertices); - WWASSERT(normals); - WWASSERT(tex_coords); - WWASSERT(diffuse); - - Create_Vertex_Buffer(usage); - Copy(vertices,normals,tex_coords,diffuse,0,VertexCount); -} - -// ---------------------------------------------------------------------------- - -DX8VertexBufferClass::DX8VertexBufferClass( - const Vector3* vertices, - const Vector4* diffuse, - const Vector2* tex_coords, - unsigned short VertexCount, - UsageType usage) - : - VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_DIFFUSE, VertexCount), - VertexBuffer(nullptr) -{ - WWASSERT(vertices); - WWASSERT(tex_coords); - WWASSERT(diffuse); - - Create_Vertex_Buffer(usage); - Copy(vertices,tex_coords,diffuse,0,VertexCount); -} - -// ---------------------------------------------------------------------------- - -DX8VertexBufferClass::DX8VertexBufferClass( - const Vector3* vertices, - const Vector2* tex_coords, - unsigned short VertexCount, - UsageType usage) - : - VertexBufferClass(BUFFER_TYPE_DX8, D3DFVF_XYZ|D3DFVF_TEX1, VertexCount), - VertexBuffer(nullptr) -{ - WWASSERT(vertices); - WWASSERT(tex_coords); - - Create_Vertex_Buffer(usage); - Copy(vertices,tex_coords,0,VertexCount); -} - -// ---------------------------------------------------------------------------- - -DX8VertexBufferClass::~DX8VertexBufferClass() -{ -#ifdef VERTEX_BUFFER_LOG - WWDEBUG_SAY(("VertexBuffer->Release()")); - _DX8VertexBufferCount--; - WWDEBUG_SAY(("Current vertex buffer count: %d",_DX8VertexBufferCount)); -#endif - VertexBuffer->Release(); -} - -// ---------------------------------------------------------------------------- -// -// -// -// ---------------------------------------------------------------------------- - -void DX8VertexBufferClass::Create_Vertex_Buffer(UsageType usage) -{ - DX8_THREAD_ASSERT(); - WWASSERT(!VertexBuffer); - -#ifdef VERTEX_BUFFER_LOG - StringClass fvf_name; - FVF_Info().Get_FVF_Name(fvf_name); - WWDEBUG_SAY(("CreateVertexBuffer(fvfsize=%d, vertex_count=%d, D3DUSAGE_WRITEONLY|%s|%s, fvf: %s, %s)", - FVF_Info().Get_FVF_Size(), - VertexCount, - (usage&USAGE_DYNAMIC) ? "D3DUSAGE_DYNAMIC" : "-", - (usage&USAGE_SOFTWAREPROCESSING) ? "D3DUSAGE_SOFTWAREPROCESSING" : "-", - fvf_name, - (usage&USAGE_DYNAMIC) ? "D3DPOOL_DEFAULT" : "D3DPOOL_MANAGED")); - _DX8VertexBufferCount++; - WWDEBUG_SAY(("Current vertex buffer count: %d",_DX8VertexBufferCount)); -#endif - - unsigned usage_flags= - D3DUSAGE_WRITEONLY| - ((usage&USAGE_DYNAMIC) ? D3DUSAGE_DYNAMIC : 0)| - ((usage&USAGE_NPATCHES) ? D3DUSAGE_NPATCHES : 0)| - ((usage&USAGE_SOFTWAREPROCESSING) ? D3DUSAGE_SOFTWAREPROCESSING : 0); - // New Code - if (!DX8Wrapper::Get_Current_Caps()->Support_TnL()) { - usage_flags|=D3DUSAGE_SOFTWAREPROCESSING; - } - - HRESULT ret=DX8Wrapper::_Get_D3D_Device8()->CreateVertexBuffer( - FVF_Info().Get_FVF_Size()*VertexCount, - usage_flags, - FVF_Info().Get_FVF(), - (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, - &VertexBuffer); - if (SUCCEEDED(ret)) { - return; - } - - WWDEBUG_SAY(("Vertex buffer creation failed, trying to release assets...")); - - // Vertex buffer creation failed, so try releasing least used textures and flushing the mesh cache. - - // Free all textures that haven't been used in the last 5 seconds - TextureClass::Invalidate_Old_Unused_Textures(5000); - - // Invalidate the mesh cache - WW3D::_Invalidate_Mesh_Cache(); - - //@todo: Find some way to invalidate the textures too - ret = DX8Wrapper::_Get_D3D_Device8()->ResourceManagerDiscardBytes(0); - - // Try again... - ret=DX8Wrapper::_Get_D3D_Device8()->CreateVertexBuffer( - FVF_Info().Get_FVF_Size()*VertexCount, - usage_flags, - FVF_Info().Get_FVF(), - (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, - &VertexBuffer); - - if (SUCCEEDED(ret)) { - WWDEBUG_SAY(("...Vertex buffer creation successful")); - } - - // If it still fails it is fatal - DX8_ErrorCode(ret); - - /* Old Code - DX8CALL(CreateVertexBuffer( - FVF_Info().Get_FVF_Size()*VertexCount, - usage_flags, - FVF_Info().Get_FVF(), - (usage&USAGE_DYNAMIC) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, - &VertexBuffer)); - */ -} - -// ---------------------------------------------------------------------------- - -void DX8VertexBufferClass::Copy(const Vector3* loc, const Vector3* norm, const Vector2* uv, unsigned first_vertex,unsigned count) -{ - WWASSERT(loc); - WWASSERT(norm); - WWASSERT(uv); - WWASSERT(count<=VertexCount); - WWASSERT(FVF_Info().Get_FVF()==DX8_FVF_XYZNUV1); - - if (first_vertex) { - VertexBufferClass::AppendLockClass l(this,first_vertex,count); - VertexFormatXYZNUV1* verts=(VertexFormatXYZNUV1*)l.Get_Vertex_Array(); - for (unsigned v=0;vNum_Refs() == 1)); - REF_PTR_RELEASE(_DynamicDX8VertexBuffer); - _DynamicDX8VertexBufferInUse=false; - _DynamicDX8VertexBufferSize=DEFAULT_VB_SIZE; - _DynamicDX8VertexBufferOffset=0; - - WWASSERT ((_DynamicSortingVertexArray == nullptr) || (_DynamicSortingVertexArray->Num_Refs() == 1)); - REF_PTR_RELEASE(_DynamicSortingVertexArray); - WWASSERT(!_DynamicSortingVertexArrayInUse); - _DynamicSortingVertexArrayInUse=false; - _DynamicSortingVertexArraySize=0; - _DynamicSortingVertexArrayOffset=0; -} - -void DynamicVBAccessClass::Allocate_DX8_Dynamic_Buffer() -{ - WWMEMLOG(MEM_RENDERER); - WWASSERT(!_DynamicDX8VertexBufferInUse); - _DynamicDX8VertexBufferInUse=true; - - // If requesting more vertices than dynamic vertex buffer can fit, delete the vb - // and adjust the size to the new count. - if (VertexCount>_DynamicDX8VertexBufferSize) { - REF_PTR_RELEASE(_DynamicDX8VertexBuffer); - _DynamicDX8VertexBufferSize=VertexCount; - if (_DynamicDX8VertexBufferSizeSupport_NPatches()) { - usage|=DX8VertexBufferClass::USAGE_NPATCHES; - } - - _DynamicDX8VertexBuffer=NEW_REF(DX8VertexBufferClass,( - dynamic_fvf_type, - _DynamicDX8VertexBufferSize, - (DX8VertexBufferClass::UsageType)usage)); - _DynamicDX8VertexBufferOffset=0; - } - - // Any room at the end of the buffer? - if (((unsigned)VertexCount+_DynamicDX8VertexBufferOffset)>_DynamicDX8VertexBufferSize) { - _DynamicDX8VertexBufferOffset=0; - } - - REF_PTR_SET(VertexBuffer,_DynamicDX8VertexBuffer); - VertexBufferOffset=_DynamicDX8VertexBufferOffset; -} - -void DynamicVBAccessClass::Allocate_Sorting_Dynamic_Buffer() -{ - WWMEMLOG(MEM_RENDERER); - WWASSERT(!_DynamicSortingVertexArrayInUse); - _DynamicSortingVertexArrayInUse=true; - - unsigned new_vertex_count=_DynamicSortingVertexArrayOffset+VertexCount; - WWASSERT(new_vertex_count<65536); - if (new_vertex_count>_DynamicSortingVertexArraySize) { - REF_PTR_RELEASE(_DynamicSortingVertexArray); - _DynamicSortingVertexArraySize=new_vertex_count; - if (_DynamicSortingVertexArraySizeGet_Type()) { - case BUFFER_TYPE_DYNAMIC_DX8: -#ifdef VERTEX_BUFFER_LOG - { - WWASSERT(!dx8_lock); - dx8_lock++; - StringClass fvf_name; - DynamicVBAccess->VertexBuffer->FVF_Info().Get_FVF_Name(fvf_name); - WWDEBUG_SAY(("DynamicVertexBuffer->Lock(start_index: %d, index_range: %d, fvf_size: %d, fvf: %s)", - DynamicVBAccess->VertexBufferOffset, - DynamicVBAccess->Get_Vertex_Count(), - DynamicVBAccess->VertexBuffer->FVF_Info().Get_FVF_Size(), - fvf_name)); - } -#endif - WWASSERT(_DynamicDX8VertexBuffer); -// WWASSERT(!_DynamicDX8VertexBuffer->Engine_Refs()); - - DX8_Assert(); - // Lock with discard contents if the buffer offset is zero - DX8_ErrorCode(static_cast(DynamicVBAccess->VertexBuffer)->Get_DX8_Vertex_Buffer()->Lock( - DynamicVBAccess->VertexBufferOffset*_DynamicDX8VertexBuffer->FVF_Info().Get_FVF_Size(), - DynamicVBAccess->Get_Vertex_Count()*DynamicVBAccess->VertexBuffer->FVF_Info().Get_FVF_Size(), - (unsigned char**)&Vertices, - D3DLOCK_NOSYSLOCK | (!DynamicVBAccess->VertexBufferOffset ? D3DLOCK_DISCARD : D3DLOCK_NOOVERWRITE))); - break; - case BUFFER_TYPE_DYNAMIC_SORTING: - Vertices=static_cast(DynamicVBAccess->VertexBuffer)->VertexBuffer; - Vertices+=DynamicVBAccess->VertexBufferOffset; -// vertices=_DynamicSortingVertexArray+_DynamicSortingVertexArrayOffset; - break; - default: - WWASSERT(0); - break; - } -} - -// ---------------------------------------------------------------------------- - -DynamicVBAccessClass::WriteLockClass::~WriteLockClass() -{ - DX8_THREAD_ASSERT(); - switch (DynamicVBAccess->Get_Type()) { - case BUFFER_TYPE_DYNAMIC_DX8: -#ifdef VERTEX_BUFFER_LOG - dx8_lock--; - WWASSERT(!dx8_lock); - WWDEBUG_SAY(("DynamicVertexBuffer->Unlock()")); -#endif - DX8_Assert(); - DX8_ErrorCode(static_cast(DynamicVBAccess->VertexBuffer)->Get_DX8_Vertex_Buffer()->Unlock()); - break; - case BUFFER_TYPE_DYNAMIC_SORTING: - break; - default: - WWASSERT(0); - break; - } -} - -// ---------------------------------------------------------------------------- - -void DynamicVBAccessClass::_Reset(bool frame_changed) -{ - _DynamicSortingVertexArrayOffset=0; - if (frame_changed) _DynamicDX8VertexBufferOffset=0; -} - -unsigned short DynamicVBAccessClass::Get_Default_Vertex_Count() -{ - return _DynamicDX8VertexBufferSize; -} - diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h deleted file mode 100644 index 1c0a632e44d..00000000000 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h +++ /dev/null @@ -1,253 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program 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. -** -** This program 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 this program. If not, see . -*/ - -/*********************************************************************************************** - *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** - *********************************************************************************************** - * * - * Project Name : WW3D * - * * - * $Archive:: /Commando/Code/ww3d2/dx8vertexbuffer.h $* - * * - * Original Author:: Jani Penttinen * - * * - * $Author:: Kenny Mitchell * - * * - * $Modtime:: 06/26/02 5:06p $* - * * - * $Revision:: 26 $* - * * - * 06/26/02 KM VB Vertex format size update for shaders * - *---------------------------------------------------------------------------------------------* - * Functions: * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -#pragma once - -#include "always.h" -#include "wwdebug.h" -#include "dx8fvf.h" - -const unsigned dynamic_fvf_type=D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2|D3DFVF_DIFFUSE; - -class DX8Wrapper; -class SortingRendererClass; -class Vector2; -class Vector3; -class Vector4; -class StringClass; -class DX8VertexBufferClass; -class FVFInfoClass; -struct IDirect3DVertexBuffer8; -class VertexBufferClass; -struct VertexFormatXYZNDUV2; - -class VertexBufferLockClass -{ -protected: - VertexBufferClass* VertexBuffer; - void* Vertices; - - // This class can't be used directly, so constructor as to be protected - VertexBufferLockClass(VertexBufferClass* vertex_buffer_) : VertexBuffer(vertex_buffer_) {} -public: - void* Get_Vertex_Array() { return Vertices; } -}; - -/** -** DX8VertexBufferClass -** This class wraps a DX8 vertex buffer. Use the lock objects to modify or append to the vertex buffer. -*/ -class VertexBufferClass : public RefCountClass -{ -protected: - VertexBufferClass(unsigned type, unsigned FVF, unsigned short VertexCount); - virtual ~VertexBufferClass() override; -public: - - const FVFInfoClass& FVF_Info() const { return *fvf_info; } - unsigned short Get_Vertex_Count() const { return VertexCount; } - unsigned Type() const { return type; } - - void Add_Engine_Ref() const; - void Release_Engine_Ref() const; - unsigned Engine_Refs() const { return engine_refs; } - - class WriteLockClass : public VertexBufferLockClass - { - public: - WriteLockClass(VertexBufferClass* vertex_buffer, int flags=0); - ~WriteLockClass(); - }; - - class AppendLockClass : public VertexBufferLockClass - { - public: - AppendLockClass(VertexBufferClass* vertex_buffer,unsigned start_index, unsigned index_range); - ~AppendLockClass(); - }; - - static unsigned Get_Total_Buffer_Count(); - static unsigned Get_Total_Allocated_Vertices(); - static unsigned Get_Total_Allocated_Memory(); - -protected: - unsigned type; - unsigned short VertexCount; - mutable int engine_refs; - FVFInfoClass* fvf_info; -}; - - - -/** -** Dynamic vertex buffer access is a wrapper to a single cycled dynamic vertex -** buffer. -** DynamicVBAccess gains an access to the dynamic vertex buffer and only -** only of these are allowed at any one time. -** -** The dynamic fvf buffers are always of the same type. -** -** NOTE: Dynamic vertex buffers accessors should only be used locally! -** -*/ - -class DynamicVBAccessClass -{ - friend DX8Wrapper; - friend SortingRendererClass; - - const FVFInfoClass& FVFInfo; - unsigned Type; - unsigned short VertexCount; - unsigned short VertexBufferOffset; - VertexBufferClass* VertexBuffer; -// static VertexFormatXYZNDUV2* _Get_Sorting_Vertex_Array(); - - void Allocate_Sorting_Dynamic_Buffer(); - void Allocate_DX8_Dynamic_Buffer(); -public: - // Type parameter can be either BUFFER_TYPE_DYNAMIC_DX8 or BUFFER_TYPE_DYNAMIC_SORTING. - - // Note: Even though the constructor takes fvf as a parameter, currently the - // only acceptable parameter is "dynamic_fvf_type". Any other type will - // result to an assert. - DynamicVBAccessClass(unsigned type,unsigned fvf,unsigned short vertex_count); - ~DynamicVBAccessClass(); - - // Access fvf - const FVFInfoClass& FVF_Info() const { return FVFInfo; } - unsigned Get_Type() const { return Type; } - unsigned short Get_Vertex_Count() const { return VertexCount; } - - // Call at the end of the execution, or at whatever time you wish to release - // the recycled dynamic vertex buffer. - static void _Deinit(); - static void _Reset(bool frame_changed); - static unsigned short Get_Default_Vertex_Count(); ///VertexBuffer->FVF_Info().Get_FVF() == (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2|D3DFVF_DIFFUSE)); - return Vertices; -} - -// ---------------------------------------------------------------------------- - -/** -** DX8VertexBufferClass -** This class wraps a DX8 vertex buffer. Use the lock objects to modify or append to the vertex buffer. -*/ -class DX8VertexBufferClass : public VertexBufferClass -{ - W3DMPO_CODE(DX8VertexBufferClass) -protected: - virtual ~DX8VertexBufferClass() override; -public: - enum UsageType { - USAGE_DEFAULT=0, - USAGE_DYNAMIC=1, - USAGE_SOFTWAREPROCESSING=2, - USAGE_NPATCHES=4 - }; - - DX8VertexBufferClass(unsigned FVF, unsigned short VertexCount, UsageType usage=USAGE_DEFAULT); - DX8VertexBufferClass(const Vector3* vertices, const Vector3* normals, const Vector2* tex_coords, unsigned short VertexCount,UsageType usage=USAGE_DEFAULT); - DX8VertexBufferClass(const Vector3* vertices, const Vector3* normals, const Vector4* diffuse, const Vector2* tex_coords, unsigned short VertexCount,UsageType usage=USAGE_DEFAULT); - DX8VertexBufferClass(const Vector3* vertices, const Vector4* diffuse, const Vector2* tex_coords, unsigned short VertexCount,UsageType usage=USAGE_DEFAULT); - DX8VertexBufferClass(const Vector3* vertices, const Vector2* tex_coords, unsigned short VertexCount,UsageType usage=USAGE_DEFAULT); - - IDirect3DVertexBuffer8* Get_DX8_Vertex_Buffer() { return VertexBuffer; } - - void Copy(const Vector3* loc, unsigned first_vertex, unsigned count); - void Copy(const Vector3* loc, const Vector2* uv, unsigned first_vertex, unsigned count); - void Copy(const Vector3* loc, const Vector3* norm, unsigned first_vertex, unsigned count); - void Copy(const Vector3* loc, const Vector3* norm, const Vector2* uv, unsigned first_vertex, unsigned count); - void Copy(const Vector3* loc, const Vector3* norm, const Vector2* uv, const Vector4* diffuse, unsigned first_vertex, unsigned count); - void Copy(const Vector3* loc, const Vector2* uv, const Vector4* diffuse, unsigned first_vertex, unsigned count); - -protected: - IDirect3DVertexBuffer8* VertexBuffer; - - void Create_Vertex_Buffer(UsageType usage); -}; - - -/** -** SortingVertexBufferClass -** This class acts as a vertex buffer for the vertices that need to be passed to alpha renderer. -*/ -class SortingVertexBufferClass : public VertexBufferClass -{ - W3DMPO_CODE(SortingVertexBufferClass) - - friend DX8Wrapper; - friend SortingRendererClass; - friend VertexBufferClass::WriteLockClass; - friend VertexBufferClass::AppendLockClass; - friend DynamicVBAccessClass::WriteLockClass; - - VertexFormatXYZNDUV2* VertexBuffer; - -protected: - virtual ~SortingVertexBufferClass() override; -public: - SortingVertexBufferClass(unsigned short VertexCount); -}; diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index e1a1eaa9c79..cd6a3a731c1 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -45,21 +45,21 @@ set(WW3D2_SRC #dllist.h # dx8caps.cpp # dx8caps.h - dx8fvf.cpp - dx8fvf.h - dx8indexbuffer.cpp - dx8indexbuffer.h +# dx8fvf.cpp +# dx8fvf.h +# dx8indexbuffer.cpp +# dx8indexbuffer.h #dx8list.h #dx8polygonrenderer.cpp #dx8polygonrenderer.h - dx8renderer.cpp - dx8renderer.h +# dx8renderer.cpp +# dx8renderer.h # dx8rendererdebugger.cpp # dx8rendererdebugger.h #dx8texman.cpp #dx8texman.h - dx8vertexbuffer.cpp - dx8vertexbuffer.h +# dx8vertexbuffer.cpp +# dx8vertexbuffer.h #dx8webbrowser.cpp #dx8webbrowser.h # dx8wrapper.cpp diff --git a/scripts/cpp/unify_move_files.py b/scripts/cpp/unify_move_files.py index b293dd29157..936b08844e6 100644 --- a/scripts/cpp/unify_move_files.py +++ b/scripts/cpp/unify_move_files.py @@ -536,6 +536,15 @@ def main(): #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameLogic/System/Damage.cpp", Game.CORE, "GameEngine/Source/GameLogic/System/Damage.cpp") #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp", Game.CORE, "GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp") #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameLogic/System/RankInfo.cpp", Game.CORE, "GameEngine/Source/GameLogic/System/RankInfo.cpp") + + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8fvf.h", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8fvf.h") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.h") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8renderer.h", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8renderer.h") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.h") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8fvf.cpp") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8indexbuffer.cpp") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8renderer.cpp") + #unify_file_lib(Game.ZEROHOUR, "Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp", Game.CORE, "Libraries/Source/WWVegas/WW3D2/dx8vertexbuffer.cpp") return