-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathllighttracer.h
196 lines (165 loc) · 5.22 KB
/
llighttracer.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
#pragma once
#include "core/math/aabb.h"
#include "lbitfield_dynamic.h"
#include "llighttests_simd.h"
#include "llighttypes.h"
#include "lvector.h"
#include <limits.h>
//#define LIGHTTRACER_IGNORE_VOXELS
#define LIGHTTRACER_EXPANDED_BOUND (0.2f)
#define LIGHTTRACER_HALF_EXPANSION (LIGHTTRACER_EXPANDED_BOUND / 2.0f)
namespace LM {
class LightScene;
class Voxel {
public:
void Reset() {
m_TriIDs.clear();
m_PackedTriangles.clear();
m_iNumTriangles = 0;
m_SDF = UINT_MAX;
}
LVector<uint32_t> m_TriIDs;
// a COPY of the triangles in SIMD format, edge form
// contiguous in memory for faster testing
LVector<PackedTriangles> m_PackedTriangles;
int m_iNumTriangles;
unsigned int m_SDF; // measured in voxels
void AddTriangle(const Tri &tri, uint32_t tri_id) {
m_TriIDs.push_back(tri_id);
uint32_t packed = m_iNumTriangles / 4;
uint32_t mod = m_iNumTriangles % 4;
if (packed >= m_PackedTriangles.size()) {
PackedTriangles *pNew = m_PackedTriangles.request();
pNew->Create();
}
// fill the relevant packed triangle
PackedTriangles &tris = m_PackedTriangles[packed];
tris.Set(mod, tri);
m_iNumTriangles++;
}
void Finalize() {
uint32_t packed = m_iNumTriangles / 4;
uint32_t mod = m_iNumTriangles % 4;
if (mod) {
PackedTriangles &tris = m_PackedTriangles[packed];
tris.Finalize(mod);
}
if (m_iNumTriangles)
m_SDF = 0; // seed the SDF
}
};
class LightTracer {
public:
friend class RayBank;
void Reset();
// void Create(const LightScene &scene, const Vec3i &voxel_dims);
void Create(const LightScene &scene, int voxel_density);
// translate a real world distance into a number of voxels in each direction
// (this can be used to limit the distance in ray traces)
void GetDistanceInVoxels(float dist, Vec3i &ptVoxelDist) const;
bool RayTrace_Start(Ray ray, Ray &voxel_ray, Vec3i &start_voxel);
const Voxel *RayTrace(const Ray &ray_orig, Ray &ray_out, Vec3i &ptVoxel);
LVector<uint32_t> m_TriHits;
bool m_bSIMD;
bool m_bUseSDF;
void FindNearestVoxel(const Vector3 &ptWorld, Vec3i &ptVoxel) const;
const AABB &GetWorldBound_expanded() const { return m_SceneWorldBound_expanded; }
const AABB &GetWorldBound_mid() const { return m_SceneWorldBound_mid; }
const AABB &GetWorldBound_contracted() const { return m_SceneWorldBound_contracted; }
// void ClampVoxelToBounds(Vec3i &v) const
// {
// v.x = CLAMP(v.x, 0, m_Dims.x-1);
// v.y = CLAMP(v.y, 0, m_Dims.y-1);
// v.z = CLAMP(v.z, 0, m_Dims.z-1);
// }
Vec3i EstimateVoxelDims(int voxel_density);
private:
void CalculateWorldBound();
void CalculateVoxelDims(int voxel_density);
void FillVoxels();
void CalculateSDF();
void Debug_SaveSDF();
void CalculateSDF_Voxel(const Vec3i &ptCentre);
void CalculateSDF_AssessNeighbour(const Vec3i &pt, unsigned int &min_SDF);
bool VoxelWithinBounds(Vec3i v) const {
if (v.x < 0)
return false;
if (v.y < 0)
return false;
if (v.z < 0)
return false;
if (v.x >= m_Dims.x)
return false;
if (v.y >= m_Dims.y)
return false;
if (v.z >= m_Dims.z)
return false;
return true;
}
void DebugCheckWorldPointInVoxel(Vector3 pt, const Vec3i &ptVoxel);
void DebugCheckLocalPointInVoxel(Vector3 pt, const Vec3i &ptVoxel) {
// assert ((int) (pt.x+0.5f) == ptVoxel.x);
// assert ((int) (pt.y+0.5f) == ptVoxel.y);
// assert ((int) (pt.z+0.5f) == ptVoxel.z);
}
LVector<Voxel> m_Voxels;
LVector<AABB> m_VoxelBounds;
LBitField_Dynamic m_BFTrisHit;
int m_iNumTris;
// slightly expanded
AABB m_SceneWorldBound_expanded;
AABB m_SceneWorldBound_mid;
// exact
AABB m_SceneWorldBound_contracted;
const LightScene *m_pScene;
Vec3i m_Dims;
int m_DimsXTimesY;
Vector3 m_VoxelSize;
int m_iNumVoxels;
// Plane m_VoxelPlanes[6];
// to prevent integer overflow in the voxels, we calculate the maximum possible distance
real_t m_fMaxTestDist;
int GetVoxelNum(const Vec3i &pos) const {
int v = pos.z * m_DimsXTimesY;
v += pos.y * m_Dims.x;
v += pos.x;
return v;
}
const Voxel &GetVoxel(const Vec3i &pos) const {
int v = GetVoxelNum(pos);
assert(v < m_iNumVoxels);
return m_Voxels[v];
}
Voxel &GetVoxel(const Vec3i &pos) {
int v = GetVoxelNum(pos);
assert(v < m_iNumVoxels);
return m_Voxels[v];
}
// the pt is both the output intersection point, and the input plane constant (in the correct tuple)
void IntersectAAPlane_OnlyWithinAABB(const AABB &aabb, const Ray &ray, int axis, Vector3 &pt, float &nearest_hit, int plane_id, int &nearest_plane_id, float aabb_epsilon = 0.0f) const {
if (ray.IntersectAAPlane(axis, pt)) {
Vector3 offset = (pt - ray.o);
float dist = offset.length_squared();
if (dist < nearest_hit) {
// must be within aabb
if (aabb.has_point(pt)) {
nearest_hit = dist;
nearest_plane_id = plane_id;
}
}
}
}
// the pt is both the output intersection point, and the input plane constant (in the correct tuple)
void IntersectAAPlane(const Ray &ray, int axis, Vector3 &pt, float &nearest_hit, int plane_id, int &nearest_plane_id) const {
if (ray.IntersectAAPlane(axis, pt)) {
Vector3 offset = (pt - ray.o);
float dist = offset.length_squared();
if (dist < nearest_hit) {
nearest_hit = dist;
nearest_plane_id = plane_id;
}
}
}
bool IntersectRayAABB(const Ray &ray, const AABB &aabb, Vector3 &ptInter);
};
} // namespace LM