OpenBarnyard
 
Loading...
Searching...
No Matches
AModel.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "AModel.h"
3
7#include "Render/ARenderer.h"
10
11#ifdef TOSHI_SKU_WINDOWS
13#endif
14
16
17//-----------------------------------------------------------------------------
18// Enables memory debugging.
19// Note: Should be the last include!
20//-----------------------------------------------------------------------------
21#include <Core/TMemoryDebugOn.h>
22
24
26
27// $Barnyard: FUNCTION 0060fef0
28AModel::AModel( const TPString8& a_rName, TTRB* a_pTRB )
29 : m_Name( a_rName )
30 , m_uiID( ms_uiNumCreated )
31 , m_pManagedModel( TNULL )
32 , m_Vec1( TVector3::VEC_ZERO )
33 , m_Vec2( TVector3::VEC_ZERO )
34{
35 m_pManagedModel = AModel::Create( a_rName, a_pTRB );
36
37 ms_uiNumCreated += 1;
38}
39
40// $Barnyard: FUNCTION 0060fc90
41// $Barnyard: FUNCTION 0060fed0
43{
44 if ( m_pManagedModel )
45 {
46 delete m_pManagedModel;
47 }
48}
49
50// $Barnyard: FUNCTION 0060f9f0
51void AModel::Update( TFLOAT a_fDeltaTime )
52{
53 TRenderContext* pRenderCtx = ARenderer::GetSingleton()->GetMainViewport()->GetRenderContext();
54
55 for ( TINT i = 0; i < m_vecInstanceRefs.Size(); i++ )
56 {
57 AModelInstance* pInstance = m_vecInstanceRefs[ i ].Get();
58 TSceneObject* pSceneObject = pInstance->GetSceneObject();
59 TModel* pModel = pSceneObject->GetInstance()->GetModel();
60
61 auto& transform = pSceneObject->GetTransform();
62 auto& transformScale = transform.GetScale();
63 auto& lod = pModel->GetLOD( 0 );
64
65 TVector4 vecBoundingSphere;
66 vecBoundingSphere.w = lod.BoundingSphere.GetRadius() * TMath::Max( TMath::Max( transformScale.x, transformScale.y ), transformScale.z );
67
68 if ( vecBoundingSphere.w <= 0.0f )
69 // The instance's scale is zero, do not render
70 {
71 pInstance->SetVisible( TFALSE );
72 }
73 else
74 // Check if the bounding sphere currently visible
75 {
76 TMatrix44 transformMatrix;
77 transform.GetLocalMatrixImp( transformMatrix );
78
79 TMatrix44::TransformVector( vecBoundingSphere.AsVector3(), transformMatrix, lod.BoundingSphere.GetOrigin() );
80
81 if ( TRenderContext::CullSphereToFrustumSimple( vecBoundingSphere, pRenderCtx->GetWorldPlanes(), 6 ) )
82 {
83 // The object is visible, update clip flags to match the flags it was checked against
84 pInstance->SetVisible( TTRUE );
85 pInstance->SetClipFlags( pRenderCtx->GetClipFlags() );
86 }
87 else
88 {
89 // The object is not visible
90 pInstance->SetVisible( TFALSE );
91 }
92 }
93
94 if ( pInstance->IsUpdatingSkeleton() )
95 {
96 pInstance->GetSceneObject()->Update( a_fDeltaTime );
97 }
98 }
99}
100
101// $Barnyard: FUNCTION 0060fb10
102void AModel::Render( TBOOL a_bIsSomething )
103{
104 for ( TINT i = 0; i < m_vecInstanceRefs.Size(); i++ )
105 {
106 auto& pModelInstance = m_vecInstanceRefs[ i ];
107 auto eFlags = pModelInstance->m_eFlags;
108
109 if ( HASANYFLAG( eFlags, AModelInstance::Flags_Unknown ) == a_bIsSomething &&
112 {
113 auto pSceneObject = pModelInstance->GetSceneObject();
114 auto pModel = pSceneObject->GetInstance()->GetModel();
115
116 auto& transform = pSceneObject->GetTransform();
117 auto& transformScale = transform.GetScale();
118 auto& lod = pModel->GetLOD( 0 );
119
120 TFLOAT fRadiusScale = TMath::Max( TMath::Max( transformScale.x, transformScale.y ), transformScale.z );
121 TFLOAT fRadius = lod.BoundingSphere.GetRadius() * fRadiusScale;
122
123 TMatrix44 transformMatrix;
124 transform.GetLocalMatrixImp( transformMatrix );
125
126 TVector3 boundingPos;
127 TMatrix44::TransformVector( boundingPos, transformMatrix, lod.BoundingSphere.GetOrigin() );
128 pSceneObject->Render( pModelInstance->GetClipFlags(), boundingPos );
129 }
130 }
131}
132
133// $Barnyard: FUNCTION 0060fd20
135{
136 // TODO: use this name in debug?
137 TString8 instanceName = GenerateInstanceName( m_Name );
138
139 AModelInstanceRef modelInstanceRef = new AModelInstance(
140 this,
141 m_pManagedModel->CreateSceneObject(),
142 TFALSE
143 );
144
145 m_vecInstanceRefs.PushBack( modelInstanceRef );
146 return modelInstanceRef;
147}
148
149// $Barnyard: FUNCTION 0060fe40
151{
152 m_vecInstanceRefs.FindAndEraseFast( a_pInstance );
153}
154
156{
157 return m_vecInstanceRefs.Size();
158}
159
160// $Barnyard: FUNCTION 0060f8c0
161TManagedModel* AModel::Create( const TPString8& a_rFilePath, TTRB* a_pTRB )
162{
163 // TODO: use this name in debug?
164 TString8 modelName;
165 GetNameFromPath( a_rFilePath, modelName );
166
167 auto pModelPtr = new TManagedModel();
168
169 if ( pModelPtr )
170 {
171 TString8 filepath = a_rFilePath.GetString8();
172 filepath.MakeLower();
173
174 if ( filepath.Find( ".trb" ) < 0 &&
175 filepath.Find( ".trz" ) < 0 )
176 {
177 filepath += ".trb";
178 }
179
180 pModelPtr->Create( filepath, a_pTRB );
181
182 ASkinLightingManager::GetSingleton()->ApplySkinLight( pModelPtr, TNULL, TNULL );
183 }
184
185 return pModelPtr;
186}
187
188// $Barnyard: FUNCTION 0060f6e0
189void AModel::GetNameFromPath( const TPString8& a_FilePath, TString8& a_rName )
190{
191 TString8 name = a_FilePath.GetString8();
192
193 if ( name.Length() <= 8 )
194 {
195 a_rName = name;
196 }
197 else
198 {
199 TINT iPos1 = 0;
200 TINT iPos2;
201
202 do {
203 iPos2 = iPos1;
204 iPos1 = name.Find( '\\', iPos1 + 1 );
205 } while ( -1 < iPos1 );
206
207 do {
208 iPos1 = iPos2;
209 iPos2 = name.Find( '/', iPos1 + 1 );
210 } while ( -1 < iPos2 );
211
212 if ( iPos1 < 0 || name.Length() - 1 <= iPos1 ) iPos1 = 0;
213 iPos1 += 1;
214 iPos2 = name.Find( '_', iPos1 );
215 if ( iPos2 < 0 ) iPos2 = name.Length() - 1;
216
217 TUINT iSize = iPos2 - iPos1;
218
219 if ( iSize < 1 )
220 {
221 iPos1 = 0;
222 iSize = 8;
223 }
224 else if ( 8 < iSize )
225 {
226 iSize = 8;
227 }
228
229 a_rName.Copy( name.GetString( iPos1 ), iSize );
230 }
231}
232
233// $Barnyard: FUNCTION 0060f7f0
235{
236 static TUINT ms_uiDebugObjectIndex = 0;
237
238 TString8 name;
239 GetNameFromPath( a_FilePath, name );
240
241 TString8 debugName;
242 debugName.Format( "%s%i", name.GetString(), ms_uiDebugObjectIndex % 1000 );
243 ms_uiDebugObjectIndex += 1;
244
245 return debugName;
246}
247
248// $Barnyard: FUNCTION 00611280
249AModelInstance::AModelInstance( AModel* a_pModel, TSceneObject* a_pSceneObject, TBOOL a_bEnableSkeletonUpdate )
250 : m_ChangeEmitter( this )
251{
252 TFIXME( "Initialise some unknown members" );
253
254 m_Scale = TVector4( 1.0f, 1.0f, 1.0f, 1.0f );
255 m_pModel = a_pModel;
256 m_uiClipFlags = 0x3F;
257 m_pSceneObject = a_pSceneObject;
258 m_eFlags = Flags_ReceivesLight | Flags_UpdatingSkeleton;
259
260 SetSkeletonUpdating( a_bEnableSkeletonUpdate );
261 m_pSceneObject->GetInstance()->SetCustomRenderMethod( RenderInstanceCallback, this );
262}
263
264// $Barnyard: FUNCTION 00610820
266 : m_ChangeEmitter( this )
267{
268 TFIXME( "Initialise some unknown members" );
269
270 m_Scale = TVector4( 1.0f, 1.0f, 1.0f, 1.0f );
271 m_pModel = TNULL;
272 m_pSceneObject = TNULL;
273 m_uiClipFlags = 0x3F;
274 m_eFlags = 0b00010000 | Flags_ReceivesLight;
275}
276
277// $Barnyard: FUNCTION 006100d0
278void AModelInstance::SetTransform( const TMatrix44& a_rcTransform )
279{
280 m_pSceneObject->GetTransform().SetMatrix( a_rcTransform );
281}
282
283// $Barnyard: FUNCTION 006108c0
284void AModelInstance::RenderInstanceCallback( TModelInstance* a_pInstance, void* a_pUserData )
285{
286 TModel* pModel = a_pInstance->GetModel();
287 TSkeletonInstance* pSkeletonInstance = a_pInstance->GetSkeletonInstance();
288
289 AModelInstance* pGameModelInstance = TSTATICCAST( AModelInstance, a_pUserData );
290
291 // Update skeleton state
292 pSkeletonInstance->UpdateState( TTRUE );
293
294 // Update current render context with actual skeleton instance to render
296 pRenderContext->SetSkeletonInstance( pSkeletonInstance );
297
298 TModelLOD* pLOD = &pModel->GetLOD( a_pInstance->GetLOD() );
299 TBOOL bIsWorldMesh = TFALSE;
300
301 // Check if it's a world model
302 if ( pLOD->iNumMeshes > 0 )
303 {
304 bIsWorldMesh = pLOD->ppMeshes[ 0 ]->GetClass() == &TGetClass( AWorldShaderHAL );
305 }
306
307 // Check if object can be affected by any light sources
308 if ( pLOD->iNumMeshes > 0 && pGameModelInstance->ReceivesLight() )
309 {
310 TMatrix44 matTransform;
311 pGameModelInstance->GetSceneObject()->GetTransform().GetLocalMatrixImp( matTransform );
312
313 // Get position of bounding sphere transformed by this scene object
314 TSphere boundingSphere = pLOD->BoundingSphere;
315 TMatrix44::TransformVector( boundingSphere.GetOrigin(), matTransform, boundingSphere.GetOrigin() );
316
317 TLightIDList lightIds;
318 AGlowViewport::GetSingleton()->GetInfluencingLightIDs( boundingSphere, lightIds );
319
320 if ( lightIds[ 0 ] != -1 )
321 {
322 // Add light to the render context
323 pRenderContext->AddLight( lightIds[ 0 ] );
324 }
325 }
326
327 static TUINT s_uiUnusedFlags;
328 if ( !( s_uiUnusedFlags & 1 ) )
329 s_uiUnusedFlags |= 1;
330
331 static TMatrix44 s_oOldModelViewMatrix;
332 TMatrix44 oScaledModelViewMatrix;
333
334 if ( pGameModelInstance )
335 {
336 // Save current model view matrix
337 s_oOldModelViewMatrix = pRenderContext->GetModelViewMatrix();
338
339 // Calculate model view matrix for this instance and set it
340 oScaledModelViewMatrix = pRenderContext->GetModelViewMatrix();
341 oScaledModelViewMatrix.Scale( pGameModelInstance->GetScale() );
342
343 pRenderContext->SetModelViewMatrix( oScaledModelViewMatrix );
344 }
345
346 // Don't do anything if there are no meshed to render
347 if ( pLOD->iNumMeshes == 0 )
348 return;
349
350 TBOOL bIsStaticInstanceMesh = pLOD->ppMeshes[ 0 ]->IsA( &TGetClass( AStaticInstanceMesh ) );
351 AStaticInstanceMaterial* pStaticInstanceMat = AModelLoader::ms_pDefaultStaticInstanceMaterial;
352 AWorldMaterial* pWorldMat = AModelLoader::ms_pDefaultWorldMaterial;
353 ASkinMaterial* pSkinMat = AModelLoader::ms_pDefaultSkinMaterial;
354
355 static constexpr TINT MAX_NUM_MATERIALS = 32;
356 TMaterial* apOldMaterials[ MAX_NUM_MATERIALS ];
357 TASSERT( pLOD->iNumMeshes < MAX_NUM_MATERIALS );
358
359 if ( !pGameModelInstance->DrawWithDefaultMaterials() )
360 {
361 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
362 {
363 pLOD->ppMeshes[ i ]->Render();
364 }
365 }
366 else if ( bIsStaticInstanceMesh )
367 {
368 // Render meshes with the default material
369 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
370 {
371 apOldMaterials[ i ] = pLOD->ppMeshes[ i ]->GetMaterial();
372 pLOD->ppMeshes[ i ]->SetMaterial( pStaticInstanceMat );
373 pLOD->ppMeshes[ i ]->Render();
374 }
375
376 // Render meshes with their original materials
377 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
378 {
379 pLOD->ppMeshes[ i ]->SetMaterial( apOldMaterials[ i ] );
380 pLOD->ppMeshes[ i ]->Render();
381 }
382 }
383 else if ( bIsWorldMesh )
384 {
385 // Render meshes with the default material
386 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
387 {
388 apOldMaterials[ i ] = pLOD->ppMeshes[ i ]->GetMaterial();
389 pLOD->ppMeshes[ i ]->SetMaterial( pWorldMat );
390 pLOD->ppMeshes[ i ]->Render();
391 }
392
393 // Render meshes with their original materials
394 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
395 {
396 pLOD->ppMeshes[ i ]->SetMaterial( apOldMaterials[ i ] );
397 pLOD->ppMeshes[ i ]->Render();
398 }
399 }
400 else
401 {
402 // Render meshes with the default material
403 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
404 {
405 apOldMaterials[ i ] = pLOD->ppMeshes[ i ]->GetMaterial();
406 pLOD->ppMeshes[ i ]->SetMaterial( pSkinMat );
407 pLOD->ppMeshes[ i ]->Render();
408 }
409
410 // Render meshes with their original materials
411 for ( TINT i = 0; i < pLOD->iNumMeshes; i++ )
412 {
413 pLOD->ppMeshes[ i ]->SetMaterial( apOldMaterials[ i ] );
414 pLOD->ppMeshes[ i ]->Render();
415 }
416 }
417
418 if ( pGameModelInstance )
419 {
420 // Restore old model view matrix
421 pRenderContext->SetModelViewMatrix( s_oOldModelViewMatrix );
422 }
423}
424
425// $Barnyard: FUNCTION 00610cd0
427{
428 if ( a_bUpdating )
429 {
430 if ( !IsUpdatingSkeleton() )
431 {
432 m_pSceneObject->EnableSkeletonUpdate();
433 m_ChangeEmitter.Throw( ChangeEvent_EnabledSkeletonUpdate );
434 }
435
436 m_eFlags |= Flags_UpdatingSkeleton;
437 }
438 else
439 {
440 if ( IsUpdatingSkeleton() )
441 {
442 m_pSceneObject->DisableSkeletonUpdate();
443 m_ChangeEmitter.Throw( ChangeEvent_DisabledSkeletonUpdate );
444 }
445
446 m_eFlags &= ~Flags_UpdatingSkeleton;
447 }
448}
449
450// $Barnyard: FUNCTION 00610380
452{
453 if ( a_bReceives )
454 m_eFlags |= Flags_ReceivesLight;
455 else
456 m_eFlags &= ~Flags_ReceivesLight;
457}
458
459// $Barnyard: FUNCTION 00610d40
461{
462 if ( a_bVisible )
463 {
464 if ( !IsVisible() )
465 m_ChangeEmitter.Throw( ChangeEvent_Visibility );
466
467 m_eFlags |= Flags_Visible;
468 }
469 else
470 {
471 if ( IsVisible() )
472 m_ChangeEmitter.Throw( ChangeEvent_Visibility );
473
474 m_eFlags &= ~Flags_Visible;
475 }
476}
477
478// $Barnyard: FUNCTION 006100c0
480{
481 return m_pModel->GetName();
482}
Rendering system interface for the Toshi engine.
#define TASSERT(X,...)
Definition Defines.h:138
#define TSTATICCAST(POINTERTYPE, VALUE)
Definition Defines.h:69
#define HASANYFLAG(STATE, FLAG)
Definition Defines.h:5
#define TFIXME(DESC)
Definition Defines.h:135
#define TOSHI_NAMESPACE_USING
Definition Defines.h:46
#define TGetClass(CLASS)
Definition TObject.h:13
#define TDEFINE_CLASS(...)
Definition TObject.h:120
unsigned int TUINT
Definition Typedefs.h:8
size_t TSIZE
Definition Typedefs.h:9
float TFLOAT
Definition Typedefs.h:4
#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
Toshi::TRef< AModelInstance > AModelInstanceRef
Definition AModel.h:78
TFORCEINLINE const T & Max(const T &a, const T &b)
Definition TTRB.h:253
static constexpr void TransformVector(TVector3 &a_rOutVector, const TMatrix44 &a_rMatrix, const TVector3 &a_rVector)
Definition TMatrix44.h:280
constexpr void Scale(TFLOAT a_fScalar1, TFLOAT a_fScalar2, TFLOAT a_fScalar3)
Definition TMatrix44.h:176
constexpr TFORCEINLINE TVector3 & GetOrigin()
Definition TSphere.h:96
TVector3 & AsVector3()
Definition TVector4.h:321
TFLOAT w
Definition TVector4.h:367
TSphere BoundingSphere
Definition TModel.h:26
TINT iNumMeshes
Definition TModel.h:27
TMesh ** ppMeshes
Definition TModel.h:28
TModel * GetModel() const
Definition TModel.cpp:332
TINT32 GetLOD()
Definition TModel.cpp:313
TSkeletonInstance * GetSkeletonInstance() const
Definition TModel.cpp:337
TModelLOD & GetLOD(TUINT32 a_uiLOD)
Definition TModel.h:115
static TBOOL CullSphereToFrustumSimple(const TSphere &a_rSphere, const TPlane *a_pPlanes, TINT a_iNumPlanes)
void SetSkeletonInstance(TSkeletonInstance *a_pSkeletonInstance)
TMatrix44 & GetModelViewMatrix()
const TPlane * GetWorldPlanes()
void AddLight(TLightID a_iLightId)
TUINT GetClipFlags() const
virtual void SetModelViewMatrix(const TMatrix44 &a_rMatrix)
TRenderContext * GetCurrentContext() const
void UpdateState(TBOOL a_bForceUpdate)
const TVector3 & GetScale() const
TFORCEINLINE const TString8 & GetString8() const
Definition TPString8.h:172
TModelInstance * GetInstance()
TTransformObject & GetTransform()
static TFORCEINLINE TRenderInterface * GetSingleton()
Definition TSingleton.h:49
TString8 & MakeLower()
Definition TString8.h:87
TString8 & Format(const TCHAR *a_pcFormat,...)
Definition TString8.cpp:176
TINT Find(TCHAR character, TINT pos=0) const
Definition TString8.cpp:107
TINT Length() const
Definition TString8.h:93
void Copy(const TString8 &src, TINT size=-1)
Definition TString8.h:32
const TCHAR * GetString(TINT a_iIndex=0) const
Definition TString8.cpp:286
void SetReceivesLight(TBOOL a_bReceives)
Definition AModel.cpp:451
@ Flags_ReceivesLight
Definition AModel.h:27
@ Flags_UpdatingSkeleton
Definition AModel.h:24
TBOOL IsUpdatingSkeleton() const
Definition AModel.h:60
TBOOL DrawWithDefaultMaterials() const
Definition AModel.h:62
const Toshi::TVector4 & GetScale() const
Definition AModel.h:58
const Toshi::TPString8 & GetModelName() const
Definition AModel.cpp:479
@ ChangeEvent_DisabledSkeletonUpdate
Definition AModel.h:36
@ ChangeEvent_Visibility
Definition AModel.h:33
@ ChangeEvent_EnabledSkeletonUpdate
Definition AModel.h:35
TBOOL ReceivesLight() const
Definition AModel.h:63
void SetTransform(const Toshi::TMatrix44 &a_rcTransform)
Definition AModel.cpp:278
void SetVisible(TBOOL a_bVisible)
Definition AModel.cpp:460
TBOOL IsVisible() const
Definition AModel.h:61
Toshi::TSceneObject * GetSceneObject() const
Definition AModel.h:52
void SetClipFlags(TUINT a_uiClipFlags)
Definition AModel.h:56
void SetSkeletonUpdating(TBOOL a_bUpdating)
Definition AModel.cpp:426
void DestroyInstance(AModelInstance *a_pInstance)
Definition AModel.cpp:150
AModelInstanceRef CreateInstance()
Definition AModel.cpp:134
static void GetNameFromPath(const Toshi::TPString8 &a_FilePath, Toshi::TString8 &a_rName)
Definition AModel.cpp:189
virtual ~AModel()
Definition AModel.cpp:42
AModel(const Toshi::TPString8 &a_rName, Toshi::TTRB *a_pTRB)
Definition AModel.cpp:28
TSIZE GetNumInstances() const
Definition AModel.cpp:155
void Render(TBOOL a_bIsSomething)
Definition AModel.cpp:102
void Update(TFLOAT a_fDeltaTime)
Definition AModel.cpp:51
static Toshi::TManagedModel * Create(const Toshi::TPString8 &a_rFilePath, Toshi::TTRB *a_pTRB)
Definition AModel.cpp:161
static Toshi::TString8 GenerateInstanceName(const Toshi::TPString8 &a_FilePath)
Definition AModel.cpp:234