OpenBarnyard
 
Loading...
Searching...
No Matches
ATerrainInterface.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "ATerrainInterface.h"
3#include "Tasks/ARootTask.h"
6#include "ALoadScreen.h"
7
8#include <Toshi/T2String.h>
9
10#ifdef TOSHI_SKU_WINDOWS
13#endif
14
15//-----------------------------------------------------------------------------
16// Enables memory debugging.
17// Note: Should be the last include!
18//-----------------------------------------------------------------------------
19#include <Core/TMemoryDebugOn.h>
20
22
23ATerrainInterface::ATerrainInterface( TINT a_iUnused1, TINT a_iUnused2, TINT a_iPreloadTerrainBlockSize, TINT a_iStartVISGroup )
24{
25 m_bIsLoaded = TTRUE;
26 m_pTerrainVIS = TNULL;
27 m_iNumChunks = 16;
28 m_iPreloadTerrainBlockSize = a_iPreloadTerrainBlockSize;
29
30 m_pJobs = new JobSlot[ NUM_TOTAL_JOBS ];
31 auto pJobSlot = &m_pJobs[ 0 ];
32
33 for ( TUINT i = 0; i < MAX_NUM_MODEL_LOADER_JOBS; i++ )
34 {
35 pJobSlot->SetNodeValue( &m_aModelLoaderJobs[ i ] );
36 m_FreeModelLoaderJobs.PushFront( pJobSlot );
37 pJobSlot++;
38 }
39
40 for ( TUINT i = 0; i < MAX_NUM_KEYLIB_LOADER_JOBS; i++ )
41 {
42 pJobSlot->SetNodeValue( &m_aKeylibLoaderJobs[ i ] );
43 m_FreeKeylibLoaderJobs.PushFront( pJobSlot );
44 pJobSlot++;
45 }
46
47 for ( TUINT i = 0; i < MAX_NUM_MATLIB_LOADER_JOBS; i++ )
48 {
49 pJobSlot->SetNodeValue( &m_aMatlibLoaderJobs[ i ] );
50 m_FreeMatlibLoaderJobs.PushFront( pJobSlot );
51 pJobSlot++;
52 }
53
54 for ( TUINT i = 0; i < MAX_NUM_SECTION_LOADER_JOBS; i++ )
55 {
56 pJobSlot->SetNodeValue( &m_aSectionDoneJobs[ i ] );
57 m_FreeSectionLoaderJobs.PushFront( pJobSlot );
58 pJobSlot++;
59 }
60
61 for ( TUINT i = 0; i < MAX_NUM_TRB_LOADER_JOBS; i++ )
62 {
63 pJobSlot->SetNodeValue( &m_aTRBLoaderJobs[ i ] );
64 m_FreeTRBLoaderJobs.PushFront( pJobSlot );
65 pJobSlot++;
66 }
67
68 for ( TUINT i = 0; i < MAX_NUM_SKELETON_LOADER_JOBS; i++ )
69 {
70 pJobSlot->SetNodeValue( &m_aSkeletonDoneJobs[ i ] );
71 m_FreeSkeletonLoaderJobs.PushFront( pJobSlot );
72 pJobSlot++;
73 }
74
75 for ( TUINT i = 0; i < MAX_NUM_COLLISION_LOADER_JOBS; i++ )
76 {
77 pJobSlot->SetNodeValue( &m_aCollisionDoneJobs[ i ] );
78 m_FreeCollisionLoaderJobs.PushFront( pJobSlot );
79 pJobSlot++;
80 }
81
82 TTODO( "Call FUN_00619040() and initialise some other values" );
83 m_iCurrentSection = a_iStartVISGroup;
84 m_iPreviousSection = -1;
85 m_bUnused4 = TFALSE;
86 // ...
87 m_fUnused3 = 0.0f;
88 m_cbOnCollsionModelLoaded = TNULL;
89 m_cbOnModelLoaded = TNULL;
90 m_cbOnVISGroupChanged = TNULL;
91 m_fnGetCurrentVISGroup = GetCurrentSectionID;
92}
93
95{
96 TIMPLEMENT();
97 m_bIsLoaded = TFALSE;
98
99 m_UsedModelLoaderJobs.Clear();
100 m_FreeModelLoaderJobs.Clear();
101 m_UsedUnknownLoaderJobs.Clear();
102 m_FreeUnknownLoaderJobs.Clear();
103 m_UsedSectionLoaderJobs.Clear();
104 m_FreeSectionLoaderJobs.Clear();
105 m_UsedKeylibLoaderJobs.Clear();
106 m_FreeKeylibLoaderJobs.Clear();
107 m_UsedMatlibLoaderJobs.Clear();
108 m_FreeMatlibLoaderJobs.Clear();
109 m_UsedTRBLoaderJobs.Clear();
110 m_FreeTRBLoaderJobs.Clear();
111 m_UsedSkeletonLoaderJobs.Clear();
112 m_FreeSkeletonLoaderJobs.Clear();
113 m_UsedCollisionLoaderJobs.Clear();
114 m_FreeCollisionLoaderJobs.Clear();
115
116 delete[] m_pJobs;
117}
118
120{
121 if ( !m_pTerrainVIS ) return;
122
123 if ( m_fnGetCurrentVISGroup )
124 {
125 TINT iCurrentGroup = m_fnGetCurrentVISGroup();
126
127 if ( iCurrentGroup != -1 )
128 {
129 m_iCurrentSection = iCurrentGroup;
130 }
131 }
132
133 if ( m_iCurrentSection >= 0 )
134 {
135 if ( m_iPreviousSection != m_iCurrentSection )
136 {
139
142
143 if ( m_cbOnVISGroupChanged )
144 {
145 auto pPrevious = m_iPreviousSection >= 0 ? &m_pTerrainVIS->m_pSections[ m_iPreviousSection ] : TNULL;
146 auto pCurrent = m_iCurrentSection >= 0 ? &m_pTerrainVIS->m_pSections[ m_iCurrentSection ] : TNULL;
147
148 m_cbOnVISGroupChanged( pPrevious, pCurrent );
149 }
150
151 m_iPreviousSection = m_iCurrentSection;
153 }
154
155 if ( m_bIsLoaded && !IsLoaded() )
156 {
157 TFIXME( "Create and push ATerrainLoadingStallState if needed" );
158 }
159
160 TBOOL bSkipLoadingModels = TFALSE;
161
162 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
163 {
164 if ( m_pTerrainVIS->m_pSections[ i ].IsLODLoading( ATerrainLODType_High ) ||
165 m_pTerrainVIS->m_pSections[ i ].IsLODLoading( ATerrainLODType_Low ) )
166 {
167 // There are already some models loading, don't create any new jobs
168 bSkipLoadingModels = TTRUE;
169 break;
170 }
171 }
172
173 if ( !bSkipLoadingModels )
174 {
175 if ( HasAnyLODsQueued() )
176 {
177 auto pGroups = m_pTerrainVIS->m_pSections;
178
179 if ( m_pOrderDVIS )
180 {
181 // Use precomputed order of queued groups to load
182 auto pDVIS = &m_pOrderDVIS[ m_iCurrentSection ];
183
184 for ( TINT i = 0; i < pDVIS->iCount; i++ )
185 {
186 auto uiGroupIndex = pDVIS->pInfo[ i ].uiGroupIndex;
187 auto eLODType = pDVIS->pInfo[ i ].eLODType;
188
189 if ( pGroups[ uiGroupIndex ].IsLODQueued( eLODType ) )
190 {
191 pGroups[ uiGroupIndex ].LoadModels( eLODType );
192 break;
193 }
194 }
195 }
196 else
197 {
198 // Brute force order of queued groups to load
199 if ( pGroups[ m_iCurrentSection ].IsLODQueued( ATerrainLODType_High ) )
200 {
201 pGroups[ m_iCurrentSection ].LoadModels( ATerrainLODType_High );
202 }
203 else
204 {
205 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
206 {
207 if ( pGroups[ i ].IsLODQueued( ATerrainLODType_High ) )
208 {
209 pGroups[ i ].LoadModels( ATerrainLODType_High );
210 break;
211 }
212 else if ( pGroups[ i ].IsLODQueued( ATerrainLODType_Low ) )
213 {
214 pGroups[ i ].LoadModels( ATerrainLODType_Low );
215 break;
216 }
217 }
218 }
219 }
220 }
221 }
222
223 TFIXME( "Restore value of m_fnGetCurrentVISGroup if it was saved" );
224
225 // Wait till queued LODs are ready
226 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
227 {
228 if ( m_pTerrainVIS->m_pSections[ i ].IsLODQueued( ATerrainLODType_High ) ||
229 m_pTerrainVIS->m_pSections[ i ].IsLODQueued( ATerrainLODType_Low ) )
230 {
231 FlushJobs();
232 return;
233 }
234 }
235
236 // Wait till all LODs are loaded
237 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
238 {
239 if ( m_pTerrainVIS->m_pSections[ i ].IsLODLoading( ATerrainLODType_High ) ||
240 m_pTerrainVIS->m_pSections[ i ].IsLODLoading( ATerrainLODType_Low ) )
241 {
242 FlushJobs();
243 return;
244 }
245 }
246
247 if ( m_pOrderDVIS )
248 {
249 auto pDVIS = &m_pOrderDVIS[ m_iCurrentSection ];
250
251 for ( TINT i = 0; i < pDVIS->iCount; i++ )
252 {
253 auto pInfo = &pDVIS->pInfo[ i ];
254 auto pGroup = &m_pTerrainVIS->m_pSections[ pInfo->uiGroupIndex ];
255
256 if ( pGroup->IsLODLoaded( pInfo->eLODType ) && !pGroup->IsLODEmpty( pInfo->eLODType ) )
257 {
259 pGroup->DestroyLOD( pInfo->eLODType );
261 }
262 }
263 }
264 }
265
266 FlushJobs();
267}
268
269static TFLOAT s_ShadowColor2Multiplier = 0.6f;
270
272{
273 m_pTerrainVIS->m_pPersistantTerrainBlock->UpdateLastAccessTime();
274
275 auto pRenderContext = TRenderInterface::GetSingleton()->GetCurrentContext();
276 auto pCameraObject = pRenderContext->GetCameraObject();
277
278 if ( pCameraObject )
279 {
280 auto pWorldShader = TDYNAMICCAST( AWorldShaderHAL, AWorldShader::GetSingleton() );
281
282 m_DefaultShadowColor = pWorldShader->GetShadowColour();
283 m_DefaultAmbientColor = pWorldShader->GetAmbientColour();
284
285 m_LitShadowColor.x = 0.5f;
286 m_LitShadowColor.y = 0.5f;
287 m_LitShadowColor.z = 0.3254902f;
288 m_LitShadowColor.w = 1.0f;
289 m_LitShadowColor.Multiply( s_ShadowColor2Multiplier );
290
291 m_LitAmbientColor = m_LitShadowColor;
292 m_bUnused4 = TFALSE;
293 m_fUnused3 = 1.0f;
294 m_bUnused4 = TTRUE;
295
296 auto pTerrainVIS = m_pTerrainVIS;
297
298 if ( TNULL != pTerrainVIS )
299 {
300 // Reset current section if it is out of range
301 if ( pTerrainVIS->m_iNumSections <= m_iCurrentSection || m_iCurrentSection < 0 )
302 {
303 m_iCurrentSection = 0;
304 }
305
306 auto pSections = pTerrainVIS->m_pSections;
307 auto iCurrentSection = m_iCurrentSection;
308 auto pCurrentSection = &pSections[ iCurrentSection ];
309
310 if ( TNULL == m_pOrderDVIS )
311 {
312 pCurrentSection->Draw( ATerrainLODType_High );
313 }
314
315 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
316 {
317 ATerrainLODType eSectionVisibility = pCurrentSection->m_pVisibility[ i ];
318
319 if ( eSectionVisibility != ATerrainLODType_None )
320 {
321 pSections[ i ].Draw( eSectionVisibility );
322 }
323 }
324 }
325 }
326}
327
329{
330 if ( m_pTerrainVIS == TNULL )
331 {
332 return TTRUE;
333 }
334
335 if ( m_pTerrainVIS->GetLocatorList() && m_pTerrainVIS->GetLocatorList()->GetTRB() )
336 {
337 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
338 {
339 if ( HASANYFLAG( m_pTerrainVIS->m_pSections[ i ].m_eFlags, 0xF3C ) )
340 {
341 return TFALSE;
342 }
343 }
344
345 return TTRUE;
346 }
347
348 return TFALSE;
349}
350
351void ATerrainInterface::LoadFromFile( const TCHAR* a_szFilePath, TBOOL a_bLoadLater, TBOOL a_bStreamCollision )
352{
353 TFIXME( "Do something with ATerrainSectionHudElement" );
354
355 m_bIsLoaded = TFALSE;
356
357 m_VISTRB.Close();
358 m_VISTRB.Load( a_szFilePath, 0 );
359
360 m_pTerrainVIS = m_VISTRB.CastSymbol<ATerrainVIS>( "terrainvis" );
361 m_pOrderDVIS = m_VISTRB.CastSymbol<ATerrainOrderDVIS>( "orderdvis" );
362
363 if ( m_VISTRB.GetSymbolAddress( "preloadcollision" ) )
364 {
365 // We won't stream collision models if there's any preload collision
366 a_bStreamCollision = TFALSE;
367 m_iPreloadTerrainBlockSize = m_pTerrainVIS->m_uiPersistantTerrainBlockSize;
368 }
369
370 m_VISTRB.DeleteSymbolTable();
371
372 if ( !a_bStreamCollision )
373 {
374 m_pTerrainVIS->m_uiPersistantTerrainBlockSize = m_iPreloadTerrainBlockSize;
375 }
376
377 if ( m_pTerrainVIS->m_uiPersistantTerrainBlockSize > 0 )
378 {
379 m_pTerrainVIS->m_pPersistantTerrainBlock = new ATerrainLODBlock(
380 m_pTerrainVIS->m_uiPersistantTerrainBlockSize,
381 "Terrain_Persistant"
382 );
383 }
384
385 // Create HighLOD blocks
386 if ( m_pTerrainVIS->m_iNumHighBlocks > 0 )
387 {
388 m_pTerrainVIS->m_ppHighBlocks = new ATerrainLODBlock*[ m_pTerrainVIS->m_iNumHighBlocks ];
389
390 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumHighBlocks; i++ )
391 {
392 TCHAR szBlockName[ 64 ];
393 TStringManager::String8Format( szBlockName, sizeof( szBlockName ), "Terrain_HighLOD_Block%d", i );
394
395 m_pTerrainVIS->m_ppHighBlocks[ i ] = new ATerrainLODBlock(
396 m_pTerrainVIS->m_uiHighBlockSize,
397 szBlockName
398 );
399 }
400 }
401
402 // Create LowLOD blocks
403 if ( m_pTerrainVIS->m_iNumLowBlocks > 0 )
404 {
405 m_pTerrainVIS->m_ppLowBlocks = new ATerrainLODBlock*[ m_pTerrainVIS->m_iNumLowBlocks ];
406
407 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumLowBlocks; i++ )
408 {
409 TCHAR szBlockName[ 64 ];
410 TStringManager::String8Format( szBlockName, sizeof( szBlockName ), "Terrain_LowLOD_Block%d", i );
411
412 m_pTerrainVIS->m_ppLowBlocks[ i ] = new ATerrainLODBlock(
413 m_pTerrainVIS->m_uiLowBlockSize,
414 szBlockName
415 );
416 }
417 }
418
419 m_pTerrainVIS->LoadSkeleton();
420
421 // Load global matlib if it is specified
422 if ( *m_pTerrainVIS->m_szMatLibrary != '\0' )
423 {
424 auto pMatlibJob = GetFreeMatlibLoaderJob();
425 auto pPersitantBlock = m_pTerrainVIS->m_pPersistantTerrainBlock;
426
427 auto pTRB = new ( pPersitantBlock->GetMemBlock() ) TTRB();
428 m_pTerrainVIS->m_pMaterialLibraryTRB = pTRB;
429 pPersitantBlock->SetupTRB( pTRB, pPersitantBlock );
430
431 pMatlibJob->InitJob(
432 m_pTerrainVIS->m_szMatLibrary,
433 m_pTerrainVIS->m_pMaterialLibraryTRB,
434 m_pTerrainVIS->m_pMaterialLibrary,
435 pPersitantBlock->GetMemBlock()
436 );
437
438 AAssetStreaming::GetSingleton()->AddMainThreadJob( pMatlibJob );
439 }
440
441 m_bStreamCollision = a_bStreamCollision;
442
443 // If collision is not streamed, create jobs to load it for every section
444 if ( !a_bStreamCollision )
445 {
446 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
447 {
448 m_pTerrainVIS->m_pSections[ i ].LoadCollision();
449 }
450 }
451
452 // Wait until all assets are loaded
453 if ( !a_bLoadLater )
454 {
455 while ( AAssetStreaming::GetSingleton()->HasActiveJobs() )
456 {
457 AAssetStreaming::GetSingleton()->Update();
458
459#ifndef BARNYARD_COMMUNITY_PATCH
460 ThreadSleep( 20 );
461#endif // BARNYARD_COMMUNITY_PATCH
462 }
463
465 }
466
467 m_bIsLoaded = TTRUE;
468}
469
471{
473
474 while ( TTRUE )
475 {
476 Update();
477
478 if ( IsLoaded() ) return;
479 TRenderInterface::GetSingleton()->Update( 1.0f / 1000.0f );
480 AAssetStreaming::GetSingleton()->Update();
481
482#ifndef BARNYARD_COMMUNITY_PATCH
483 ThreadSleep( 20 );
484#endif // BARNYARD_COMMUNITY_PATCH
485 }
486}
487
489{
490 TVALIDPTR( a_pModelData );
491
492 if ( a_pModelData->IsLinked() )
493 {
494 m_llModelNodes.Erase( a_pModelData );
495 }
496
497 if ( a_pModelData )
498 {
499 delete a_pModelData;
500 }
501}
502
504{
505 TINT iNumBlocks;
506 ATerrainLODBlock** ppBlocks;
507
508 if ( a_eLODType == ATerrainLODType_High )
509 {
510 iNumBlocks = m_pTerrainVIS->m_iNumHighBlocks;
511 ppBlocks = m_pTerrainVIS->m_ppHighBlocks;
512 }
513 else
514 {
515 iNumBlocks = m_pTerrainVIS->m_iNumLowBlocks;
516 ppBlocks = m_pTerrainVIS->m_ppLowBlocks;
517 }
518
519 auto pCurrentVISGroup = m_pTerrainVIS->m_pSections + m_iCurrentSection;
520
521 for ( TINT i = 0; i < iNumBlocks; i++ )
522 {
523 auto pBlock = ppBlocks[ i ];
524 pBlock->SetUnused();
525
526 if ( a_eLODType == ATerrainLODType_High && pBlock->m_pVISGroup == pCurrentVISGroup )
527 {
528 pBlock->SetUsed();
529 }
530 else
531 {
532 auto pVIS = m_pTerrainVIS;
533
534 for ( TINT k = 0; k < pVIS->m_iNumSections; k++ )
535 {
536 if ( pCurrentVISGroup->m_pVisibility[ k ] == a_eLODType &&
537 pBlock->m_pVISGroup == &pVIS->m_pSections[ k ] )
538 {
539 pBlock->SetUsed();
540 }
541 }
542 }
543 }
544}
545
547{
548 TASSERT( m_iCurrentSection != -1 );
549
550 auto pCurrentGroup = &m_pTerrainVIS->m_pSections[ m_iCurrentSection ];
551
552 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
553 {
554 auto eLODType = pCurrentGroup->m_pVisibility[ i ];
555
556 if ( eLODType > ATerrainLODType_None )
557 {
558 auto pGroup = &m_pTerrainVIS->m_pSections[ i ];
559
560 if ( ( pGroup->m_eFlags & ( 21 << eLODType ) ) == 0 )
561 {
562 pGroup->SetLODQueued( eLODType, TTRUE );
563 }
564 }
565 }
566
567 if ( !HASANYFLAG(
568 pCurrentGroup->m_eFlags,
570 ) )
571 {
572 pCurrentGroup->SetLODQueued( ATerrainLODType_High, TTRUE );
573 }
574}
575
577{
578 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
579 {
580 m_pTerrainVIS->m_pSections[ i ].RemoveFromStreamingQueue();
581 }
582}
583
585{
586 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
587 {
588 auto pGroup = &m_pTerrainVIS->m_pSections[ i ];
589
591 {
592 return TTRUE;
593 }
594 }
595
596 return TFALSE;
597}
598
600{
601 TINT iNumBlocks;
602 ATerrainLODBlock** ppBlocks;
603
604 if ( a_eLODType == ATerrainLODType_High )
605 {
606 iNumBlocks = m_pTerrainVIS->m_iNumHighBlocks;
607 ppBlocks = m_pTerrainVIS->m_ppHighBlocks;
608 }
609 else
610 {
611 iNumBlocks = m_pTerrainVIS->m_iNumLowBlocks;
612 ppBlocks = m_pTerrainVIS->m_ppLowBlocks;
613 }
614
615 TFLOAT fMinAccessTime = TMath::MAXFLOAT;
616 TINT iPrevFoundIndex = -1;
617 TINT iFoundIndex;
618
619 for ( TINT i = 0; i < iNumBlocks; i++ )
620 {
621 auto pBlock = ppBlocks[ i ];
622 iFoundIndex = iPrevFoundIndex;
623
624 if ( !pBlock->IsUsed() )
625 {
626 iFoundIndex = i;
627 if ( pBlock->m_pVISGroup == TNULL ) break;
628
629 iFoundIndex = iPrevFoundIndex;
630 if ( !pBlock->m_pVISGroup->IsLODLoading( a_eLODType ) )
631 {
632 iFoundIndex = i;
633 if ( pBlock->m_pVISGroup = TNULL ) break;
634
635 iFoundIndex = iPrevFoundIndex;
636 if ( pBlock->m_fLastAccessTime < fMinAccessTime )
637 {
638 fMinAccessTime = pBlock->m_fLastAccessTime;
639 iFoundIndex = i;
640 }
641 }
642 }
643
644 iPrevFoundIndex = iFoundIndex;
645 }
646
647 if ( iFoundIndex >= 0 )
648 {
649 auto pBlock = ppBlocks[ iFoundIndex ];
650 auto pVISGroup = pBlock->m_pVISGroup;
651
652 if ( pVISGroup )
653 {
654 if ( pVISGroup->IsLODEmpty( pBlock->m_eLODType ) )
655 {
656 pVISGroup->SetLODEmpty( pBlock->m_eLODType, TFALSE );
657 return TNULL;
658 }
659
660 if ( pVISGroup )
661 {
662 if ( ( pVISGroup->m_eFlags & ( 21 << a_eLODType ) ) != 0 )
663 {
664 if ( pVISGroup->IsMatLibLoaded( pBlock->m_eLODType ) )
665 {
666 pVISGroup->SetLODEmpty( pBlock->m_eLODType, TFALSE );
667
668 if ( pBlock->m_pVISGroup )
669 {
670 pBlock->m_pVISGroup->UnloadMatlib( pBlock->m_eLODType );
671 }
672 }
673 else if ( pBlock->m_pVISGroup )
674 {
675 pBlock->m_pVISGroup->DestroyLOD( pBlock->m_eLODType );
676 }
677
678 return TNULL;
679 }
680
681 if ( pVISGroup )
682 {
683 pVISGroup->DestroyLOD( pBlock->m_eLODType );
684 }
685 }
686 }
687
688 pBlock->Assign( a_pVISGroup, a_eLODType );
689 return pBlock;
690 }
691
692 return TNULL;
693}
694
695// $Barnyard: FUNCTION 005e8d70
696void ATerrainInterface::GetLocatorTransform( const TCHAR* a_pszLocatorName, TMatrix44& a_rOutTransform )
697{
698 ATerrainLocatorList* pLocatorManager = GetLocatorList();
699
700 ATerrainLocator* pLocator = pLocatorManager->FindLocator( a_pszLocatorName );
701 TASSERT( pLocator != TNULL );
702
703 // Get transform of the locator
704 TMatrix44 matLocator;
705 pLocator->GetMatrix( matLocator );
706
707 // Get locators global transform
708 pLocatorManager->GetWorldTransform().GetLocalMatrixImp( a_rOutTransform );
709
710 // Transform locator by the global transform
711 a_rOutTransform.Multiply( matLocator );
712}
713
714// $Barnyard: FUNCTION 005e8b60
716{
717 ATerrainLocatorList* pLocatorManager = GetLocatorList();
718
719 ATerrainLocator* pLocator = pLocatorManager->FindLocator( a_pszLocatorName );
720 TASSERT( pLocator != TNULL );
721
722 // Get transform of the locator
723 TMatrix44 matLocator;
724 pLocator->GetMatrix( matLocator );
725
726 // Get locators global transform and transform the locator
727 TMatrix44 matTransformed;
728 pLocatorManager->GetWorldTransform().GetLocalMatrixImp( matTransformed );
729 matTransformed.Multiply( matLocator );
730
731 return matTransformed.AsBasisVector4( BASISVECTOR_TRANSLATION );
732}
733
734// $Barnyard: FUNCTION 005e8bf0
735void ATerrainInterface::GetLocatorPosAndRot( const TCHAR* a_pszLocatorName, Toshi::TVector4& a_rOutPosition, Toshi::TQuaternion& a_rOutRotation )
736{
737 ATerrainLocatorList* pLocatorManager = GetLocatorList();
738
739 ATerrainLocator* pLocator = pLocatorManager->FindLocator( a_pszLocatorName );
740 TASSERT( pLocator != TNULL );
741
742 // Get transform of the locator
743 TMatrix44 matLocator;
744 pLocator->GetMatrix( matLocator );
745
746 // Get locators global transform and transform the locator
747 TMatrix44 matTransformed;
748 pLocatorManager->GetWorldTransform().GetLocalMatrixImp( matTransformed );
749 matTransformed.Multiply( matLocator );
750
751 TVector3& vecUp = matTransformed.AsBasisVector3( BASISVECTOR_UP );
752 a_rOutRotation = TQuaternion( -vecUp.x, -vecUp.y, -vecUp.z, 1.0f );
753 a_rOutPosition = matTransformed.AsBasisVector4( BASISVECTOR_TRANSLATION );
754}
755
756// $Barnyard: FUNCTION 005e82f0
758{
759 if ( !m_pTerrainVIS )
760 return TNULL;
761
762 return GetLocatorList()->FindLocator( a_pszLocatorName );
763}
764
766{
767 TASSERT( m_FreeTRBLoaderJobs.Size() > 0, "No free ATRBLoaderJobs left!" );
768
769 if ( m_FreeTRBLoaderJobs.Size() > 0 )
770 {
771 auto pTRBJobSlot = m_FreeTRBLoaderJobs.PopFront();
772 m_UsedTRBLoaderJobs.PushFront( pTRBJobSlot );
773
774 return TSTATICCAST( ATRBLoaderJob, pTRBJobSlot->GetNodeValue() );
775 }
776 else
777 {
778 return TNULL;
779 }
780}
781
783{
784 TASSERT( m_FreeSkeletonLoaderJobs.Size() > 0, "No free ASkeletonDoneJobs left!" );
785
786 if ( m_FreeSkeletonLoaderJobs.Size() > 0 )
787 {
788 auto pTRBJobSlot = m_FreeSkeletonLoaderJobs.PopFront();
789 m_UsedSkeletonLoaderJobs.PushFront( pTRBJobSlot );
790
791 return TSTATICCAST( ASkeletonDoneJob, pTRBJobSlot->GetNodeValue() );
792 }
793 else
794 {
795 return TNULL;
796 }
797}
798
800{
801 TASSERT( m_FreeMatlibLoaderJobs.Size() > 0, "No free AMatlibLoaderJobs left!" );
802
803 if ( m_FreeMatlibLoaderJobs.Size() > 0 )
804 {
805 auto pTRBJobSlot = m_FreeMatlibLoaderJobs.PopFront();
806 m_UsedMatlibLoaderJobs.PushFront( pTRBJobSlot );
807
808 return TSTATICCAST( AMatLibLoaderJob, pTRBJobSlot->GetNodeValue() );
809 }
810 else
811 {
812 return TNULL;
813 }
814}
815
817{
818 TASSERT( m_FreeCollisionLoaderJobs.Size() > 0, "No free ACollisionDoneJob left!" );
819
820 if ( m_FreeCollisionLoaderJobs.Size() > 0 )
821 {
822 auto pTRBJobSlot = m_FreeCollisionLoaderJobs.PopFront();
823 m_UsedCollisionLoaderJobs.PushFront( pTRBJobSlot );
824
825 return TSTATICCAST( ACollisionDoneJob, pTRBJobSlot->GetNodeValue() );
826 }
827 else
828 {
829 return TNULL;
830 }
831}
832
834{
835 TASSERT( m_FreeModelLoaderJobs.Size() > 0, "No free AModelLoaderJob left!" );
836
837 if ( m_FreeModelLoaderJobs.Size() > 0 )
838 {
839 auto pTRBJobSlot = m_FreeModelLoaderJobs.PopFront();
840 m_UsedModelLoaderJobs.PushFront( pTRBJobSlot );
841
842 return TSTATICCAST( AModelLoaderJob, pTRBJobSlot->GetNodeValue() );
843 }
844 else
845 {
846 return TNULL;
847 }
848}
849
851{
852 TASSERT( m_FreeSectionLoaderJobs.Size() > 0, "No free ASectionDoneJob left!" );
853
854 if ( m_FreeSectionLoaderJobs.Size() > 0 )
855 {
856 auto pTRBJobSlot = m_FreeSectionLoaderJobs.PopFront();
857 m_UsedSectionLoaderJobs.PushFront( pTRBJobSlot );
858
859 return TSTATICCAST( ASectionDoneJob, pTRBJobSlot->GetNodeValue() );
860 }
861 else
862 {
863 return TNULL;
864 }
865}
866
867void ATerrainInterface::FlushJobs()
868{
869 MoveAllFinishedJobs( m_FreeModelLoaderJobs, m_UsedModelLoaderJobs );
870 MoveAllFinishedJobs( m_FreeUnknownLoaderJobs, m_UsedUnknownLoaderJobs );
871 MoveAllFinishedJobs( m_FreeSectionLoaderJobs, m_UsedSectionLoaderJobs );
872 MoveAllFinishedJobs( m_FreeKeylibLoaderJobs, m_UsedKeylibLoaderJobs );
873 MoveAllFinishedJobs( m_FreeMatlibLoaderJobs, m_UsedMatlibLoaderJobs );
874 MoveAllFinishedJobs( m_FreeTRBLoaderJobs, m_UsedTRBLoaderJobs );
875 MoveAllFinishedJobs( m_FreeSkeletonLoaderJobs, m_UsedSkeletonLoaderJobs );
876 MoveAllFinishedJobs( m_FreeCollisionLoaderJobs, m_UsedCollisionLoaderJobs );
877}
878
879void ATerrainInterface::MoveAllFinishedJobs( Toshi::T2SList<JobSlot>& a_rFreeJobs, Toshi::T2SList<JobSlot>& a_rUsedJobs )
880{
881 for ( auto it = a_rUsedJobs.Begin(); it != a_rUsedJobs.End(); )
882 {
883 auto pNext = it.Next();
884
885 if ( it->GetNodeValue()->IsFinished() )
886 {
887 a_rUsedJobs.Erase( it );
888 a_rFreeJobs.PushFront( it );
889 }
890
891 it = pNext;
892 }
893}
894
895#ifdef TOSHI_SKU_WINDOWS
896
897static void RenderWorldWin( TModelInstance* a_pModelInstance )
898{
899 auto pSkeletonInstance = a_pModelInstance->GetSkeletonInstance();
900
901 if ( TNULL != pSkeletonInstance )
902 {
903 pSkeletonInstance->UpdateState( TFALSE );
904 }
905
907
908 auto pModel = a_pModelInstance->GetModel();
909 auto pLOD = &pModel->GetLOD( a_pModelInstance->GetLOD() );
910
911 for ( TINT i = 0; pLOD->iNumMeshes; i++ )
912 {
913 TVALIDPTR( pLOD->ppMeshes[ i ] );
914 pLOD->ppMeshes[ i ]->Render();
915 }
916}
917
918static void RenderNothing( TModelInstance* a_pModelInstance )
919{
920}
921
922static void RenderCellMeshDefault( CellMeshSphere* a_pMeshSphere, RenderData* a_pRenderData )
923{
924 TVALIDPTR( a_pMeshSphere );
925 a_pMeshSphere->m_pCellMesh->pMesh->Render();
926}
927
928static void RenderCellMeshWin( CellMeshSphere* a_pMeshSphere, RenderData* a_pRenderData )
929{
930 TVALIDPTR( a_pMeshSphere );
931 TTODO( "Calculate real lighting colour" );
932
933 TVector4 colour;
934 colour.x = 0.3f;
935 colour.y = 0.3f;
936 colour.z = 0.1952941f;
937 colour.w = 1.0f;
938
939 TDYNAMICCAST( AWorldShaderHAL, AWorldShader::GetSingleton() )->SetColours( colour, colour );
940 a_pMeshSphere->m_pCellMesh->pMesh->Render();
941}
942
943static void RenderWorldVisWin( TModelInstance* a_pModelInstance, void* a_pModelNode )
944{
945 auto pModel = a_pModelInstance->GetModel();
946 auto pModelNode = TSTATICCAST( ATerrainSection::ModelNode, a_pModelNode );
947
948 if ( TNULL != pModel->GetTRB() )
949 {
950 auto pWorldDatabase = pModel->CastSymbol<WorldDatabase>( "Database" );
951 TASSERT( TNULL != pWorldDatabase );
952
953 if ( TNULL != pWorldDatabase )
954 {
955 auto pRenderContext = TRenderInterface::GetSingleton()->GetCurrentContext();
956
957 // Save alpha blend value to restore it after rendering
958 TFLOAT fAlphaBlend = pRenderContext->GetAlphaBlend();
959
960 TMatrix44 projection;
961 pRenderContext->ComputePerspectiveProjection(
962 projection,
963 pRenderContext->GetViewportParameters(),
964 pRenderContext->GetProjectionParams()
965 );
966
967 TMatrix44 modelView = pRenderContext->GetModelViewMatrix();
968
969 const TBOOL bIsDefaultRenderer =
970 ( pModelNode->m_WorldVis.m_pfnRenderCallback == RenderCellMeshDefault );
971
972 // If using lighting, specify method that calculates lighting
973 if ( bIsDefaultRenderer && pModelNode->IsUsingLighting() )
974 pModelNode->m_WorldVis.m_pfnRenderCallback = RenderCellMeshWin;
975
976 // Build visibility and render
977 pModelNode->m_WorldVis.Reset();
978 pModelNode->m_WorldVis.Build( modelView, projection, 0 );
979 pModelNode->m_WorldVis.Render( modelView );
980
981 // Set render method back to default
982 if ( bIsDefaultRenderer )
983 pModelNode->m_WorldVis.m_pfnRenderCallback = RenderCellMeshDefault;
984
985 pRenderContext->SetAlphaBlend( fAlphaBlend );
986 }
987 }
988}
989
990#endif // TOSHI_SKU_WINDOWS
991
992ATerrainSection::ModelNode* ATerrainInterface::CreateModelInstance( ATerrainSection::ModelNode* a_pModelNode, const char* a_szModelName, const char* a_szType )
993{
994 // Make sure model is created
995 auto pModel = a_pModelNode->m_ModelRef.GetModel();
996 if ( !pModel || !pModel->IsCreated() )
997 {
998 a_pModelNode->m_ModelRef.Create(
999 a_szModelName,
1001 );
1002 }
1003
1004 auto pInstance = a_pModelNode->m_ModelRef.CreateSceneObject();
1005 auto pInstanceTransform = &pInstance->GetTransform();
1006
1007 pInstanceTransform->SetEuler( TVector3( 1.570796f, 0.0f, 0.0f ) );
1008 pInstanceTransform->SetTranslate( TVector3::VEC_ZERO );
1009
1010 TMatrix44 collisionLocalMatrix;
1011 pInstanceTransform->GetLocalMatrixImp( collisionLocalMatrix );
1012 pInstanceTransform->SetMatrix( collisionLocalMatrix );
1013
1014 a_pModelNode->m_pSceneObject = pInstance;
1015
1016 pInstance->GetSomeVector1().x = 1.0f;
1017 pInstance->GetSomeVector1().y = 1.0f;
1018 pInstance->GetSomeVector2().x = 10000000.0f;
1019 pInstance->GetSomeVector2().y = 10000001.0f;
1020 pInstance->EnableSkeletonUpdate();
1021 pInstance->EnableUnknown1();
1022
1023 TTODO( "Create collision model set" );
1024
1025 auto pModelInstance = pInstance->GetInstance();
1026 pModel = pModelInstance->GetModel();
1027
1028 auto pWorldDatabase = pModel->CastSymbol<WorldDatabase>( "Database" );
1029
1030 if ( TNULL == pWorldDatabase )
1031 {
1032 // Render as a simple model
1033 pModelInstance->SetPreRenderCallback( RenderWorldWin );
1034 }
1035 else
1036 {
1037 // Render WorldVIS
1038 auto& rLOD = pModel->GetLOD( 0 );
1039
1040 if ( rLOD.iNumMeshes < 1 )
1041 {
1042 // Nothing to render here
1043 pModelInstance->SetPreRenderCallback( RenderNothing );
1044 }
1045 else
1046 {
1047 pModelInstance->SetCustomRenderMethod( RenderWorldVisWin, a_pModelNode );
1048 a_pModelNode->m_WorldVis.Create( pWorldDatabase->m_ppWorlds[ 0 ] );
1049
1050 TBOOL bIsWorldMesh = rLOD.ppMeshes[ 0 ]->IsA( &TGetClass( AWorldMesh ) );
1051
1052 if ( bIsWorldMesh )
1053 {
1054 a_pModelNode->m_WorldVis.m_pfnRenderCallback = RenderCellMeshDefault;
1055 TTODO( "Setup materials" );
1056 }
1057 else
1058 {
1059 a_pModelNode->m_WorldVis.m_pfnRenderCallback = RenderCellMeshDefault;
1060 }
1061 }
1062 }
1063
1064 if ( TNULL != a_szType )
1065 {
1068 }
1069
1070 m_llModelNodes.PushBack( a_pModelNode );
1071 a_pModelNode->m_bCreated = TTRUE;
1072 return a_pModelNode;
1073}
1074
1076{
1077 if ( m_iCurrentSection != m_iPreviousSection && m_iPreviousSection >= 0 )
1078 {
1079 for ( TINT i = 0; i < m_pTerrainVIS->m_iNumSections; i++ )
1080 {
1081 auto pGroup = &m_pTerrainVIS->m_pSections[ i ];
1082
1084 {
1085 if ( i < 0 ) return;
1086 if ( pGroup->m_pVisibility[ i ] == ( ( pGroup->m_eFlags >> 2 ) - 1 ) % ATerrainLODType_NUMOF ) return;
1087 if ( i == m_iCurrentSection ) return;
1088
1089 AAssetStreaming::GetSingleton()->CancelAllJobs();
1090 return;
1091 }
1092 }
1093 }
1094}
1095
1096void ATerrainInterface::UpdateNightMaterials()
1097{
1098 TIMPLEMENT();
1099}
1100
1101TINT ATerrainInterface::GetCurrentSectionID()
1102{
1103 TIMPLEMENT();
1104 return 0;
1105}
1106
1107TINT ATerrainInterface::GetPersistantSectionID()
1108{
1109 return ms_iPersistantVISGroupIndex;
1110}
@ BASISVECTOR_TRANSLATION
Definition TMatrix44.h:28
@ BASISVECTOR_UP
Definition TMatrix44.h:26
#define TIMPLEMENT()
Definition Defines.h:136
#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 TTODO(DESC)
Definition Defines.h:134
#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
unsigned int TUINT
Definition Typedefs.h:8
char TCHAR
Definition Typedefs.h:20
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
@ AAssetType_AssetPack
Definition AAssetLoader.h:7
@ ATerrainLODType_None
@ ATerrainLODType_NUMOF
@ ATerrainLODType_High
@ ATerrainLODType_Low
TINT8 ATerrainLODType
void ThreadSleep(TUINT dwMilliseconds)
constexpr TFLOAT MAXFLOAT
Definition TMathInline.h:30
Definition TTRB.h:253
const TVector3 & AsBasisVector3(BASISVECTOR a_iIndex) const
Definition TMatrix44.h:115
const TVector4 & AsBasisVector4(BASISVECTOR a_iIndex) const
Definition TMatrix44.h:131
void Multiply(const TMatrix44 &a_rLeft, const TMatrix44 &a_rRight)
Definition TMatrix44.cpp:61
static constinit const TVector3 VEC_ZERO
Definition TVector3.h:150
TFLOAT y
Definition TVector3.h:163
TFLOAT z
Definition TVector3.h:163
TFLOAT x
Definition TVector3.h:163
TFLOAT w
Definition TVector4.h:367
TFLOAT x
Definition TVector4.h:367
TFLOAT y
Definition TVector4.h:367
TFLOAT z
Definition TVector4.h:367
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
void SetSkeletonInstance(TSkeletonInstance *a_pSkeletonInstance)
TCameraObject * GetCameraObject() const
TRenderContext * GetCurrentContext() const
virtual TBOOL Update(float a_fDeltaTime)=0
static TFORCEINLINE TRenderInterface * GetSingleton()
Definition TSingleton.h:49
static TSIZE String8Length(const TCHAR *str)
static void String8Format(TCHAR *str, TINT size, const TCHAR *format,...)
static TCHAR * String8Copy(TCHAR *dst, const TCHAR *src, TSIZE size=-1)
static Toshi::TTRB * GetAssetTRB(AAssetType a_eAssetType)
ASectionDoneJob * GetFreeSectionLoaderJob()
static constexpr TUINT MAX_NUM_SECTION_LOADER_JOBS
AMatLibLoaderJob * GetFreeMatlibLoaderJob()
ATerrainLocator * FindLocator(const TCHAR *a_pszLocatorName)
Finds a locator (bone) by the specified name and returns it if found.
void UpdateUsedBlocks(ATerrainLODType a_eLODType)
Sets visible blocks of specified LOD type to be used.
void LoadFromFile(const TCHAR *a_szFilePath, TBOOL a_bLoadLater, TBOOL a_bStreamCollision)
Loads information about terrain.
Toshi::TVector4 GetLocatorPos(const TCHAR *a_pszLocatorName)
Finds a locator (bone) by the specified name and obtains it current position if found.
static constexpr TUINT MAX_NUM_TRB_LOADER_JOBS
ASkeletonDoneJob * GetFreeSkeletonLoaderJob()
void DestroyModelData(ATerrainSection::ModelNode *a_pModelData)
void GetLocatorTransform(const TCHAR *a_pszLocatorName, Toshi::TMatrix44 &a_rOutTransform)
Finds a locator (bone) by the specified name and obtains it current transform if found.
static constexpr TUINT MAX_NUM_MATLIB_LOADER_JOBS
ACollisionDoneJob * GetFreeCollisionLoaderJob()
ATerrainSection::ModelNode * CreateModelInstance(ATerrainSection::ModelNode *a_pModelNode, const char *a_szModelName, const char *a_szType)
static constexpr TUINT MAX_NUM_MODEL_LOADER_JOBS
ATerrainLocatorList * GetLocatorList() const
ATerrainLODBlock * AllocateLODBlock(ATerrainLODType a_eLODType, ATerrainSection *a_pVISGroup)
Allocates free LODBlock of specified type and assigns it to the section.
static constexpr TUINT MAX_NUM_SKELETON_LOADER_JOBS
static constexpr TUINT NUM_TOTAL_JOBS
ATerrainInterface(TINT a_iUnused1, TINT a_iUnused2, TINT a_iPreloadTerrainBlockSize, TINT a_iStartVISGroup)
static constexpr TUINT MAX_NUM_COLLISION_LOADER_JOBS
void GetLocatorPosAndRot(const TCHAR *a_pszLocatorName, Toshi::TVector4 &a_rOutPosition, Toshi::TQuaternion &a_rOutRotation)
Finds a locator (bone) by the specified name and obtains it current position and rotation if found.
AModelLoaderJob * GetFreeModelLoaderJob()
static constexpr TUINT MAX_NUM_KEYLIB_LOADER_JOBS
Toshi::T2SListNodeWrapper< AMainThreadJob > JobSlot
ATRBLoaderJob * GetFreeTRBLoaderJob()
void GetMatrix(Toshi::TMatrix44 &a_rOutMatrix)
Toshi::TTransformObject & GetWorldTransform()
ATerrainLocator * FindLocator(const TCHAR *a_pszLocatorName)
Toshi::TSceneObject * m_pSceneObject
Toshi::TManagedModel m_ModelRef
static constexpr TUINT TYPE_NAME_MAX_SIZE
char m_szType[TYPE_NAME_MAX_SIZE+1]
Toshi::TMesh * pMesh
Definition AWorld.h:71
CellMesh * m_pCellMesh
Definition AWorld.h:83
t_RenderCallback m_pfnRenderCallback
Definition AWorldVIS.h:44
void Create(World *a_pWorld)
Definition AWorldVIS.cpp:34