OpenBarnyard
 
Loading...
Searching...
No Matches
AModelLoader.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "AModelLoader.h"
3#include "AAssetLoader.h"
5
6#ifdef TOSHI_SKU_WINDOWS
10
11# include <Render/TTMDWin.h>
14#endif // TOSHI_SKU_WINDOWS
15
16//-----------------------------------------------------------------------------
17// Enables memory debugging.
18// Note: Should be the last include!
19//-----------------------------------------------------------------------------
20#include <Core/TMemoryDebugOn.h>
21
23
25
27{
28 for ( TUINT i = 0; i < TARRAYSIZE( ms_oNodesAlloc ); i++ )
29 {
30 ms_oFreeMaterials.PushBack( &ms_oNodesAlloc[ i ] );
31 ms_oNodesAlloc[ i ].iId = TUINT16( i );
32 }
33
34 // Load material properties
35 const TBOOL bAssetPackLoaded = AAssetLoader::GetAssetTRB( AAssetType_AssetPack ) != TNULL;
36
37 if ( bAssetPackLoaded )
38 {
39 // Use asset pack
40 ms_pWorldEndRender = AAssetLoader::GetSymbolAddress( "materialproperties", "WorldEndRender", AAssetType_AssetPack );
41 ms_pWorldStartRender = AAssetLoader::GetSymbolAddress( "materialproperties", "WorldStartRender", AAssetType_AssetPack );
42 ms_pWorldUVOffsetsPerSec = AAssetLoader::GetSymbolAddress( "materialproperties", "WorldUVOffsetsPerSec", AAssetType_AssetPack );
43 ms_pAlphaRefMaterials = AAssetLoader::CastSymbol<AlphaRefMaterial>( "materialproperties", "AlphaRefMaterials", AAssetType_AssetPack );
44 ms_pClampedMaterials = AAssetLoader::CastSymbol<ClampedMaterial>( "materialproperties", "ClampedMaterials", AAssetType_AssetPack );
45 ms_pGlowMaterials = AAssetLoader::CastSymbol<const TCHAR*>( "materialproperties", "GlowMaterials", AAssetType_AssetPack );
46 }
47 else
48 {
49 // Load from file
50 m_oTRB.Load( "Data\\MiscTextures\\MaterialProperties.trb" );
51 ms_pWorldEndRender = m_oTRB.GetSymbolAddress( "WorldEndRender" );
52 ms_pWorldStartRender = m_oTRB.GetSymbolAddress( "WorldStartRender" );
53 ms_pWorldUVOffsetsPerSec = m_oTRB.GetSymbolAddress( "WorldUVOffsetsPerSec" );
54 ms_pAlphaRefMaterials = m_oTRB.CastSymbol<AlphaRefMaterial>( "AlphaRefMaterials" );
55 ms_pClampedMaterials = m_oTRB.CastSymbol<ClampedMaterial>( "ClampedMaterials" );
56 ms_pGlowMaterials = m_oTRB.CastSymbol<const TCHAR*>( "GlowMaterials" );
57 }
58
59 TModel::SetLoaderTMDCallback( AModelLoaderLoadTMDCallback );
60 TModel::SetLoaderTRBCallback( AModelLoaderLoadTRBCallback );
61
62 // Count glow materials
63 ms_iNumGlowMaterials = 0;
64 auto pGlowMaterial = ms_pGlowMaterials;
65
66 while ( *pGlowMaterial )
67 {
68 ms_iNumGlowMaterials += 1;
69 pGlowMaterial++;
70 }
71
72 // Load double sided materials
73 ms_pDoubleSidedMaterials = ( bAssetPackLoaded ) ?
74 AAssetLoader::CastSymbol<const TCHAR*>( "materialproperties", "DoubleSidedMaterials", AAssetType_AssetPack ) :
75 m_oTRB.CastSymbol<const TCHAR*>( "DoubleSidedMaterials" );
76
77 // Count double sided materials
78 ms_iNumDoubleSidedMaterials = 0;
79 auto pDoubleSidedMaterial = ms_pDoubleSidedMaterials;
80
81 while ( *pDoubleSidedMaterial )
82 {
83 ms_iNumDoubleSidedMaterials += 1;
84 pDoubleSidedMaterial++;
85 }
86
87 // Symbol table is not needed anymore
88 if ( !bAssetPackLoaded )
89 m_oTRB.DeleteSymbolTable();
90
91 if ( TNULL == ms_pDefaultSkinMaterial )
92 {
93 ASkinMaterial* pSkinMaterial = ASkinShader::GetSingleton()->CreateMaterial( TNULL );
94 pSkinMaterial->Create( 7 );
95 pSkinMaterial->SetFlags( TMaterial::FLAGS_NO_CULL, TFALSE );
96 pSkinMaterial->SetTexture( TNULL );
97
98 ms_pDefaultSkinMaterial = pSkinMaterial;
99 }
100
101 if ( TNULL == ms_pDefaultWorldMaterial )
102 {
103 AWorldMaterial* pWorldMaterial = AWorldShader::GetSingleton()->CreateMaterial( TNULL );
104 pWorldMaterial->Create( 6 );
105 pWorldMaterial->SetFlags( TMaterial::FLAGS_NO_CULL, TFALSE );
106 pWorldMaterial->SetTexture( 0, TNULL );
107 pWorldMaterial->SetTextureNum( 1 );
108
109 ms_pDefaultWorldMaterial = pWorldMaterial;
110 }
111}
112
116
117void AModelLoader::MaterialApplyFlags( TMaterial* a_pMaterial, const TCHAR* a_szMaterialName )
118{
119 // Check if material is glowing
120 for ( TINT i = 0; i < ms_iNumGlowMaterials; i++ )
121 {
122 if ( TStringManager::String8Compare( ms_pGlowMaterials[ i ], a_szMaterialName ) == 0 )
123 {
124 a_pMaterial->SetFlags( TMaterial::FLAGS_GLOW, TTRUE );
125 break;
126 }
127 }
128
129 // Check if material is double sided
130 for ( TINT i = 0; i < ms_iNumDoubleSidedMaterials; i++ )
131 {
132 if ( TStringManager::String8Compare( ms_pDoubleSidedMaterials[ i ], a_szMaterialName ) == 0 )
133 {
134 a_pMaterial->SetFlags( TMaterial::FLAGS_NO_CULL, TTRUE );
135 break;
136 }
137 }
138}
139
140void AModelLoader::MaterialApplyClamp( TMaterial* a_pMaterial, const TCHAR* a_szMaterialName, TTexture* a_pTexture )
141{
142 auto pClampedMaterial = ms_pClampedMaterials;
143
144 for ( ;; )
145 {
146 if ( pClampedMaterial->szName == TNULL ) return;
147 if ( TStringManager::String8Compare( pClampedMaterial->szName, a_szMaterialName ) == 0 ) break;
148
149 pClampedMaterial += 1;
150 }
151
152 for ( TUINT i = 0; i < a_pMaterial->GetTextureNum(); i++ )
153 {
154 if ( a_pTexture )
155 {
156 auto pTexture = TDYNAMICCAST( TTextureResourceHAL, a_pTexture );
157
158 if ( pClampedMaterial->eAddressUState > 0 )
159 pTexture->SetAddressUState( ADDRESSINGMODE_CLAMP );
160
161 if ( pClampedMaterial->eAddressVState > 0 )
162 pTexture->SetAddressVState( ADDRESSINGMODE_CLAMP );
163 }
164 }
165}
166
167void AModelLoader::MaterialApplyAlphaRef( TMaterial* a_pMaterial, const TCHAR* a_szMaterialName, TTexture* a_pTexture )
168{
169 auto pAlphaRefMaterial = ms_pAlphaRefMaterials;
170
171 for ( ;; )
172 {
173 if ( pAlphaRefMaterial->szName == TNULL ) return;
174 if ( TStringManager::String8Compare( pAlphaRefMaterial->szName, a_szMaterialName ) == 0 ) break;
175
176 pAlphaRefMaterial += 1;
177 }
178
179 // Does nothing with the material in the original game
180}
181
182// $Barnyard: FUNCTION 006119d0
183TMaterial* AModelLoader::CreateMaterial( TShader* a_pShader, const TCHAR* a_szMaterialName )
184{
186
187 char prefixName[ 32 ];
188
189 if ( a_pShader->IsA( &TGetClass( ASkinShader ) ) )
190 {
191 TStringManager::String8Copy( prefixName, "ss_" );
192 }
193 else if ( a_pShader->IsA( &TGetClass( AWorldShader ) ) )
194 {
195 TStringManager::String8Copy( prefixName, "ws_" );
196 }
197 else if ( a_pShader->IsA( &TGetClass( AGrassShader ) ) )
198 {
199 TStringManager::String8Copy( prefixName, "gs_" );
200 }
201 else
202 {
203 TASSERT( !"Unknown shader" );
204 return TNULL;
205 }
206
207 TString8 materialName = prefixName;
208 materialName += a_szMaterialName;
209
210 auto pResultMaterial = FindMaterial( materialName );
211 if ( pResultMaterial ) return pResultMaterial;
212
213 TTextureResourceHAL* pTexture;
214 const char* szTextureName;
215 auto pTMDMaterial = FindMaterialInModel( a_szMaterialName );
216
217 if ( pTMDMaterial )
218 {
219 pTexture = TDYNAMICCAST(
221 AMaterialLibraryManager::GetSingleton()->FindTexture( pTMDMaterial->szTextureFile )
222 );
223
224 szTextureName = pTMDMaterial->szTextureFile;
225 }
226 else
227 {
228 TTRACE( "Couldn't find texture for material '%s'", a_szMaterialName );
229 pTexture = TDYNAMICCAST(
231 TRenderD3DInterface::Interface()->GetInvalidTexture()
232 );
233 szTextureName = "invalid";
234 }
235
236 TVALIDPTR( pTexture );
237
238 auto eTextureFormat = pTexture->GetImageInfo().Format;
239 const TBOOL bIsAlpha = eTextureFormat == D3DFMT_A8R8G8B8 ||
240 eTextureFormat == D3DFMT_A4R4G4B4 ||
241 eTextureFormat == D3DFMT_A8R3G3B2 ||
242 eTextureFormat == D3DFMT_DXT5;
243
244 if ( a_pShader->IsA( &TGetClass( ASkinShader ) ) )
245 {
246 ASkinShaderHAL* pShader = TDYNAMICCAST( ASkinShaderHAL, a_pShader );
247 ASkinMaterial* pMaterial = pShader->CreateMaterial( TNULL );
248 pMaterial->Create( bIsAlpha ? 1 : 0 );
249 pMaterial->SetTexture( pTexture );
250
251 pResultMaterial = pMaterial;
252 }
253 else if ( a_pShader->IsA( &TGetClass( AWorldShader ) ) )
254 {
255 AWorldShaderHAL* pShader = TDYNAMICCAST( AWorldShaderHAL, a_pShader );
256 AWorldMaterial* pMaterial = pShader->CreateMaterial( TNULL );
257 pMaterial->Create( bIsAlpha ? 1 : 0 );
258 pMaterial->SetTexture( 0, pTexture );
259 pMaterial->SetTextureNum( 1 );
260
261 pResultMaterial = pMaterial;
262
263 TTODO( "Setup material using properties" );
264 }
265 else if ( a_pShader->IsA( &TGetClass( AGrassShader ) ) )
266 {
267 AGrassShaderHAL* pShader = TDYNAMICCAST( AGrassShaderHAL, a_pShader );
268 AGrassMaterial* pMaterial = pShader->CreateMaterial( TNULL );
269 pMaterial->Create( 0 );
270 pMaterial->SetTexture( 0, pTexture );
271 pMaterial->SetTextureNum( 1 );
272
273 pResultMaterial = pMaterial;
274 }
275 else
276 {
277 TASSERT( !"Support other shaders" );
278 }
279
280 MaterialApplyFlags( pResultMaterial, a_szMaterialName );
281 MaterialApplyClamp( pResultMaterial, a_szMaterialName, pTexture );
282 MaterialApplyAlphaRef( pResultMaterial, a_szMaterialName, pTexture );
283
284 TASSERT( !ms_oFreeMaterials.IsEmpty() );
285 auto pMatNode = ms_oFreeMaterials.PopFront();
286 pMatNode->pMaterial = pResultMaterial;
287 pMatNode->iNumRefs = 1;
288
289 TStringManager::String8Copy( pMatNode->szTextureName, szTextureName, TARRAYSIZE( pMatNode->szTextureName ) );
290 TStringManager::String8Copy( pMatNode->szName, materialName, TARRAYSIZE( pMatNode->szName ) );
291
292 // Truncate material name so it fits the limit
293 if ( materialName.Length() > TMaterial::NAMESIZELIMIT )
294 {
295 materialName[ TMaterial::NAMESIZELIMIT ] = '\0';
296 }
297
298 pResultMaterial->SetName( materialName );
299 ms_oUsedMaterials.PushFront( pMatNode );
300
301 AddMaterial( materialName, pMatNode );
302 return pResultMaterial;
303}
304
305void AModelLoader::DestroyMaterial( TMaterial* a_pMaterial )
306{
308
309 TINT iId = 0;
310 TINT16 iIndex;
311
312 if ( 0 < ms_iNumCreatedMaterials )
313 {
314 while ( true )
315 {
316 iIndex = ms_oMaterialIds[ iId ];
317 if ( a_pMaterial == ms_oNodesAlloc[ iIndex ].pMaterial ) break;
318
319 if ( ms_iNumCreatedMaterials <= ++iId )
320 {
321 TASSERT( !"Trying to destroy some unknown material" );
322 return;
323 }
324 }
325
326 ms_oNodesAlloc[ iIndex ].iNumRefs -= 1;
327
328 if ( ms_oNodesAlloc[ iIndex ].iNumRefs < 1 )
329 {
330 ms_oNodesAlloc[ iIndex ].Remove();
331 ms_oNodesAlloc[ iIndex ].pMaterial->Destroy();
332 ms_oNodesAlloc[ iIndex ].pMaterial = TNULL;
333
334 ms_oFreeMaterials.PushFront( &ms_oNodesAlloc[ iIndex ] );
335 ms_iNumCreatedMaterials -= 1;
336
337 if ( iId < ms_iNumCreatedMaterials )
338 {
339 TINT16* pNext = ms_oMaterialIds + iId + 1;
340 TINT16* pCurr = ms_oMaterialIds + iId;
341
342 for ( TINT i = ms_iNumCreatedMaterials - iId; i != 0; i-- )
343 {
344 *( pCurr++ ) = *( pNext++ );
345 }
346 }
347 }
348 }
349}
350
352{
353 InitialiseGrassLayersTextures();
354}
355
356void AModelLoader::AddMaterial( const TString8& a_rName, MaterialNode* a_pMaterialNode )
357{
359
360 TINT iMaxIndex = ms_iNumCreatedMaterials;
361 TINT iMaterialIndex = ms_iNumCreatedMaterials / 2;
362
363 TINT iOffset = 0;
364 TINT iCmpResult = 0;
365
366 while ( iOffset <= iMaterialIndex )
367 {
368 if ( iMaxIndex <= iMaterialIndex ) break;
369
370 auto pMatNode = &ms_oNodesAlloc[ ms_oMaterialIds[ iMaterialIndex ] ];
371 iCmpResult = TStringManager::String8Compare( a_rName, pMatNode->szName );
372
373 if ( -1 < iCmpResult )
374 {
375 iOffset = iMaterialIndex + 1;
376 iMaterialIndex = iMaxIndex;
377 }
378
379 iMaxIndex = iMaterialIndex;
380 iMaterialIndex = iOffset + ( iMaterialIndex - iOffset ) / 2;
381 }
382
383 if ( iCmpResult < 1 && ( iOffset = iMaterialIndex, iCmpResult < 0 ) )
384 {
385 iOffset = iMaxIndex;
386 }
387
388 for ( TINT i = ms_iNumCreatedMaterials; iOffset < i; i-- )
389 {
390 ms_oMaterialIds[ i ] = ms_oMaterialIds[ i - 1 ];
391 }
392
393 ms_oMaterialIds[ iOffset ] = a_pMaterialNode->iId;
394 ms_iNumCreatedMaterials += 1;
395}
396
397TMaterial* AModelLoader::FindMaterial( const TString8& a_rName )
398{
400
401 TINT iMaxIndex = ms_iNumCreatedMaterials;
402 TINT iMaterialIndex = ms_iNumCreatedMaterials / 2;
403
404 TINT iOffset = 0;
405
406 while ( iOffset <= iMaterialIndex )
407 {
408 if ( iMaxIndex <= iMaterialIndex ) break;
409
410 auto pMatNode = &ms_oNodesAlloc[ ms_oMaterialIds[ iMaterialIndex ] ];
411 TINT iCmpResult = TStringManager::String8Compare( a_rName, pMatNode->szName );
412
413 if ( iCmpResult == 0 )
414 {
415 pMatNode->iNumRefs++;
416
417 if ( pMatNode->pMaterial )
418 return pMatNode->pMaterial;
419
420 break;
421 }
422
423 if ( iCmpResult > -1 )
424 {
425 iOffset = iMaterialIndex + 1;
426 iMaterialIndex = iMaxIndex;
427 }
428
429 iMaxIndex = iMaterialIndex;
430 iMaterialIndex = iOffset + ( iMaterialIndex - iOffset ) / 2;
431 }
432
433 return TNULL;
434}
435
436TTMDBase::Material* AModelLoader::FindMaterialInModel( const TCHAR* a_szName )
437{
438 for ( TINT i = 0; i < ms_oCurrentModelMaterialsHeader.iNumMaterials; i++ )
439 {
440 if ( TStringManager::String8Compare( ms_oCurrentModelMaterials[ i ].szMatName, a_szName ) == 0 )
441 {
442 return &ms_oCurrentModelMaterials[ i ];
443 }
444 }
445
446 return TNULL;
447}
448
449TBOOL AModelLoader::AModelLoaderLoadTMDCallback( TModel* a_pModel )
450{
451 return TFALSE;
452}
453
454TBOOL AModelLoader::AModelLoaderLoadTRBCallback( TModel* a_pModel )
455{
457
458 TTODO( "Load collision data" );
459
460 TTMDWin::TRBWinHeader* pHeader = a_pModel->CastSymbol<TTMDWin::TRBWinHeader>( "Header" );
461 TTMDBase::MaterialsHeader* pMaterials = a_pModel->CastSymbol<TTMDBase::MaterialsHeader>( "Materials" );
462
463 // Copy info about materials of the current model
464 TUtil::MemCopy( ms_oCurrentModelMaterials, pMaterials + 1, pMaterials->uiSectionSize );
465 ms_oCurrentModelMaterialsHeader = *pMaterials;
466
467 a_pModel->m_iLODCount = pHeader->m_iNumLODs;
468 a_pModel->m_fLODDistance = pHeader->m_fLODDistance;
469
470 for ( TINT i = 0; i < pHeader->m_iNumLODs; i++ )
471 {
472 auto pTRBLod = pHeader->GetLOD( i );
473
474 a_pModel->m_LODs[ i ].iNumMeshes = pTRBLod->m_iMeshCount1 + pTRBLod->m_iMeshCount2;
475 a_pModel->m_LODs[ i ].ppMeshes = new TMesh*[ a_pModel->m_LODs[ i ].iNumMeshes ];
476 a_pModel->m_LODs[ i ].BoundingSphere = pTRBLod->m_RenderVolume;
477
478 if ( pTRBLod->m_eShader == TTMDWin::ST_WORLD )
479 {
480 LoadWorldMeshTRB( a_pModel, i, &a_pModel->m_LODs[ i ], pTRBLod );
481 continue;
482 }
483 else if ( pTRBLod->m_eShader == TTMDWin::ST_SKIN )
484 {
485 LoadSkinLOD( a_pModel, i, &a_pModel->m_LODs[ i ], pTRBLod );
486 continue;
487 }
488 else if ( pTRBLod->m_eShader == TTMDWin::ST_GRASS )
489 {
490 LoadGrassMeshTRB( a_pModel, i, &a_pModel->m_LODs[ i ], pTRBLod );
491 continue;
492 }
493
494 TASSERT( !"The model is using an unknown shader" );
495 return TFALSE;
496 }
497
498 return TTRUE;
499}
@ ADDRESSINGMODE_CLAMP
Definition TRender.h:42
#define TASSERT(X,...)
Definition Defines.h:138
#define TOSHI_NAMESPACE_USING
Definition Defines.h:46
#define TTODO(DESC)
Definition Defines.h:134
#define TARRAYSIZE(ARRAY)
Definition Defines.h:70
#define TTRACE(...)
Definition Defines.h:155
#define TVALIDPTR(PTR)
Definition Defines.h:139
#define TPROFILER_SCOPE()
Definition Profiler.h:17
#define TGetClass(CLASS)
Definition TObject.h:13
#define TDYNAMICCAST(T, OBJECT)
Definition TObject.h:227
#define TDEFINE_CLASS(...)
Definition TObject.h:120
uint16_t TUINT16
Definition Typedefs.h:15
unsigned int TUINT
Definition Typedefs.h:8
int16_t TINT16
Definition Typedefs.h:14
char TCHAR
Definition Typedefs.h:20
#define TNULL
Definition Typedefs.h:23
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
@ AAssetType_AssetPack
Definition AAssetLoader.h:7
@ ST_GRASS
Definition TTMDWin.h:42
@ ST_SKIN
Definition TTMDWin.h:40
@ ST_WORLD
Definition TTMDWin.h:41
static TFORCEINLINE TRenderD3DInterface * Interface()
Gets the render interface singleton.
D3DXIMAGE_INFO & GetImageInfo()
static constexpr TUINT NAMESIZELIMIT
Definition TMaterial.h:18
TUINT32 GetTextureNum() const
Definition TMaterial.cpp:84
void SetFlags(Flags a_eFlag, TBOOL a_bEnable)
@ FLAGS_NO_CULL
Definition TMaterial.h:24
TSphere BoundingSphere
Definition TModel.h:26
TINT iNumMeshes
Definition TModel.h:27
TMesh ** ppMeshes
Definition TModel.h:28
TFLOAT m_fLODDistance
Definition TModel.h:149
static void SetLoaderTMDCallback(t_ModelLoaderTMDCallback a_cbLoader)
Definition TModel.h:138
TINT m_iLODCount
Definition TModel.h:148
T * CastSymbol(const TCHAR *a_szSymbolName)
Definition TModel.h:133
TModelLOD m_LODs[MAX_NUM_LODS]
Definition TModel.h:151
static void SetLoaderTRBCallback(t_ModelLoaderTRBCallback a_cbLoader)
Definition TModel.h:139
TRBLODHeader * GetLOD(TINT a_uiIndex)
Definition TTMDWin.h:67
TINT Length() const
Definition TString8.h:93
static TINT String8Compare(const TCHAR *str1, const TCHAR *str2, TSIZE size=-1)
static TCHAR * String8Copy(TCHAR *dst, const TCHAR *src, TSIZE size=-1)
static void * MemCopy(void *dst, const void *src, TSIZE size)
Definition TUtil.h:90
static Toshi::TTRB * GetAssetTRB(AAssetType a_eAssetType)
static void * GetSymbolAddress(const TCHAR *a_szFileName, const TCHAR *a_szSymbolName, AAssetType a_eAssetType)
static T * CastSymbol(const TCHAR *a_szFileName, const TCHAR *a_szSymbolName, AAssetType a_eAssetType)
static void DestroyMaterial(Toshi::TMaterial *a_pMaterial)
static Toshi::TMaterial * CreateMaterial(Toshi::TShader *a_pShader, const TCHAR *a_szMaterialName)
static void InitialiseStatic()
virtual AGrassMaterial * CreateMaterial(const TCHAR *a_szName) override
virtual ASkinMaterial * CreateMaterial(const TCHAR *a_szName) override
virtual AWorldMaterial * CreateMaterial(const TCHAR *a_szName) override
virtual TBOOL Create(BLENDMODE a_eBlendMode)
void SetTexture(TUINT a_uiStage, Toshi::TTexture *a_pTexture)
void SetTexture(Toshi::TTexture *a_pTexture)
virtual TBOOL Create(BLENDMODE a_eBlendMode)
void SetTexture(TUINT a_uiStage, Toshi::TTexture *a_pTexture)
virtual TBOOL Create(BLENDMODE a_eBlendMode)