OpenBarnyard
 
Loading...
Searching...
No Matches
AWorldVIS.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "AWorldVIS.h"
3
5
6//-----------------------------------------------------------------------------
7// Enables memory debugging.
8// Note: Should be the last include!
9//-----------------------------------------------------------------------------
10#include <Core/TMemoryDebugOn.h>
11
13
22
24{
25 Reset();
26
27 if ( m_pCellNodes )
28 {
29 delete[] m_pCellNodes;
31 }
32}
33
34void AWorldVis::Create( World* a_pWorld )
35{
36 m_pWorld = a_pWorld;
37 m_pCellNodes = new CellNode[ a_pWorld->m_iNumCells ];
38 Reset();
39}
40
42{
43 for ( TINT i = 0; i < m_iNumBuiltCells; i++ )
44 {
45 m_pWorld->m_ppCells[ m_pCellNodes[ i ].iCellIndex ]->pNode = TNULL;
46 }
47
50}
51
52void AWorldVis::Build( const Toshi::TMatrix44& a_rModelView, const Toshi::TMatrix44& a_rProjection, TINT a_iCellIndex )
53{
55
56 TMatrix44 viewModel = a_rModelView;
57 viewModel.InvertOrthogonal();
59
60 CullBox cullBox;
61 cullBox.x = 0.0f;
62 cullBox.y = 0.0f;
63 cullBox.width = TFLOAT( TRenderInterface::GetSingleton()->GetCurrentDisplayParams()->uiWidth );
64 cullBox.height = TFLOAT( TRenderInterface::GetSingleton()->GetCurrentDisplayParams()->uiHeight );
65
66 Build( a_rModelView, a_rProjection, a_iCellIndex, cullBox );
67}
68
69// Seems to be unused in Barnyard and even de Blob
70static TUINT s_uiBuildFlags = 0;
71
72void AWorldVis::Build( const Toshi::TMatrix44& a_rModelView, const Toshi::TMatrix44& a_rProjection, TINT a_iCellIndex, const CullBox& a_rCullBox )
73{
75
76 TASSERT( a_iCellIndex < m_pWorld->m_iNumCells );
77
78 if ( ISZERO( s_uiBuildFlags & 1 ) )
79 {
80 s_uiBuildFlags |= 1;
81 }
82
83 auto pCell = m_pWorld->m_ppCells[ a_iCellIndex ];
84
85 if ( ISZERO( pCell->uiFlags & Cell::FLAGS_BUILDING ) )
86 {
87 pCell->uiFlags |= Cell::FLAGS_BUILDING;
88
89 auto pRenderContext = TRenderInterface::GetSingleton()->GetCurrentContext();
90 auto pNode = pCell->pNode;
91
92 if ( TNULL == pNode )
93 {
95 pNode = m_pCellNodes + ( m_iNumBuiltCells++ );
96 pCell->pNode = pNode;
97 pNode->iCellIndex = a_iCellIndex;
98 pNode->pCellSettings = TNULL;
99 }
100
101 TVALIDPTR( pNode );
102
103 auto pCellSettings = &m_aCellSettings[ m_iNumCellSettings++ ];
104
105 pCellSettings->pNext = pNode->pCellSettings;
106 pCellSettings->oCullBox = a_rCullBox;
107 pNode->pCellSettings = pCellSettings;
108
109 for ( TINT i = 0; i < pCell->m_iSomeCount; i++ )
110 {
111 // Seems to be never used in Barnyard so I'll just pray it will never get here
112 TASSERT( !"Well, we are fucked up" );
113 }
114
115 pCell->uiFlags &= ~Cell::FLAGS_BUILDING;
116 }
117}
118
119static void CreatePortalFrustum( Frustum& a_rFrustum, CullBox& a_rCullBox, TMatrix44& a_rMatrix )
120{
121 auto pRenderContext = TRenderInterface::GetSingleton()->GetCurrentContext();
122
123 a_rFrustum.aFrustumPlanes[ 0 ].oPlane = pRenderContext->GetFrustumPlanes()[ 0 ];
124 a_rFrustum.aFrustumPlanes[ 1 ].oPlane = pRenderContext->GetFrustumPlanes()[ 1 ];
125 a_rFrustum.aFrustumPlanes[ 2 ].oPlane = pRenderContext->GetFrustumPlanes()[ 2 ];
126 a_rFrustum.aFrustumPlanes[ 3 ].oPlane = pRenderContext->GetFrustumPlanes()[ 3 ];
127 a_rFrustum.aFrustumPlanes[ 4 ].oPlane = pRenderContext->GetFrustumPlanes()[ 4 ];
128 a_rFrustum.aFrustumPlanes[ 5 ].oPlane = pRenderContext->GetFrustumPlanes()[ 5 ];
129 a_rFrustum.aFrustumPlanes[ 0 ].uiClipFlag = 1;
130 a_rFrustum.aFrustumPlanes[ 1 ].uiClipFlag = 2;
131 a_rFrustum.aFrustumPlanes[ 2 ].uiClipFlag = 4;
132 a_rFrustum.aFrustumPlanes[ 3 ].uiClipFlag = 8;
133 a_rFrustum.aFrustumPlanes[ 4 ].uiClipFlag = 16;
134 a_rFrustum.aFrustumPlanes[ 5 ].uiClipFlag = 32;
135}
136
137void AWorldVis::Render( const Toshi::TMatrix44& a_rModelView )
138{
140
141 // Create stack values and store pointer to the array to use it later
142 StackValue aStack[ s_iStackSize + 1 ];
143 AWorldVis::s_pStack = aStack;
144
145 if ( TNULL != m_pfnRenderCallback )
146 {
147 auto pRenderContext = TRenderInterface::GetSingleton()->GetCurrentContext();
148
149 TMatrix44 viewModel = a_rModelView;
150 viewModel.InvertOrthogonal();
151
152 TMatrix44 projection;
154 projection,
155 pRenderContext->GetViewportParameters(),
156 pRenderContext->GetProjectionParams()
157 );
158
159 for ( TINT i = 0; i < m_iNumBuiltCells; i++ )
160 {
161 Frustum portalFrustum;
162 Frustum frustum;
163
164 auto pCell = m_pWorld->m_ppCells[ m_pCellNodes[ i ].iCellIndex ];
165
166 for ( auto pSettings = pCell->pNode->pCellSettings; pSettings != TNULL; pSettings = pSettings->pNext )
167 {
168 CreatePortalFrustum( portalFrustum, pSettings->oCullBox, projection );
169 frustum.Transform( portalFrustum, viewModel );
170 frustum.InitReduce();
171
172 RenderData renderData;
173 renderData.pCell = pCell;
174 renderData.pFrustum = &frustum;
175
176 RenderTreeIntersectNonRecurse( pCell->pTreeBranchNodes, &renderData );
177 }
178 }
179 }
180}
181
183{
184 auto pRightNode = a_pNode->m_pRight;
185 auto pNode = a_pNode;
186
187 while ( pRightNode != TNULL )
188 {
189 pNode = pRightNode;
190 pRightNode = pRightNode->m_pRight;
191 }
192
194 endNode.m_BoundingSphere = TSphere( 0.0f, 0.0f, 0.0f, 0.0f );
195 endNode.m_pRight = pNode->GetLeafNode()->End();
196
197 auto pStackValue1 = s_pStack + 0;
198 auto pStackValue2 = s_pStack + 1;
199
200 pStackValue1->pNextNode = a_pNode;
201 pStackValue1->pPrevNode = &endNode;
202 pStackValue1->iInitialPlaneCount = a_pRenderData->pFrustum->iActivePlaneCount;
203
204 pStackValue2->pNextNode = a_pNode;
205 pStackValue2->pPrevNode = &endNode;
206 pStackValue2->iInitialPlaneCount = a_pRenderData->pFrustum->iActivePlaneCount;
207
208 TINT iNumVisibleSpheres = 0;
209 pStackValue1 = pStackValue2;
210
211 for ( ;; )
212 {
213 auto pStackValue2Node = pStackValue2->pNextNode;
214 a_pRenderData->pFrustum->iActivePlaneCount = pStackValue2->iInitialPlaneCount;
215
216 if ( pStackValue2Node->IsLeaf() )
217 {
218 RenderLeafNodeIntersect( pStackValue2Node, a_pRenderData );
219 iNumVisibleSpheres -= 1;
220
221 pStackValue2 = pStackValue1 - 1;
222 pStackValue2->pNextNode = pStackValue2->pNextNode->m_pRight;
223 pStackValue1 = pStackValue2;
224 }
225 else
226 {
227 FrustumIntersectSphereResult eIntersectResult =
228 a_pRenderData->pFrustum->IntersectSphereReduce( pStackValue2Node->m_BoundingSphere );
229
230 if ( eIntersectResult == FISR_ALL_VISIBLE )
231 {
232 // The whole node is visible so just render everything
233 TINT iCurrentActivePlaneCount = a_pRenderData->pFrustum->iActivePlaneCount;
234 a_pRenderData->pFrustum->iActivePlaneCount = 0;
235
236 auto pEndNode = pStackValue2->pPrevNode->m_pRight;
237 while ( pStackValue2Node < pEndNode )
238 {
239 if ( pStackValue2Node->IsLeaf() )
240 {
241 for ( TUINT i = 0; i < pStackValue2Node->GetLeafNode()->m_uiNumMeshes; i++ )
242 {
244 a_pRenderData->pCell->ppCellMeshSpheres[ pStackValue2Node->GetLeafNode()->GetMeshIndex( i ) ],
245 a_pRenderData
246 );
247 }
248
249 pStackValue2Node = pStackValue2Node->GetLeafNode()->End();
250 }
251 else
252 {
253 pStackValue2Node = pStackValue2Node->GetSubNode();
254 }
255 }
256
257 a_pRenderData->pFrustum->iActivePlaneCount = iCurrentActivePlaneCount;
258 }
259
260 if ( eIntersectResult == FISR_PARTIALLY_VISIBLE )
261 {
262 // This node is partially visible so let's
263 // check what leaf nodes are actually visible
264 iNumVisibleSpheres++;
265 pStackValue2 = pStackValue1 + 1;
266 pStackValue2->iInitialPlaneCount = a_pRenderData->pFrustum->iActivePlaneCount;
267 pStackValue2->pNextNode = pStackValue2Node->GetSubNode();
268 pStackValue2->pPrevNode = pStackValue2Node;
269 pStackValue1 = pStackValue2;
270 }
271 else
272 {
273 // Skip this node is already rendered or just not visible
274 iNumVisibleSpheres--;
275 pStackValue2 = pStackValue1 - 1;
276 pStackValue2->pNextNode = pStackValue2->pNextNode->m_pRight;
277 pStackValue1 = pStackValue2;
278 }
279 }
280
281 if ( iNumVisibleSpheres < 0 ) break;
282 }
283}
284
286{
287 // Use this to restore active planes after reduce intersect
288 TINT iActivePlaneCount = a_pRenderData->pFrustum->iActivePlaneCount;
289
290 for ( TUINT i = 0; i < a_pNode->GetLeafNode()->m_uiNumMeshes; i++ )
291 {
292 CellMeshSphere* pMeshSphere = a_pRenderData->pCell->ppCellMeshSpheres[ a_pNode->GetLeafNode()->GetMeshIndex( i ) ];
293 TINT iIntersectResult = a_pRenderData->pFrustum->IntersectSphereReduce( pMeshSphere->m_BoundingSphere );
294
295 if ( iIntersectResult != -1 )
296 {
297 m_pfnRenderCallback( pMeshSphere, a_pRenderData );
298 }
299
300 a_pRenderData->pFrustum->iActivePlaneCount = iActivePlaneCount;
301 }
302}
Rendering system interface for the Toshi engine.
#define TASSERT(X,...)
Definition Defines.h:138
#define TOSHI_NAMESPACE_USING
Definition Defines.h:46
#define ISZERO(X)
Definition Defines.h:3
#define TVALIDPTR(PTR)
Definition Defines.h:139
#define TPROFILER_SCOPE()
Definition Profiler.h:17
unsigned int TUINT
Definition Typedefs.h:8
float TFLOAT
Definition Typedefs.h:4
#define TNULL
Definition Typedefs.h:23
int TINT
Definition Typedefs.h:7
FrustumIntersectSphereResult
Definition AWorld.h:38
@ FISR_PARTIALLY_VISIBLE
Definition AWorld.h:41
@ FISR_ALL_VISIBLE
Definition AWorld.h:39
void InvertOrthogonal()
TVector4 & GetTranslation()
Definition TMatrix44.h:157
TVector3 & AsVector3()
Definition TVector4.h:321
static void ComputePerspectiveProjection(TMatrix44 &a_rOutProjection, const VIEWPORTPARAMS &a_rViewportParams, const PROJECTIONPARAMS &a_rProjParams)
TRenderContext * GetCurrentContext() const
static TFORCEINLINE TRenderInterface * GetSingleton()
Definition TSingleton.h:49
TFLOAT y
Definition AWorld.h:12
TFLOAT x
Definition AWorld.h:11
TFLOAT width
Definition AWorld.h:13
TFLOAT height
Definition AWorld.h:14
Toshi::TPlane oPlane
Definition AWorld.h:33
TUINT uiClipFlag
Definition AWorld.h:34
TINT iActivePlaneCount
Definition AWorld.h:58
FrustumIntersectSphereResult IntersectSphereReduce(const Toshi::TSphere &a_rSphere)
Definition AWorld.cpp:33
void Transform(const Frustum &a_rFrustum, const Toshi::TMatrix44 &a_rMatrix)
Definition AWorld.cpp:59
void InitReduce()
Definition AWorld.cpp:23
FrustumPlane aFrustumPlanes[6]
Definition AWorld.h:56
Toshi::TSphere m_BoundingSphere
Definition AWorld.h:82
struct CellSphereTreeBranchNode * End()
Definition AWorld.h:96
TUINT16 & GetMeshIndex(TUINT32 a_uiIndex)
Definition AWorld.h:90
CellSphereTreeLeafNode * GetLeafNode()
Definition AWorld.h:109
CellSphereTreeBranchNode * m_pRight
Definition AWorld.h:105
Toshi::TSphere m_BoundingSphere
Definition AWorld.h:104
Definition AWorld.h:128
CellMeshSphere ** ppCellMeshSpheres
Definition AWorld.h:141
@ FLAGS_BUILDING
Definition AWorld.h:132
TINT32 m_iNumCells
Definition AWorld.h:147
Cell * pCell
Definition AWorld.h:159
Frustum * pFrustum
Definition AWorld.h:160
Toshi::TVector3 m_ViewModelPos
Definition AWorldVIS.h:43
t_RenderCallback m_pfnRenderCallback
Definition AWorldVIS.h:44
void RenderLeafNodeIntersect(CellSphereTreeBranchNode *a_pNode, RenderData *a_pRenderData)
TINT m_iNumBuiltCells
Definition AWorldVIS.h:40
void Reset()
Definition AWorldVIS.cpp:41
void Build(const Toshi::TMatrix44 &a_rModelView, const Toshi::TMatrix44 &a_rProjection, TINT a_iCellIndex)
Definition AWorldVIS.cpp:52
CellSettings m_aCellSettings[MAX_VISIBLE_CELLS]
Definition AWorldVIS.h:38
void Create(World *a_pWorld)
Definition AWorldVIS.cpp:34
TINT m_iNumCellSettings
Definition AWorldVIS.h:41
World * m_pWorld
Definition AWorldVIS.h:37
void RenderTreeIntersectNonRecurse(CellSphereTreeBranchNode *a_pNode, RenderData *a_pRenderData)
static constexpr TUINT MAX_VISIBLE_CELLS
Definition AWorldVIS.h:7
CellNode * m_pCellNodes
Definition AWorldVIS.h:39
void Render(const Toshi::TMatrix44 &a_rModelView)