mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 15:32:54 +00:00
Add some intersection tests useful for culling
This commit is contained in:
parent
e3dc9c93b9
commit
402227d6b6
5 changed files with 437 additions and 71 deletions
|
@ -1053,6 +1053,7 @@ set( FASTMATH_PCH_SOURCES
|
||||||
r_swrenderer2.cpp
|
r_swrenderer2.cpp
|
||||||
r_poly.cpp
|
r_poly.cpp
|
||||||
r_poly_triangle.cpp
|
r_poly_triangle.cpp
|
||||||
|
r_poly_intersection.cpp
|
||||||
r_3dfloors.cpp
|
r_3dfloors.cpp
|
||||||
r_bsp.cpp
|
r_bsp.cpp
|
||||||
r_draw.cpp
|
r_draw.cpp
|
||||||
|
|
103
src/r_poly.cpp
103
src/r_poly.cpp
|
@ -75,6 +75,8 @@ void RenderPolyBsp::Render()
|
||||||
// Y shearing like the Doom renderer:
|
// Y shearing like the Doom renderer:
|
||||||
//worldToClip = TriMatrix::viewToClip() * TriMatrix::worldToView();
|
//worldToClip = TriMatrix::viewToClip() * TriMatrix::worldToView();
|
||||||
|
|
||||||
|
frustumPlanes = FrustumPlanes(worldToClip);
|
||||||
|
|
||||||
// Cull front to back
|
// Cull front to back
|
||||||
if (numnodes == 0)
|
if (numnodes == 0)
|
||||||
{
|
{
|
||||||
|
@ -1023,28 +1025,20 @@ int RenderPolyBsp::PointOnSide(const DVector2 &pos, const node_t *node)
|
||||||
|
|
||||||
bool RenderPolyBsp::CheckBBox(float *bspcoord)
|
bool RenderPolyBsp::CheckBBox(float *bspcoord)
|
||||||
{
|
{
|
||||||
static const int checkcoord[12][4] =
|
// Start using a quick frustum AABB test:
|
||||||
{
|
|
||||||
{ 3,0,2,1 },
|
AxisAlignedBoundingBox aabb(Vec3f(bspcoord[BOXLEFT], bspcoord[BOXBOTTOM], -1000.0f), Vec3f(bspcoord[BOXRIGHT], bspcoord[BOXTOP], 1000.0f));
|
||||||
{ 3,0,2,0 },
|
auto result = IntersectionTest::frustum_aabb(frustumPlanes, aabb);
|
||||||
{ 3,1,2,0 },
|
if (result == IntersectionTest::outside)
|
||||||
{ 0 },
|
return false;
|
||||||
{ 2,0,2,1 },
|
|
||||||
{ 0,0,0,0 },
|
// Occlusion test using solid segments (which seems to be quite broken, actually):
|
||||||
{ 3,1,3,0 },
|
|
||||||
{ 0 },
|
|
||||||
{ 2,0,3,1 },
|
|
||||||
{ 2,1,3,1 },
|
|
||||||
{ 2,1,3,0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
int boxx;
|
int boxx;
|
||||||
int boxy;
|
int boxy;
|
||||||
int boxpos;
|
int boxpos;
|
||||||
|
|
||||||
double x1, y1, x2, y2;
|
double x1, y1, x2, y2;
|
||||||
double rx1, ry1, rx2, ry2;
|
|
||||||
int sx1, sx2;
|
|
||||||
|
|
||||||
// Find the corners of the box
|
// Find the corners of the box
|
||||||
// that define the edges from current viewpoint.
|
// that define the edges from current viewpoint.
|
||||||
|
@ -1066,64 +1060,31 @@ bool RenderPolyBsp::CheckBBox(float *bspcoord)
|
||||||
if (boxpos == 5)
|
if (boxpos == 5)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
x1 = bspcoord[checkcoord[boxpos][0]] - ViewPos.X;
|
static const int checkcoord[12][4] =
|
||||||
y1 = bspcoord[checkcoord[boxpos][1]] - ViewPos.Y;
|
{
|
||||||
x2 = bspcoord[checkcoord[boxpos][2]] - ViewPos.X;
|
{ 3,0,2,1 },
|
||||||
y2 = bspcoord[checkcoord[boxpos][3]] - ViewPos.Y;
|
{ 3,0,2,0 },
|
||||||
|
{ 3,1,2,0 },
|
||||||
|
{ 0 },
|
||||||
|
{ 2,0,2,1 },
|
||||||
|
{ 0,0,0,0 },
|
||||||
|
{ 3,1,3,0 },
|
||||||
|
{ 0 },
|
||||||
|
{ 2,0,3,1 },
|
||||||
|
{ 2,1,3,1 },
|
||||||
|
{ 2,1,3,0 }
|
||||||
|
};
|
||||||
|
|
||||||
// check clip list for an open space
|
x1 = bspcoord[checkcoord[boxpos][0]];
|
||||||
|
y1 = bspcoord[checkcoord[boxpos][1]];
|
||||||
|
x2 = bspcoord[checkcoord[boxpos][2]];
|
||||||
|
y2 = bspcoord[checkcoord[boxpos][3]];
|
||||||
|
|
||||||
// Sitting on a line?
|
int sx1, sx2;
|
||||||
if (y1 * (x1 - x2) + x1 * (y2 - y1) >= -EQUAL_EPSILON)
|
if (GetSegmentRangeForLine(x1, y1, x2, y2, sx1, sx2))
|
||||||
|
return !IsSegmentCulled(sx1, sx2);
|
||||||
|
else
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
rx1 = x1 * ViewSin - y1 * ViewCos;
|
|
||||||
rx2 = x2 * ViewSin - y2 * ViewCos;
|
|
||||||
ry1 = x1 * ViewTanCos + y1 * ViewTanSin;
|
|
||||||
ry2 = x2 * ViewTanCos + y2 * ViewTanSin;
|
|
||||||
|
|
||||||
/*if (MirrorFlags & RF_XFLIP)
|
|
||||||
{
|
|
||||||
double t = -rx1;
|
|
||||||
rx1 = -rx2;
|
|
||||||
rx2 = t;
|
|
||||||
swapvalues(ry1, ry2);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (rx1 >= -ry1)
|
|
||||||
{
|
|
||||||
if (rx1 > ry1) return false; // left edge is off the right side
|
|
||||||
if (ry1 == 0) return false;
|
|
||||||
sx1 = xs_RoundToInt(CenterX + rx1 * CenterX / ry1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rx2 < -ry2) return false; // wall is off the left side
|
|
||||||
if (rx1 - rx2 - ry2 + ry1 == 0) return false; // wall does not intersect view volume
|
|
||||||
sx1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rx2 <= ry2)
|
|
||||||
{
|
|
||||||
if (rx2 < -ry2) return false; // right edge is off the left side
|
|
||||||
if (ry2 == 0) return false;
|
|
||||||
sx2 = xs_RoundToInt(CenterX + rx2 * CenterX / ry2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rx1 > ry1) return false; // wall is off the right side
|
|
||||||
if (ry2 - ry1 - rx2 + rx1 == 0) return false; // wall does not intersect view volume
|
|
||||||
sx2 = viewwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first clippost that touches the source post
|
|
||||||
// (adjacent pixels are touching).
|
|
||||||
|
|
||||||
// Does not cross a pixel.
|
|
||||||
if (sx2 <= sx1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !IsSegmentCulled(sx1, sx2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderPolyBsp::GetSegmentRangeForLine(double x1, double y1, double x2, double y2, int &sx1, int &sx2) const
|
bool RenderPolyBsp::GetSegmentRangeForLine(double x1, double y1, double x2, double y2, int &sx1, int &sx2) const
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "r_main.h"
|
#include "r_main.h"
|
||||||
#include "r_poly_triangle.h"
|
#include "r_poly_triangle.h"
|
||||||
|
#include "r_poly_intersection.h"
|
||||||
|
|
||||||
// DScreen accelerated sprite to be rendered
|
// DScreen accelerated sprite to be rendered
|
||||||
class PolyScreenSprite
|
class PolyScreenSprite
|
||||||
|
@ -143,6 +144,7 @@ private:
|
||||||
double MinFloorHeight = 0.0;
|
double MinFloorHeight = 0.0;
|
||||||
|
|
||||||
TriMatrix worldToClip;
|
TriMatrix worldToClip;
|
||||||
|
FrustumPlanes frustumPlanes;
|
||||||
|
|
||||||
std::vector<SpriteRange> SectorSpriteRanges;
|
std::vector<SpriteRange> SectorSpriteRanges;
|
||||||
std::vector<PolySortedSprite> SortedSprites;
|
std::vector<PolySortedSprite> SortedSprites;
|
||||||
|
|
235
src/r_poly_intersection.cpp
Normal file
235
src/r_poly_intersection.cpp
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
** Various 3D intersection tests
|
||||||
|
** Copyright (c) 1997-2015 The UICore Team
|
||||||
|
**
|
||||||
|
** This software is provided 'as-is', without any express or implied
|
||||||
|
** warranty. In no event will the authors be held liable for any damages
|
||||||
|
** arising from the use of this software.
|
||||||
|
**
|
||||||
|
** Permission is granted to anyone to use this software for any purpose,
|
||||||
|
** including commercial applications, and to alter it and redistribute it
|
||||||
|
** freely, subject to the following restrictions:
|
||||||
|
**
|
||||||
|
** 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
** claim that you wrote the original software. If you use this software
|
||||||
|
** in a product, an acknowledgment in the product documentation would be
|
||||||
|
** appreciated but is not required.
|
||||||
|
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
** misrepresented as being the original software.
|
||||||
|
** 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "templates.h"
|
||||||
|
#include "doomdef.h"
|
||||||
|
#include "r_poly_intersection.h"
|
||||||
|
|
||||||
|
IntersectionTest::Result IntersectionTest::plane_aabb(const Vec4f &plane, const AxisAlignedBoundingBox &aabb)
|
||||||
|
{
|
||||||
|
Vec3f center = aabb.center();
|
||||||
|
Vec3f extents = aabb.extents();
|
||||||
|
float e = extents.x * std::abs(plane.x) + extents.y * std::abs(plane.y) + extents.z * std::abs(plane.z);
|
||||||
|
float s = center.x * plane.x + center.y * plane.y + center.z * plane.z + plane.w;
|
||||||
|
if (s - e > 0)
|
||||||
|
return inside;
|
||||||
|
else if (s + e < 0)
|
||||||
|
return outside;
|
||||||
|
else
|
||||||
|
return intersecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::Result IntersectionTest::plane_obb(const Vec4f &plane, const OrientedBoundingBox &obb)
|
||||||
|
{
|
||||||
|
Vec3f n(plane);
|
||||||
|
float d = plane.w;
|
||||||
|
float e = obb.extents.x * std::abs(Vec3f::dot(obb.axis_x, n)) + obb.extents.y * std::abs(Vec3f::dot(obb.axis_y, n)) + obb.extents.z * std::abs(Vec3f::dot(obb.axis_z, n));
|
||||||
|
float s = Vec3f::dot(obb.center, n) + d;
|
||||||
|
if (s - e > 0)
|
||||||
|
return inside;
|
||||||
|
else if (s + e < 0)
|
||||||
|
return outside;
|
||||||
|
else
|
||||||
|
return intersecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::OverlapResult IntersectionTest::sphere(const Vec3f ¢er1, float radius1, const Vec3f ¢er2, float radius2)
|
||||||
|
{
|
||||||
|
Vec3f h = center1 - center2;
|
||||||
|
float square_distance = Vec3f::dot(h, h);
|
||||||
|
float radius_sum = radius1 + radius2;
|
||||||
|
if (square_distance > radius_sum * radius_sum)
|
||||||
|
return disjoint;
|
||||||
|
else
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::OverlapResult IntersectionTest::sphere_aabb(const Vec3f ¢er, float radius, const AxisAlignedBoundingBox &aabb)
|
||||||
|
{
|
||||||
|
Vec3f a = aabb.aabb_min - center;
|
||||||
|
Vec3f b = center - aabb.aabb_max;
|
||||||
|
a.x = std::max(a.x, 0.0f);
|
||||||
|
a.y = std::max(a.y, 0.0f);
|
||||||
|
a.z = std::max(a.z, 0.0f);
|
||||||
|
b.x = std::max(b.x, 0.0f);
|
||||||
|
b.y = std::max(b.y, 0.0f);
|
||||||
|
b.z = std::max(b.z, 0.0f);
|
||||||
|
Vec3f e = a + b;
|
||||||
|
float d = Vec3f::dot(e, e);
|
||||||
|
if (d > radius * radius)
|
||||||
|
return disjoint;
|
||||||
|
else
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::OverlapResult IntersectionTest::aabb(const AxisAlignedBoundingBox &a, const AxisAlignedBoundingBox &b)
|
||||||
|
{
|
||||||
|
if (a.aabb_min.x > b.aabb_max.x || b.aabb_min.x > a.aabb_max.x ||
|
||||||
|
a.aabb_min.y > b.aabb_max.y || b.aabb_min.y > a.aabb_max.y ||
|
||||||
|
a.aabb_min.z > b.aabb_max.z || b.aabb_min.z > a.aabb_max.z)
|
||||||
|
{
|
||||||
|
return disjoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::Result IntersectionTest::frustum_aabb(const FrustumPlanes &frustum, const AxisAlignedBoundingBox &box)
|
||||||
|
{
|
||||||
|
bool is_intersecting = false;
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
Result result = plane_aabb(frustum.planes[i], box);
|
||||||
|
if (result == outside)
|
||||||
|
return outside;
|
||||||
|
else if (result == intersecting)
|
||||||
|
is_intersecting = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_intersecting)
|
||||||
|
return intersecting;
|
||||||
|
else
|
||||||
|
return inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::Result IntersectionTest::frustum_obb(const FrustumPlanes &frustum, const OrientedBoundingBox &box)
|
||||||
|
{
|
||||||
|
bool is_intersecting = false;
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
Result result = plane_obb(frustum.planes[i], box);
|
||||||
|
if (result == outside)
|
||||||
|
return outside;
|
||||||
|
else if (result == intersecting)
|
||||||
|
is_intersecting = true;
|
||||||
|
}
|
||||||
|
if (is_intersecting)
|
||||||
|
return intersecting;
|
||||||
|
else
|
||||||
|
return inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntersectionTest::OverlapResult IntersectionTest::ray_aabb(const Vec3f &ray_start, const Vec3f &ray_end, const AxisAlignedBoundingBox &aabb)
|
||||||
|
{
|
||||||
|
Vec3f c = (ray_start + ray_end) * 0.5f;
|
||||||
|
Vec3f w = ray_end - c;
|
||||||
|
Vec3f h = aabb.extents();
|
||||||
|
|
||||||
|
c -= aabb.center();
|
||||||
|
|
||||||
|
Vec3f v(std::abs(w.x), std::abs(w.y), std::abs(w.z));
|
||||||
|
|
||||||
|
if (std::abs(c.x) > v.x + h.x || std::abs(c.y) > v.y + h.y || std::abs(c.z) > v.z + h.z)
|
||||||
|
return disjoint;
|
||||||
|
|
||||||
|
if (std::abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y ||
|
||||||
|
std::abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x ||
|
||||||
|
std::abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x)
|
||||||
|
return disjoint;
|
||||||
|
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FrustumPlanes::FrustumPlanes()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FrustumPlanes::FrustumPlanes(const Mat4f &world_to_projection)
|
||||||
|
{
|
||||||
|
planes[0] = near_frustum_plane(world_to_projection);
|
||||||
|
planes[1] = far_frustum_plane(world_to_projection);
|
||||||
|
planes[2] = left_frustum_plane(world_to_projection);
|
||||||
|
planes[3] = right_frustum_plane(world_to_projection);
|
||||||
|
planes[4] = top_frustum_plane(world_to_projection);
|
||||||
|
planes[5] = bottom_frustum_plane(world_to_projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4f FrustumPlanes::left_frustum_plane(const Mat4f &m)
|
||||||
|
{
|
||||||
|
Vec4f plane(
|
||||||
|
m.matrix[3 + 0 * 4] + m.matrix[0 + 0 * 4],
|
||||||
|
m.matrix[3 + 1 * 4] + m.matrix[0 + 1 * 4],
|
||||||
|
m.matrix[3 + 2 * 4] + m.matrix[0 + 2 * 4],
|
||||||
|
m.matrix[3 + 3 * 4] + m.matrix[0 + 3 * 4]);
|
||||||
|
plane /= plane.length3();
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4f FrustumPlanes::right_frustum_plane(const Mat4f &m)
|
||||||
|
{
|
||||||
|
Vec4f plane(
|
||||||
|
m.matrix[3 + 0 * 4] - m.matrix[0 + 0 * 4],
|
||||||
|
m.matrix[3 + 1 * 4] - m.matrix[0 + 1 * 4],
|
||||||
|
m.matrix[3 + 2 * 4] - m.matrix[0 + 2 * 4],
|
||||||
|
m.matrix[3 + 3 * 4] - m.matrix[0 + 3 * 4]);
|
||||||
|
plane /= plane.length3();
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4f FrustumPlanes::top_frustum_plane(const Mat4f &m)
|
||||||
|
{
|
||||||
|
Vec4f plane(
|
||||||
|
m.matrix[3 + 0 * 4] - m.matrix[1 + 0 * 4],
|
||||||
|
m.matrix[3 + 1 * 4] - m.matrix[1 + 1 * 4],
|
||||||
|
m.matrix[3 + 2 * 4] - m.matrix[1 + 2 * 4],
|
||||||
|
m.matrix[3 + 3 * 4] - m.matrix[1 + 3 * 4]);
|
||||||
|
plane /= plane.length3();
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4f FrustumPlanes::bottom_frustum_plane(const Mat4f &m)
|
||||||
|
{
|
||||||
|
Vec4f plane(
|
||||||
|
m.matrix[3 + 0 * 4] + m.matrix[1 + 0 * 4],
|
||||||
|
m.matrix[3 + 1 * 4] + m.matrix[1 + 1 * 4],
|
||||||
|
m.matrix[3 + 2 * 4] + m.matrix[1 + 2 * 4],
|
||||||
|
m.matrix[3 + 3 * 4] + m.matrix[1 + 3 * 4]);
|
||||||
|
plane /= plane.length3();
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4f FrustumPlanes::near_frustum_plane(const Mat4f &m)
|
||||||
|
{
|
||||||
|
Vec4f plane(
|
||||||
|
m.matrix[3 + 0 * 4] + m.matrix[2 + 0 * 4],
|
||||||
|
m.matrix[3 + 1 * 4] + m.matrix[2 + 1 * 4],
|
||||||
|
m.matrix[3 + 2 * 4] + m.matrix[2 + 2 * 4],
|
||||||
|
m.matrix[3 + 3 * 4] + m.matrix[2 + 3 * 4]);
|
||||||
|
plane /= plane.length3();
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4f FrustumPlanes::far_frustum_plane(const Mat4f &m)
|
||||||
|
{
|
||||||
|
Vec4f plane(
|
||||||
|
m.matrix[3 + 0 * 4] - m.matrix[2 + 0 * 4],
|
||||||
|
m.matrix[3 + 1 * 4] - m.matrix[2 + 1 * 4],
|
||||||
|
m.matrix[3 + 2 * 4] - m.matrix[2 + 2 * 4],
|
||||||
|
m.matrix[3 + 3 * 4] - m.matrix[2 + 3 * 4]);
|
||||||
|
plane /= plane.length3();
|
||||||
|
return plane;
|
||||||
|
}
|
167
src/r_poly_intersection.h
Normal file
167
src/r_poly_intersection.h
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
** Various 3D intersection tests
|
||||||
|
** Copyright (c) 1997-2015 The UICore Team
|
||||||
|
**
|
||||||
|
** This software is provided 'as-is', without any express or implied
|
||||||
|
** warranty. In no event will the authors be held liable for any damages
|
||||||
|
** arising from the use of this software.
|
||||||
|
**
|
||||||
|
** Permission is granted to anyone to use this software for any purpose,
|
||||||
|
** including commercial applications, and to alter it and redistribute it
|
||||||
|
** freely, subject to the following restrictions:
|
||||||
|
**
|
||||||
|
** 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
** claim that you wrote the original software. If you use this software
|
||||||
|
** in a product, an acknowledgment in the product documentation would be
|
||||||
|
** appreciated but is not required.
|
||||||
|
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
** misrepresented as being the original software.
|
||||||
|
** 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "r_triangle.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
class Vec4f
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec4f() = default;
|
||||||
|
Vec4f(const Vec4f &) = default;
|
||||||
|
Vec4f(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
|
||||||
|
Vec4f(float v) : x(v), y(v), z(v), w(v) { }
|
||||||
|
|
||||||
|
static float dot(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; }
|
||||||
|
static float dot3(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||||
|
float length3() const { return std::sqrt(dot3(*this, *this)); }
|
||||||
|
float magnitude() const { return std::sqrt(dot(*this, *this)); }
|
||||||
|
|
||||||
|
Vec4f &operator+=(const Vec4f &b) { *this = Vec4f(x + b.x, y + b.y, z + b.z, w + b.w); return *this; }
|
||||||
|
Vec4f &operator-=(const Vec4f &b) { *this = Vec4f(x - b.x, y - b.y, z - b.z, w - b.w); return *this; }
|
||||||
|
Vec4f &operator*=(const Vec4f &b) { *this = Vec4f(x * b.x, y * b.y, z * b.z, w * b.w); return *this; }
|
||||||
|
Vec4f &operator/=(const Vec4f &b) { *this = Vec4f(x / b.x, y / b.y, z / b.z, w / b.w); return *this; }
|
||||||
|
Vec4f &operator+=(float b) { *this = Vec4f(x + b, y + b, z + b, w + b); return *this; }
|
||||||
|
Vec4f &operator-=(float b) { *this = Vec4f(x - b, y - b, z - b, w - b); return *this; }
|
||||||
|
Vec4f &operator*=(float b) { *this = Vec4f(x * b, y * b, z * b, w * b); return *this; }
|
||||||
|
Vec4f &operator/=(float b) { *this = Vec4f(x / b, y / b, z / b, w / b); return *this; }
|
||||||
|
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Vec3f
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec3f() = default;
|
||||||
|
Vec3f(const Vec3f &) = default;
|
||||||
|
Vec3f(const Vec4f &v) : x(v.x), y(v.y), z(v.z) { }
|
||||||
|
Vec3f(float x, float y, float z) : x(x), y(y), z(z) { }
|
||||||
|
Vec3f(float v) : x(v), y(v), z(v) { }
|
||||||
|
|
||||||
|
static float dot(const Vec3f &a, const Vec3f &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||||
|
float length() const { return std::sqrt(dot(*this, *this)); }
|
||||||
|
|
||||||
|
Vec3f &operator+=(const Vec3f &b) { *this = Vec3f(x + b.x, y + b.y, z + b.z); return *this; }
|
||||||
|
Vec3f &operator-=(const Vec3f &b) { *this = Vec3f(x - b.x, y - b.y, z - b.z); return *this; }
|
||||||
|
Vec3f &operator*=(const Vec3f &b) { *this = Vec3f(x * b.x, y * b.y, z * b.z); return *this; }
|
||||||
|
Vec3f &operator/=(const Vec3f &b) { *this = Vec3f(x / b.x, y / b.y, z / b.z); return *this; }
|
||||||
|
Vec3f &operator+=(float b) { *this = Vec3f(x + b, y + b, z + b); return *this; }
|
||||||
|
Vec3f &operator-=(float b) { *this = Vec3f(x - b, y - b, z - b); return *this; }
|
||||||
|
Vec3f &operator*=(float b) { *this = Vec3f(x * b, y * b, z * b); return *this; }
|
||||||
|
Vec3f &operator/=(float b) { *this = Vec3f(x / b, y / b, z / b); return *this; }
|
||||||
|
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Vec3f operator+(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x + b.x, a.y + b.y, a.z + b.z); }
|
||||||
|
inline Vec3f operator-(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x - b.x, a.y - b.y, a.z - b.z); }
|
||||||
|
inline Vec3f operator*(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x * b.x, a.y * b.y, a.z * b.z); }
|
||||||
|
inline Vec3f operator/(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x / b.x, a.y / b.y, a.z / b.z); }
|
||||||
|
|
||||||
|
inline Vec3f operator+(const Vec3f &a, float b) { return Vec3f(a.x + b, a.y + b, a.z + b); }
|
||||||
|
inline Vec3f operator-(const Vec3f &a, float b) { return Vec3f(a.x - b, a.y - b, a.z - b); }
|
||||||
|
inline Vec3f operator*(const Vec3f &a, float b) { return Vec3f(a.x * b, a.y * b, a.z * b); }
|
||||||
|
inline Vec3f operator/(const Vec3f &a, float b) { return Vec3f(a.x / b, a.y / b, a.z / b); }
|
||||||
|
|
||||||
|
inline Vec3f operator+(float a, const Vec3f &b) { return Vec3f(a + b.x, a + b.y, a + b.z); }
|
||||||
|
inline Vec3f operator-(float a, const Vec3f &b) { return Vec3f(a - b.x, a - b.y, a - b.z); }
|
||||||
|
inline Vec3f operator*(float a, const Vec3f &b) { return Vec3f(a * b.x, a * b.y, a * b.z); }
|
||||||
|
inline Vec3f operator/(float a, const Vec3f &b) { return Vec3f(a / b.x, a / b.y, a / b.z); }
|
||||||
|
|
||||||
|
typedef TriMatrix Mat4f;
|
||||||
|
|
||||||
|
class AxisAlignedBoundingBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AxisAlignedBoundingBox() : aabb_min(), aabb_max() {}
|
||||||
|
AxisAlignedBoundingBox(const Vec3f &aabb_min, const Vec3f &aabb_max) : aabb_min(aabb_min), aabb_max(aabb_max) { }
|
||||||
|
AxisAlignedBoundingBox(const AxisAlignedBoundingBox &aabb, const Vec3f &barycentric_min, const Vec3f &barycentric_max)
|
||||||
|
: aabb_min(mix(aabb.aabb_min, aabb.aabb_max, barycentric_min)), aabb_max(mix(aabb.aabb_min, aabb.aabb_max, barycentric_max)) { }
|
||||||
|
|
||||||
|
Vec3f center() const { return (aabb_max + aabb_min) * 0.5f; }
|
||||||
|
Vec3f extents() const { return (aabb_max - aabb_min) * 0.5f; }
|
||||||
|
|
||||||
|
Vec3f aabb_min;
|
||||||
|
Vec3f aabb_max;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename A, typename B, typename C>
|
||||||
|
inline A mix(A a, B b, C mix)
|
||||||
|
{
|
||||||
|
return a * (C(1) - mix) + b * mix;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OrientedBoundingBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec3f center;
|
||||||
|
Vec3f extents;
|
||||||
|
Vec3f axis_x;
|
||||||
|
Vec3f axis_y;
|
||||||
|
Vec3f axis_z;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FrustumPlanes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FrustumPlanes();
|
||||||
|
explicit FrustumPlanes(const Mat4f &world_to_projection);
|
||||||
|
|
||||||
|
Vec4f planes[6];
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Vec4f left_frustum_plane(const Mat4f &matrix);
|
||||||
|
static Vec4f right_frustum_plane(const Mat4f &matrix);
|
||||||
|
static Vec4f top_frustum_plane(const Mat4f &matrix);
|
||||||
|
static Vec4f bottom_frustum_plane(const Mat4f &matrix);
|
||||||
|
static Vec4f near_frustum_plane(const Mat4f &matrix);
|
||||||
|
static Vec4f far_frustum_plane(const Mat4f &matrix);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IntersectionTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Result
|
||||||
|
{
|
||||||
|
outside,
|
||||||
|
inside,
|
||||||
|
intersecting,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OverlapResult
|
||||||
|
{
|
||||||
|
disjoint,
|
||||||
|
overlap
|
||||||
|
};
|
||||||
|
|
||||||
|
static Result plane_aabb(const Vec4f &plane, const AxisAlignedBoundingBox &aabb);
|
||||||
|
static Result plane_obb(const Vec4f &plane, const OrientedBoundingBox &obb);
|
||||||
|
static OverlapResult sphere(const Vec3f ¢er1, float radius1, const Vec3f ¢er2, float radius2);
|
||||||
|
static OverlapResult sphere_aabb(const Vec3f ¢er, float radius, const AxisAlignedBoundingBox &aabb);
|
||||||
|
static OverlapResult aabb(const AxisAlignedBoundingBox &a, const AxisAlignedBoundingBox &b);
|
||||||
|
static Result frustum_aabb(const FrustumPlanes &frustum, const AxisAlignedBoundingBox &box);
|
||||||
|
static Result frustum_obb(const FrustumPlanes &frustum, const OrientedBoundingBox &box);
|
||||||
|
static OverlapResult ray_aabb(const Vec3f &ray_start, const Vec3f &ray_end, const AxisAlignedBoundingBox &box);
|
||||||
|
};
|
Loading…
Reference in a new issue