forked from NikitaNikson/X-Ray_Renewal_Engine
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathISpatial.h
197 lines (175 loc) · 5.52 KB
/
ISpatial.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#pragma once
#include "../xrCore/xrPool.h"
#include "xr_collide_defs.h"
constexpr Fvector c_spatial_offset[8] =
{
{ -1, -1, -1 },
{ 1, -1, -1 },
{ -1, 1, -1 },
{ 1, 1, -1 },
{ -1, -1, 1 },
{ 1, -1, 1 },
{ -1, 1, 1 },
{ 1, 1, 1 }
};
#pragma pack(push,4)
/*
Requirements:
0. Generic
* O(1) insertion
- radius completely determines "level"
- position completely detemines "node"
* O(1) removal
*
1. Rendering
* Should live inside spatial DB
* Should have at least "bounding-sphere" or "bounding-box"
* Should have pointer to "sector" it lives in
* Approximate traversal order relative to point ("camera")
2. Spatial queries
* Should live inside spatial DB
* Should have at least "bounding-sphere" or "bounding-box"
*/
const float c_spatial_min = 8.f;
//////////////////////////////////////////////////////////////////////////
enum
{
STYPE_RENDERABLE = (1<<0),
STYPE_LIGHTSOURCE = (1<<1),
STYPE_COLLIDEABLE = (1<<2),
STYPE_VISIBLEFORAI = (1<<3),
STYPE_REACTTOSOUND = (1<<4),
STYPE_PHYSIC = (1<<5),
STYPE_OBSTACLE = (1<<6),
STYPE_SHAPE = (1<<7),
STYPE_LIGHTSOURCEHEMI = (1<<8),
STYPEFLAG_INVALIDSECTOR = (1<<16)
};
//////////////////////////////////////////////////////////////////////////
// Comment:
// ordinal objects - renderable?, collideable?, visibleforAI?
// physical-decorations - renderable, collideable
// lights - lightsource
// particles(temp-objects) - renderable
// glow - renderable
// sound - ???
//////////////////////////////////////////////////////////////////////////
class ISpatial_NODE;
class IRender_Sector;
class ISpatial_DB;
namespace Feel { class Sound; }
class IRenderable;
class IRender_Light;
class XRCDB_API ISpatial
{
public:
struct _spatial
{
u32 type;
Fsphere sphere;
Fvector node_center; // Cached node center for TBV optimization
float node_radius; // Cached node bounds for TBV optimization
ISpatial_NODE* node_ptr; // Cached parent node for "empty-members" optimization
IRender_Sector* sector;
ISpatial_DB* space; // allow different spaces
_spatial() : type(0) {} // safe way to enhure type is zero before any contstructors takes place
} spatial;
public:
BOOL spatial_inside () ;
void spatial_updatesector_internal() ;
public:
virtual void spatial_register () ;
virtual void spatial_unregister () ;
virtual void spatial_move () ;
virtual Fvector spatial_sector_point() { return spatial.sphere.P; }
ICF void spatial_updatesector() {
if (0== (spatial.type&STYPEFLAG_INVALIDSECTOR)) return;
spatial_updatesector_internal () ;
};
virtual CObject* dcast_CObject () { return 0; }
virtual Feel::Sound* dcast_FeelSound () { return 0; }
virtual IRenderable* dcast_Renderable () { return 0; }
virtual IRender_Light* dcast_Light () { return 0; }
ISpatial (ISpatial_DB* space );
virtual ~ISpatial ();
};
//////////////////////////////////////////////////////////////////////////
class ISpatial_NODE
{
public:
typedef _W64 unsigned ptrt;
public:
ISpatial_NODE* parent; // parent node for "empty-members" optimization
ISpatial_NODE* children [8]; // children nodes
xr_vector<ISpatial*> items; // own items
public:
void _init (ISpatial_NODE* _parent);
void _remove (ISpatial* _S);
void _insert (ISpatial* _S);
BOOL _empty ()
{
return items.empty() &&
children[0] == nullptr && children[1] == nullptr &&
children[2] == nullptr && children[3] == nullptr &&
children[4] == nullptr && children[5] == nullptr &&
children[6] == nullptr && children[7] == nullptr;
}
};
//////////////////////////////////////////////////////////////////////////
class XRCDB_API ISpatial_DB
{
private:
xrCriticalSection cs;
poolSS<ISpatial_NODE,128> allocator;
xr_vector<ISpatial_NODE*> allocator_pool;
ISpatial* rt_insert_object{};
public:
ISpatial_NODE* m_root;
Fvector m_center;
float m_bounds{};
xr_vector<ISpatial*>* q_result{};
u32 stat_nodes;
u32 stat_objects;
CStatTimer stat_insert;
CStatTimer stat_remove;
private:
IC u32 _octant (u32 x, u32 y, u32 z) { return z*4 + y*2 + x; }
IC u32 _octant (Fvector& base, Fvector& rel)
{
u32 o = 0;
if (rel.x > base.x) o+=1;
if (rel.y > base.y) o+=2;
if (rel.z > base.z) o+=4;
return o;
}
ISpatial_NODE* _node_create ();
void _node_destroy (ISpatial_NODE* &P);
void _insert (ISpatial_NODE* N, Fvector& n_center, float n_radius);
void _remove (ISpatial_NODE* N, ISpatial_NODE* N_sub);
public:
ISpatial_DB();
~ISpatial_DB();
// managing
void initialize (Fbox& BB);
//void destroy ();
void insert (ISpatial* S);
void remove (ISpatial* S);
void update (u32 nodes=8);
BOOL verify ();
public:
enum
{
O_ONLYFIRST = (1<<0),
O_ONLYNEAREST = (1<<1),
O_ORDERED = (1<<2),
O_force_u32 = u32(-1)
};
// query
void q_ray (xr_vector<ISpatial*>& R, u32 _o, u32 _mask_and, const Fvector& _start, const Fvector& _dir, float _range);
void q_box (xr_vector<ISpatial*>& R, u32 _o, u32 _mask_or, const Fvector& _center, const Fvector& _size);
void q_sphere (xr_vector<ISpatial*>& R, u32 _o, u32 _mask_or, const Fvector& _center, const float _radius);
void q_frustum (xr_vector<ISpatial*>& R, u32 _o, u32 _mask_or, const CFrustum& _frustum);
};
XRCDB_API extern ISpatial_DB* g_SpatialSpace ;
XRCDB_API extern ISpatial_DB* g_SpatialSpacePhysic ;
#pragma pack(pop)