mirror of
https://github.com/Redot-Engine/redot-engine.git
synced 2025-12-06 15:21:56 -05:00
New lightmapper
-Added LocalVector (needed it) -Added stb_rect_pack (It's pretty cool, we could probably use it for other stuff too) -Fixes and changes all around the place -Added library for 128 bits fixed point (required for Delaunay3D)
This commit is contained in:
@@ -29,207 +29,12 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "voxelizer.h"
|
||||
#include "core/math/geometry.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/os/threaded_array_processor.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FINDMINMAX(x0, x1, x2, min, max) \
|
||||
min = max = x0; \
|
||||
if (x1 < min) \
|
||||
min = x1; \
|
||||
if (x1 > max) \
|
||||
max = x1; \
|
||||
if (x2 < min) \
|
||||
min = x2; \
|
||||
if (x2 > max) \
|
||||
max = x2;
|
||||
|
||||
static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) {
|
||||
int q;
|
||||
Vector3 vmin, vmax;
|
||||
for (q = 0; q <= 2; q++) {
|
||||
if (normal[q] > 0.0f) {
|
||||
vmin[q] = -maxbox[q];
|
||||
vmax[q] = maxbox[q];
|
||||
} else {
|
||||
vmin[q] = maxbox[q];
|
||||
vmax[q] = -maxbox[q];
|
||||
}
|
||||
}
|
||||
if (normal.dot(vmin) + d > 0.0f)
|
||||
return false;
|
||||
if (normal.dot(vmax) + d >= 0.0f)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*======================== X-tests ========================*/
|
||||
#define AXISTEST_X01(a, b, fa, fb) \
|
||||
p0 = a * v0.y - b * v0.z; \
|
||||
p2 = a * v2.y - b * v2.z; \
|
||||
if (p0 < p2) { \
|
||||
min = p0; \
|
||||
max = p2; \
|
||||
} else { \
|
||||
min = p2; \
|
||||
max = p0; \
|
||||
} \
|
||||
rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
|
||||
if (min > rad || max < -rad) \
|
||||
return false;
|
||||
|
||||
#define AXISTEST_X2(a, b, fa, fb) \
|
||||
p0 = a * v0.y - b * v0.z; \
|
||||
p1 = a * v1.y - b * v1.z; \
|
||||
if (p0 < p1) { \
|
||||
min = p0; \
|
||||
max = p1; \
|
||||
} else { \
|
||||
min = p1; \
|
||||
max = p0; \
|
||||
} \
|
||||
rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
|
||||
if (min > rad || max < -rad) \
|
||||
return false;
|
||||
|
||||
/*======================== Y-tests ========================*/
|
||||
#define AXISTEST_Y02(a, b, fa, fb) \
|
||||
p0 = -a * v0.x + b * v0.z; \
|
||||
p2 = -a * v2.x + b * v2.z; \
|
||||
if (p0 < p2) { \
|
||||
min = p0; \
|
||||
max = p2; \
|
||||
} else { \
|
||||
min = p2; \
|
||||
max = p0; \
|
||||
} \
|
||||
rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
|
||||
if (min > rad || max < -rad) \
|
||||
return false;
|
||||
|
||||
#define AXISTEST_Y1(a, b, fa, fb) \
|
||||
p0 = -a * v0.x + b * v0.z; \
|
||||
p1 = -a * v1.x + b * v1.z; \
|
||||
if (p0 < p1) { \
|
||||
min = p0; \
|
||||
max = p1; \
|
||||
} else { \
|
||||
min = p1; \
|
||||
max = p0; \
|
||||
} \
|
||||
rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
|
||||
if (min > rad || max < -rad) \
|
||||
return false;
|
||||
|
||||
/*======================== Z-tests ========================*/
|
||||
|
||||
#define AXISTEST_Z12(a, b, fa, fb) \
|
||||
p1 = a * v1.x - b * v1.y; \
|
||||
p2 = a * v2.x - b * v2.y; \
|
||||
if (p2 < p1) { \
|
||||
min = p2; \
|
||||
max = p1; \
|
||||
} else { \
|
||||
min = p1; \
|
||||
max = p2; \
|
||||
} \
|
||||
rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
|
||||
if (min > rad || max < -rad) \
|
||||
return false;
|
||||
|
||||
#define AXISTEST_Z0(a, b, fa, fb) \
|
||||
p0 = a * v0.x - b * v0.y; \
|
||||
p1 = a * v1.x - b * v1.y; \
|
||||
if (p0 < p1) { \
|
||||
min = p0; \
|
||||
max = p1; \
|
||||
} else { \
|
||||
min = p1; \
|
||||
max = p0; \
|
||||
} \
|
||||
rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
|
||||
if (min > rad || max < -rad) \
|
||||
return false;
|
||||
|
||||
static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) {
|
||||
|
||||
/* use separating axis theorem to test overlap between triangle and box */
|
||||
/* need to test for overlap in these directions: */
|
||||
/* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
|
||||
/* we do not even need to test these) */
|
||||
/* 2) normal of the triangle */
|
||||
/* 3) crossproduct(edge from tri, {x,y,z}-directin) */
|
||||
/* this gives 3x3=9 more tests */
|
||||
Vector3 v0, v1, v2;
|
||||
float min, max, d, p0, p1, p2, rad, fex, fey, fez;
|
||||
Vector3 normal, e0, e1, e2;
|
||||
|
||||
/* This is the fastest branch on Sun */
|
||||
/* move everything so that the boxcenter is in (0,0,0) */
|
||||
|
||||
v0 = triverts[0] - boxcenter;
|
||||
v1 = triverts[1] - boxcenter;
|
||||
v2 = triverts[2] - boxcenter;
|
||||
|
||||
/* compute triangle edges */
|
||||
e0 = v1 - v0; /* tri edge 0 */
|
||||
e1 = v2 - v1; /* tri edge 1 */
|
||||
e2 = v0 - v2; /* tri edge 2 */
|
||||
|
||||
/* Bullet 3: */
|
||||
/* test the 9 tests first (this was faster) */
|
||||
fex = Math::abs(e0.x);
|
||||
fey = Math::abs(e0.y);
|
||||
fez = Math::abs(e0.z);
|
||||
AXISTEST_X01(e0.z, e0.y, fez, fey);
|
||||
AXISTEST_Y02(e0.z, e0.x, fez, fex);
|
||||
AXISTEST_Z12(e0.y, e0.x, fey, fex);
|
||||
|
||||
fex = Math::abs(e1.x);
|
||||
fey = Math::abs(e1.y);
|
||||
fez = Math::abs(e1.z);
|
||||
AXISTEST_X01(e1.z, e1.y, fez, fey);
|
||||
AXISTEST_Y02(e1.z, e1.x, fez, fex);
|
||||
AXISTEST_Z0(e1.y, e1.x, fey, fex);
|
||||
|
||||
fex = Math::abs(e2.x);
|
||||
fey = Math::abs(e2.y);
|
||||
fez = Math::abs(e2.z);
|
||||
AXISTEST_X2(e2.z, e2.y, fez, fey);
|
||||
AXISTEST_Y1(e2.z, e2.x, fez, fex);
|
||||
AXISTEST_Z12(e2.y, e2.x, fey, fex);
|
||||
|
||||
/* Bullet 1: */
|
||||
/* first test overlap in the {x,y,z}-directions */
|
||||
/* find min, max of the triangle each direction, and test for overlap in */
|
||||
/* that direction -- this is equivalent to testing a minimal AABB around */
|
||||
/* the triangle against the AABB */
|
||||
|
||||
/* test in X-direction */
|
||||
FINDMINMAX(v0.x, v1.x, v2.x, min, max);
|
||||
if (min > boxhalfsize.x || max < -boxhalfsize.x)
|
||||
return false;
|
||||
|
||||
/* test in Y-direction */
|
||||
FINDMINMAX(v0.y, v1.y, v2.y, min, max);
|
||||
if (min > boxhalfsize.y || max < -boxhalfsize.y)
|
||||
return false;
|
||||
|
||||
/* test in Z-direction */
|
||||
FINDMINMAX(v0.z, v1.z, v2.z, min, max);
|
||||
if (min > boxhalfsize.z || max < -boxhalfsize.z)
|
||||
return false;
|
||||
|
||||
/* Bullet 2: */
|
||||
/* test if the box intersects the plane of the triangle */
|
||||
/* compute plane equation of triangle: normal*x+d=0 */
|
||||
normal = e0.cross(e1);
|
||||
d = -normal.dot(v0); /* plane eq: normal.x+d=0 */
|
||||
return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
|
||||
|
||||
if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
|
||||
@@ -324,7 +129,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
|
||||
Vector3 half = (to - from) * 0.5;
|
||||
|
||||
//is in this cell?
|
||||
if (!fast_tri_box_overlap(from + half, half, p_vtx)) {
|
||||
if (!Geometry::triangle_box_overlap(from + half, half, p_vtx)) {
|
||||
continue; //face does not span this cell
|
||||
}
|
||||
|
||||
@@ -467,7 +272,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
|
||||
//test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time
|
||||
Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test
|
||||
|
||||
if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
|
||||
if (!Geometry::triangle_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) {
|
||||
//if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) {
|
||||
//does not fit in child, go on
|
||||
continue;
|
||||
@@ -648,7 +453,7 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
|
||||
}
|
||||
|
||||
//test against original bounds
|
||||
if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
|
||||
if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
|
||||
continue;
|
||||
//plot
|
||||
_plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
|
||||
@@ -681,7 +486,7 @@ void Voxelizer::plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vec
|
||||
}
|
||||
|
||||
//test against original bounds
|
||||
if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
|
||||
if (!Geometry::triangle_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs))
|
||||
continue;
|
||||
//plot face
|
||||
_plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds);
|
||||
|
||||
Reference in New Issue
Block a user