mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-02-03 13:11:04 +00:00
Replace the vector/matrix classes with something behaving a bit more like glsl
This commit is contained in:
parent
6b4fef6a2b
commit
cb42f82bfc
32 changed files with 1618 additions and 2715 deletions
|
@ -179,13 +179,11 @@ set( SOURCES
|
||||||
src/lightmap/glsl_rmiss_sun.h
|
src/lightmap/glsl_rmiss_sun.h
|
||||||
src/lightmap/cpuraytracer.cpp
|
src/lightmap/cpuraytracer.cpp
|
||||||
src/lightmap/cpuraytracer.h
|
src/lightmap/cpuraytracer.h
|
||||||
|
src/math/mat.cpp
|
||||||
|
src/math/plane.cpp
|
||||||
src/math/angle.cpp
|
src/math/angle.cpp
|
||||||
src/math/bounds.cpp
|
src/math/bounds.cpp
|
||||||
src/math/mathlib.cpp
|
src/math/mathlib.cpp
|
||||||
src/math/matrix.cpp
|
|
||||||
src/math/plane.cpp
|
|
||||||
src/math/quaternion.cpp
|
|
||||||
src/math/vector.cpp
|
|
||||||
src/models/model.cpp
|
src/models/model.cpp
|
||||||
src/models/model.h
|
src/models/model.h
|
||||||
src/models/model_md2.h
|
src/models/model_md2.h
|
||||||
|
@ -220,6 +218,9 @@ set( HEADERS
|
||||||
src/lightmap/surfaces.h
|
src/lightmap/surfaces.h
|
||||||
src/lightmap/worker.h
|
src/lightmap/worker.h
|
||||||
src/lightmap/collision.h
|
src/lightmap/collision.h
|
||||||
|
src/math/mat.h
|
||||||
|
src/math/quaternion.h
|
||||||
|
src/math/vec.h
|
||||||
src/math/mathlib.h
|
src/math/mathlib.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,9 @@ float BinFile::ReadFloat()
|
||||||
return fi.f;
|
return fi.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 BinFile::ReadVector()
|
vec3 BinFile::ReadVector()
|
||||||
{
|
{
|
||||||
Vec3 vec;
|
vec3 vec;
|
||||||
|
|
||||||
vec.x = ReadFloat();
|
vec.x = ReadFloat();
|
||||||
vec.y = ReadFloat();
|
vec.y = ReadFloat();
|
||||||
|
@ -121,7 +121,7 @@ void BinFile::WriteFloat(const float val)
|
||||||
Write32(fi.i);
|
Write32(fi.i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinFile::WriteVector(const Vec3 &val)
|
void BinFile::WriteVector(const vec3 &val)
|
||||||
{
|
{
|
||||||
WriteFloat(val.x);
|
WriteFloat(val.x);
|
||||||
WriteFloat(val.y);
|
WriteFloat(val.y);
|
||||||
|
|
|
@ -37,14 +37,14 @@ public:
|
||||||
short Read16();
|
short Read16();
|
||||||
int Read32();
|
int Read32();
|
||||||
float ReadFloat();
|
float ReadFloat();
|
||||||
Vec3 ReadVector();
|
vec3 ReadVector();
|
||||||
std::string ReadString();
|
std::string ReadString();
|
||||||
|
|
||||||
void Write8(const uint8_t val);
|
void Write8(const uint8_t val);
|
||||||
void Write16(const short val);
|
void Write16(const short val);
|
||||||
void Write32(const int val);
|
void Write32(const int val);
|
||||||
void WriteFloat(const float val);
|
void WriteFloat(const float val);
|
||||||
void WriteVector(const Vec3 &val);
|
void WriteVector(const vec3 &val);
|
||||||
void WriteString(const std::string &val);
|
void WriteString(const std::string &val);
|
||||||
|
|
||||||
int GetOffsetValue(int id);
|
int GetOffsetValue(int id);
|
||||||
|
|
|
@ -165,29 +165,3 @@ const T MAX (const T a, const T b)
|
||||||
{
|
{
|
||||||
return a > b ? a : b;
|
return a > b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// clamp
|
|
||||||
//
|
|
||||||
// Clamps in to the range [min,max].
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline
|
|
||||||
T clamp (const T in, const T min, const T max)
|
|
||||||
{
|
|
||||||
return in <= min ? min : in >= max ? max : in;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T smoothstep(const T edge0, const T edge1, const T x)
|
|
||||||
{
|
|
||||||
auto t = clamp<T>((x - edge0) / (edge1 - edge0), T(0.0), T(1.0));
|
|
||||||
return t * t * (T(3.0) - T(2.0) * t);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float radians(float degrees)
|
|
||||||
{
|
|
||||||
return degrees * 3.14159265359f / 180.0f;
|
|
||||||
}
|
|
||||||
|
|
|
@ -250,8 +250,6 @@ struct IntVertex
|
||||||
};
|
};
|
||||||
|
|
||||||
class BBox;
|
class BBox;
|
||||||
class Vec3;
|
|
||||||
class Vec2;
|
|
||||||
struct vertex_t;
|
struct vertex_t;
|
||||||
struct Surface;
|
struct Surface;
|
||||||
struct ThingLight;
|
struct ThingLight;
|
||||||
|
@ -265,8 +263,8 @@ struct FloatVertex
|
||||||
struct ThingLight
|
struct ThingLight
|
||||||
{
|
{
|
||||||
IntThing *mapThing;
|
IntThing *mapThing;
|
||||||
Vec2 origin;
|
vec2 origin;
|
||||||
Vec3 rgb;
|
vec3 rgb;
|
||||||
float intensity;
|
float intensity;
|
||||||
float innerAngleCos;
|
float innerAngleCos;
|
||||||
float outerAngleCos;
|
float outerAngleCos;
|
||||||
|
@ -276,14 +274,14 @@ struct ThingLight
|
||||||
IntSector *sector;
|
IntSector *sector;
|
||||||
MapSubsectorEx *ssect;
|
MapSubsectorEx *ssect;
|
||||||
|
|
||||||
Vec3 LightOrigin() const
|
vec3 LightOrigin() const
|
||||||
{
|
{
|
||||||
float originZ;
|
float originZ;
|
||||||
if (!bCeiling)
|
if (!bCeiling)
|
||||||
originZ = sector->floorplane.zAt(origin.x, origin.y) + height;
|
originZ = sector->floorplane.zAt(origin.x, origin.y) + height;
|
||||||
else
|
else
|
||||||
originZ = sector->ceilingplane.zAt(origin.x, origin.y) - height;
|
originZ = sector->ceilingplane.zAt(origin.x, origin.y) - height;
|
||||||
return Vec3(origin.x, origin.y, originZ);
|
return vec3(origin.x, origin.y, originZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
float LightRadius() const
|
float LightRadius() const
|
||||||
|
@ -291,31 +289,31 @@ struct ThingLight
|
||||||
return radius + radius; // 2.0 because gzdoom's dynlights do this and we want them to match
|
return radius + radius; // 2.0 because gzdoom's dynlights do this and we want them to match
|
||||||
}
|
}
|
||||||
|
|
||||||
float SpotAttenuation(const Vec3& dir) const
|
float SpotAttenuation(const vec3& dir) const
|
||||||
{
|
{
|
||||||
float spotAttenuation = 1.0f;
|
float spotAttenuation = 1.0f;
|
||||||
if (outerAngleCos > -1.0f)
|
if (outerAngleCos > -1.0f)
|
||||||
{
|
{
|
||||||
float negPitch = -radians(mapThing->pitch);
|
float negPitch = -radians(mapThing->pitch);
|
||||||
float xyLen = std::cos(negPitch);
|
float xyLen = std::cos(negPitch);
|
||||||
Vec3 spotDir;
|
vec3 spotDir;
|
||||||
spotDir.x = -std::cos(radians(mapThing->angle)) * xyLen;
|
spotDir.x = -std::cos(radians(mapThing->angle)) * xyLen;
|
||||||
spotDir.y = -std::sin(radians(mapThing->angle)) * xyLen;
|
spotDir.y = -std::sin(radians(mapThing->angle)) * xyLen;
|
||||||
spotDir.z = -std::sin(negPitch);
|
spotDir.z = -std::sin(negPitch);
|
||||||
float cosDir = Vec3::Dot(dir, spotDir);
|
float cosDir = dot(dir, spotDir);
|
||||||
spotAttenuation = smoothstep(outerAngleCos, innerAngleCos, cosDir);
|
spotAttenuation = smoothstep(outerAngleCos, innerAngleCos, cosDir);
|
||||||
spotAttenuation = std::max(spotAttenuation, 0.0f);
|
spotAttenuation = std::max(spotAttenuation, 0.0f);
|
||||||
}
|
}
|
||||||
return spotAttenuation;
|
return spotAttenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 SpotDir() const
|
vec3 SpotDir() const
|
||||||
{
|
{
|
||||||
if (outerAngleCos > -1.0f)
|
if (outerAngleCos > -1.0f)
|
||||||
{
|
{
|
||||||
float negPitch = -radians(mapThing->pitch);
|
float negPitch = -radians(mapThing->pitch);
|
||||||
float xyLen = std::cos(negPitch);
|
float xyLen = std::cos(negPitch);
|
||||||
Vec3 spotDir;
|
vec3 spotDir;
|
||||||
spotDir.x = -std::cos(radians(mapThing->angle)) * xyLen;
|
spotDir.x = -std::cos(radians(mapThing->angle)) * xyLen;
|
||||||
spotDir.y = -std::sin(radians(mapThing->angle)) * xyLen;
|
spotDir.y = -std::sin(radians(mapThing->angle)) * xyLen;
|
||||||
spotDir.z = -std::sin(negPitch);
|
spotDir.z = -std::sin(negPitch);
|
||||||
|
@ -323,7 +321,7 @@ struct ThingLight
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Vec3(0.0f);
|
return vec3(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +335,7 @@ struct SurfaceLightDef
|
||||||
{
|
{
|
||||||
float distance;
|
float distance;
|
||||||
float intensity;
|
float intensity;
|
||||||
Vec3 rgb;
|
vec3 rgb;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mapFlags_t
|
enum mapFlags_t
|
||||||
|
@ -387,8 +385,8 @@ struct FLevel
|
||||||
TArray<SurfaceLightDef> SurfaceLights;
|
TArray<SurfaceLightDef> SurfaceLights;
|
||||||
TArray<int> ThingLightProbes;
|
TArray<int> ThingLightProbes;
|
||||||
|
|
||||||
Vec3 defaultSunColor;
|
vec3 defaultSunColor;
|
||||||
Vec3 defaultSunDirection;
|
vec3 defaultSunDirection;
|
||||||
int Samples;
|
int Samples;
|
||||||
int LightBounce;
|
int LightBounce;
|
||||||
float GridSize;
|
float GridSize;
|
||||||
|
@ -404,15 +402,15 @@ struct FLevel
|
||||||
int NumSectors() const { return Sectors.Size(); }
|
int NumSectors() const { return Sectors.Size(); }
|
||||||
int NumThings() const { return Things.Size(); }
|
int NumThings() const { return Things.Size(); }
|
||||||
|
|
||||||
const Vec3 &GetSunColor() const;
|
const vec3 &GetSunColor() const;
|
||||||
const Vec3 &GetSunDirection() const;
|
const vec3 &GetSunDirection() const;
|
||||||
IntSector *GetFrontSector(const IntSideDef *side);
|
IntSector *GetFrontSector(const IntSideDef *side);
|
||||||
IntSector *GetBackSector(const IntSideDef *side);
|
IntSector *GetBackSector(const IntSideDef *side);
|
||||||
IntSector *GetSectorFromSubSector(const MapSubsectorEx *sub);
|
IntSector *GetSectorFromSubSector(const MapSubsectorEx *sub);
|
||||||
MapSubsectorEx *PointInSubSector(const int x, const int y);
|
MapSubsectorEx *PointInSubSector(const int x, const int y);
|
||||||
FloatVertex GetSegVertex(int index);
|
FloatVertex GetSegVertex(int index);
|
||||||
|
|
||||||
Vec3 GetLightProbePosition(int index);
|
vec3 GetLightProbePosition(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CheckSkySectors();
|
void CheckSkySectors();
|
||||||
|
|
|
@ -85,8 +85,8 @@ void FLevel::SetupLights()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GG to whoever memset'ed FLevel
|
// GG to whoever memset'ed FLevel
|
||||||
defaultSunColor = Vec3(1, 1, 1);
|
defaultSunColor = vec3(1, 1, 1);
|
||||||
defaultSunDirection = Vec3(0.45f, 0.3f, 0.9f);
|
defaultSunDirection = vec3(0.45f, 0.3f, 0.9f);
|
||||||
Samples = 8;
|
Samples = 8;
|
||||||
LightBounce = 1;
|
LightBounce = 1;
|
||||||
GridSize = 32.0f;
|
GridSize = 32.0f;
|
||||||
|
@ -101,8 +101,8 @@ void FLevel::SetupLights()
|
||||||
else if (thing->type == 9890) // ZDRayInfo
|
else if (thing->type == 9890) // ZDRayInfo
|
||||||
{
|
{
|
||||||
uint32_t lightcolor = 0xffffff;
|
uint32_t lightcolor = 0xffffff;
|
||||||
Vec3 sundir(0.0f, 0.0f, 0.0f);
|
vec3 sundir(0.0f, 0.0f, 0.0f);
|
||||||
Vec3 suncolor(1.0f, 1.0f, 1.0f);
|
vec3 suncolor(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
for (unsigned int propIndex = 0; propIndex < thing->props.Size(); propIndex++)
|
for (unsigned int propIndex = 0; propIndex < thing->props.Size(); propIndex++)
|
||||||
{
|
{
|
||||||
|
@ -144,9 +144,9 @@ void FLevel::SetupLights()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vec3::Dot(sundir, sundir) > 0.01f)
|
if (dot(sundir, sundir) > 0.01f)
|
||||||
{
|
{
|
||||||
sundir.Normalize();
|
sundir = normalize(sundir);
|
||||||
suncolor.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
suncolor.x = ((lightcolor >> 16) & 0xff) / 255.0f;
|
||||||
suncolor.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
suncolor.y = ((lightcolor >> 8) & 0xff) / 255.0f;
|
||||||
suncolor.z = (lightcolor & 0xff) / 255.0f;
|
suncolor.z = (lightcolor & 0xff) / 255.0f;
|
||||||
|
@ -183,12 +183,12 @@ void FLevel::CheckSkySectors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vec3 &FLevel::GetSunColor() const
|
const vec3 &FLevel::GetSunColor() const
|
||||||
{
|
{
|
||||||
return defaultSunColor;
|
return defaultSunColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vec3 &FLevel::GetSunDirection() const
|
const vec3 &FLevel::GetSunDirection() const
|
||||||
{
|
{
|
||||||
return defaultSunDirection;
|
return defaultSunDirection;
|
||||||
}
|
}
|
||||||
|
@ -235,8 +235,8 @@ MapSubsectorEx *FLevel::PointInSubSector(const int x, const int y)
|
||||||
MapNodeEx *node;
|
MapNodeEx *node;
|
||||||
int side;
|
int side;
|
||||||
int nodenum;
|
int nodenum;
|
||||||
Vec3 dp1;
|
vec3 dp1;
|
||||||
Vec3 dp2;
|
vec3 dp2;
|
||||||
float d;
|
float d;
|
||||||
|
|
||||||
// single subsector is a special case
|
// single subsector is a special case
|
||||||
|
@ -251,15 +251,15 @@ MapSubsectorEx *FLevel::PointInSubSector(const int x, const int y)
|
||||||
{
|
{
|
||||||
node = &GLNodes[nodenum];
|
node = &GLNodes[nodenum];
|
||||||
|
|
||||||
Vec3 pt1(F(node->x), F(node->y), 0);
|
vec3 pt1(F(node->x), F(node->y), 0);
|
||||||
Vec3 pt2(F(node->dx), F(node->dy), 0);
|
vec3 pt2(F(node->dx), F(node->dy), 0);
|
||||||
//Vec3 pt1(F(node->x << 16), F(node->y << 16), 0);
|
//vec3 pt1(F(node->x << 16), F(node->y << 16), 0);
|
||||||
//Vec3 pt2(F(node->dx << 16), F(node->dy << 16), 0);
|
//vec3 pt2(F(node->dx << 16), F(node->dy << 16), 0);
|
||||||
Vec3 pos(F(x << 16), F(y << 16), 0);
|
vec3 pos(F(x << 16), F(y << 16), 0);
|
||||||
|
|
||||||
dp1 = pt1 - pos;
|
dp1 = pt1 - pos;
|
||||||
dp2 = (pt2 + pt1) - pos;
|
dp2 = (pt2 + pt1) - pos;
|
||||||
d = dp1.Cross(dp2).z;
|
d = cross(dp1, dp2).z;
|
||||||
|
|
||||||
side = FLOATSIGNBIT(d);
|
side = FLOATSIGNBIT(d);
|
||||||
|
|
||||||
|
@ -338,7 +338,8 @@ void FLevel::CreateLights()
|
||||||
thingLight.bCeiling = false;
|
thingLight.bCeiling = false;
|
||||||
thingLight.ssect = PointInSubSector(x, y);
|
thingLight.ssect = PointInSubSector(x, y);
|
||||||
thingLight.sector = GetSectorFromSubSector(thingLight.ssect);
|
thingLight.sector = GetSectorFromSubSector(thingLight.ssect);
|
||||||
thingLight.origin.Set(x, y);
|
thingLight.origin.x = x;
|
||||||
|
thingLight.origin.y = y;
|
||||||
|
|
||||||
ThingLights.Push(thingLight);
|
ThingLights.Push(thingLight);
|
||||||
}
|
}
|
||||||
|
@ -464,7 +465,7 @@ void FLevel::CreateLights()
|
||||||
printf("Surface lights: %i\n", (int)SurfaceLights.Size());
|
printf("Surface lights: %i\n", (int)SurfaceLights.Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 FLevel::GetLightProbePosition(int index)
|
vec3 FLevel::GetLightProbePosition(int index)
|
||||||
{
|
{
|
||||||
int thingIndex = ThingLightProbes[index];
|
int thingIndex = ThingLightProbes[index];
|
||||||
const IntThing& thing = Things[thingIndex];
|
const IntThing& thing = Things[thingIndex];
|
||||||
|
@ -482,5 +483,5 @@ Vec3 FLevel::GetLightProbePosition(int index)
|
||||||
z = sector->floorplane.zAt(x, y) + thing.height;
|
z = sector->floorplane.zAt(x, y) + thing.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Vec3(x, y, z);
|
return vec3(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,7 +519,7 @@ void FProcessor::ParseSector(IntSector *sec)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float scale = 1.0f / sec->ceilingplane.Normal().Length();
|
float scale = 1.0f / length(sec->ceilingplane.Normal());
|
||||||
sec->ceilingplane.a *= scale;
|
sec->ceilingplane.a *= scale;
|
||||||
sec->ceilingplane.b *= scale;
|
sec->ceilingplane.b *= scale;
|
||||||
sec->ceilingplane.c *= scale;
|
sec->ceilingplane.c *= scale;
|
||||||
|
@ -536,7 +536,7 @@ void FProcessor::ParseSector(IntSector *sec)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float scale = 1.0f / sec->floorplane.Normal().Length();
|
float scale = 1.0f / length(sec->floorplane.Normal());
|
||||||
sec->floorplane.a *= scale;
|
sec->floorplane.a *= scale;
|
||||||
sec->floorplane.b *= scale;
|
sec->floorplane.b *= scale;
|
||||||
sec->floorplane.c *= scale;
|
sec->floorplane.c *= scale;
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TriangleMeshShape::TriangleMeshShape(const Vec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements)
|
TriangleMeshShape::TriangleMeshShape(const vec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements)
|
||||||
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements)
|
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements)
|
||||||
{
|
{
|
||||||
int num_triangles = num_elements / 3;
|
int num_triangles = num_elements / 3;
|
||||||
|
@ -36,7 +36,7 @@ TriangleMeshShape::TriangleMeshShape(const Vec3 *vertices, int num_vertices, con
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<int> triangles;
|
std::vector<int> triangles;
|
||||||
std::vector<Vec3> centroids;
|
std::vector<vec3> centroids;
|
||||||
triangles.reserve(num_triangles);
|
triangles.reserve(num_triangles);
|
||||||
centroids.reserve(num_triangles);
|
centroids.reserve(num_triangles);
|
||||||
for (int i = 0; i < num_triangles; i++)
|
for (int i = 0; i < num_triangles; i++)
|
||||||
|
@ -44,7 +44,7 @@ TriangleMeshShape::TriangleMeshShape(const Vec3 *vertices, int num_vertices, con
|
||||||
triangles.push_back(i);
|
triangles.push_back(i);
|
||||||
|
|
||||||
int element_index = i * 3;
|
int element_index = i * 3;
|
||||||
Vec3 centroid = (vertices[elements[element_index + 0]] + vertices[elements[element_index + 1]] + vertices[elements[element_index + 2]]) * (1.0f / 3.0f);
|
vec3 centroid = (vertices[elements[element_index + 0]] + vertices[elements[element_index + 1]] + vertices[elements[element_index + 2]]) * (1.0f / 3.0f);
|
||||||
centroids.push_back(centroid);
|
centroids.push_back(centroid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ TriangleMeshShape::TriangleMeshShape(const Vec3 *vertices, int num_vertices, con
|
||||||
root = subdivide(&triangles[0], (int)triangles.size(), ¢roids[0], &work_buffer[0]);
|
root = subdivide(&triangles[0], (int)triangles.size(), ¢roids[0], &work_buffer[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, const Vec3 &target)
|
float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, const vec3 &target)
|
||||||
{
|
{
|
||||||
return sweep(shape1, shape2, shape1->root, target);
|
return sweep(shape1, shape2, shape1->root, target);
|
||||||
}
|
}
|
||||||
|
@ -68,19 +68,19 @@ bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape1, SphereShape *sha
|
||||||
return find_any_hit(shape1, shape2, shape1->root);
|
return find_any_hit(shape1, shape2, shape1->root);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const Vec3 &ray_start, const Vec3 &ray_end)
|
bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const vec3 &ray_start, const vec3 &ray_end)
|
||||||
{
|
{
|
||||||
return find_any_hit(shape, RayBBox(ray_start, ray_end), shape->root);
|
return find_any_hit(shape, RayBBox(ray_start, ray_end), shape->root);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const Vec3 &ray_start, const Vec3 &ray_end)
|
TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const vec3 &ray_start, const vec3 &ray_end)
|
||||||
{
|
{
|
||||||
TraceHit hit;
|
TraceHit hit;
|
||||||
|
|
||||||
// Perform segmented tracing to keep the ray AABB box smaller
|
// Perform segmented tracing to keep the ray AABB box smaller
|
||||||
|
|
||||||
Vec3 ray_dir = ray_end - ray_start;
|
vec3 ray_dir = ray_end - ray_start;
|
||||||
float tracedist = ray_dir.Length();
|
float tracedist = length(ray_dir);
|
||||||
float segmentlen = std::max(100.0f, tracedist / 20.0f);
|
float segmentlen = std::max(100.0f, tracedist / 20.0f);
|
||||||
for (float t = 0.0f; t < tracedist; t += segmentlen)
|
for (float t = 0.0f; t < tracedist; t += segmentlen)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const Vec3
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const Vec3 &target)
|
float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const vec3 &target)
|
||||||
{
|
{
|
||||||
if (sweep_overlap_bv_sphere(shape1, shape2, a, target))
|
if (sweep_overlap_bv_sphere(shape1, shape2, a, target))
|
||||||
{
|
{
|
||||||
|
@ -239,7 +239,7 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
{
|
{
|
||||||
const int start_element = shape->nodes[a].element_index;
|
const int start_element = shape->nodes[a].element_index;
|
||||||
|
|
||||||
Vec3 p[3] =
|
vec3 p[3] =
|
||||||
{
|
{
|
||||||
shape->vertices[shape->elements[start_element]],
|
shape->vertices[shape->elements[start_element]],
|
||||||
shape->vertices[shape->elements[start_element + 1]],
|
shape->vertices[shape->elements[start_element + 1]],
|
||||||
|
@ -248,15 +248,15 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
|
|
||||||
// Moeller–Trumbore ray-triangle intersection algorithm:
|
// Moeller–Trumbore ray-triangle intersection algorithm:
|
||||||
|
|
||||||
Vec3 D = ray.end - ray.start;
|
vec3 D = ray.end - ray.start;
|
||||||
|
|
||||||
// Find vectors for two edges sharing p[0]
|
// Find vectors for two edges sharing p[0]
|
||||||
Vec3 e1 = p[1] - p[0];
|
vec3 e1 = p[1] - p[0];
|
||||||
Vec3 e2 = p[2] - p[0];
|
vec3 e2 = p[2] - p[0];
|
||||||
|
|
||||||
// Begin calculating determinant - also used to calculate u parameter
|
// Begin calculating determinant - also used to calculate u parameter
|
||||||
Vec3 P = Vec3::Cross(D, e2);
|
vec3 P = cross(D, e2);
|
||||||
float det = Vec3::Dot(e1, P);
|
float det = dot(e1, P);
|
||||||
|
|
||||||
// Backface check
|
// Backface check
|
||||||
//if (det < 0.0f)
|
//if (det < 0.0f)
|
||||||
|
@ -269,26 +269,26 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
float inv_det = 1.0f / det;
|
float inv_det = 1.0f / det;
|
||||||
|
|
||||||
// Calculate distance from p[0] to ray origin
|
// Calculate distance from p[0] to ray origin
|
||||||
Vec3 T = ray.start - p[0];
|
vec3 T = ray.start - p[0];
|
||||||
|
|
||||||
// Calculate u parameter and test bound
|
// Calculate u parameter and test bound
|
||||||
float u = Vec3::Dot(T, P) * inv_det;
|
float u = dot(T, P) * inv_det;
|
||||||
|
|
||||||
// Check if the intersection lies outside of the triangle
|
// Check if the intersection lies outside of the triangle
|
||||||
if (u < 0.f || u > 1.f)
|
if (u < 0.f || u > 1.f)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
// Prepare to test v parameter
|
// Prepare to test v parameter
|
||||||
Vec3 Q = Vec3::Cross(T, e1);
|
vec3 Q = cross(T, e1);
|
||||||
|
|
||||||
// Calculate V parameter and test bound
|
// Calculate V parameter and test bound
|
||||||
float v = Vec3::Dot(D, Q) * inv_det;
|
float v = dot(D, Q) * inv_det;
|
||||||
|
|
||||||
// The intersection lies outside of the triangle
|
// The intersection lies outside of the triangle
|
||||||
if (v < 0.f || u + v > 1.f)
|
if (v < 0.f || u + v > 1.f)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
float t = Vec3::Dot(e2, Q) * inv_det;
|
float t = dot(e2, Q) * inv_det;
|
||||||
if (t <= FLT_EPSILON)
|
if (t <= FLT_EPSILON)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const Vec3 &target)
|
bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const vec3 &target)
|
||||||
{
|
{
|
||||||
// Convert to ray test by expanding the AABB:
|
// Convert to ray test by expanding the AABB:
|
||||||
|
|
||||||
|
@ -309,30 +309,30 @@ bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, Spher
|
||||||
return IntersectionTest::ray_aabb(RayBBox(shape2->center, target), aabb) == IntersectionTest::overlap;
|
return IntersectionTest::ray_aabb(RayBBox(shape2->center, target), aabb) == IntersectionTest::overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const Vec3 &target)
|
float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const vec3 &target)
|
||||||
{
|
{
|
||||||
const int start_element = shape1->nodes[a].element_index;
|
const int start_element = shape1->nodes[a].element_index;
|
||||||
|
|
||||||
Vec3 p[3] =
|
vec3 p[3] =
|
||||||
{
|
{
|
||||||
shape1->vertices[shape1->elements[start_element]],
|
shape1->vertices[shape1->elements[start_element]],
|
||||||
shape1->vertices[shape1->elements[start_element + 1]],
|
shape1->vertices[shape1->elements[start_element + 1]],
|
||||||
shape1->vertices[shape1->elements[start_element + 2]]
|
shape1->vertices[shape1->elements[start_element + 2]]
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec3 c = shape2->center;
|
vec3 c = shape2->center;
|
||||||
Vec3 e = target;
|
vec3 e = target;
|
||||||
float r = shape2->radius;
|
float r = shape2->radius;
|
||||||
|
|
||||||
// Dynamic intersection test between a ray and the minkowski sum of the sphere and polygon:
|
// Dynamic intersection test between a ray and the minkowski sum of the sphere and polygon:
|
||||||
|
|
||||||
Vec3 n = Vec3::Normalize(Vec3::Cross(p[1] - p[0], p[2] - p[0]));
|
vec3 n = normalize(cross(p[1] - p[0], p[2] - p[0]));
|
||||||
Vec4 plane(n, -Vec3::Dot(n, p[0]));
|
vec4 plane(n, -dot(n, p[0]));
|
||||||
|
|
||||||
// Step 1: Plane intersect test
|
// Step 1: Plane intersect test
|
||||||
|
|
||||||
float sc = Vec4::Dot(plane, Vec4(c, 1.0f));
|
float sc = dot(plane, vec4(c, 1.0f));
|
||||||
float se = Vec4::Dot(plane, Vec4(e, 1.0f));
|
float se = dot(plane, vec4(e, 1.0f));
|
||||||
bool same_side = sc * se > 0.0f;
|
bool same_side = sc * se > 0.0f;
|
||||||
|
|
||||||
if (same_side && std::abs(sc) > r && std::abs(se) > r)
|
if (same_side && std::abs(sc) > r && std::abs(se) > r)
|
||||||
|
@ -342,26 +342,26 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
|
||||||
{
|
{
|
||||||
float t = (sc - r) / (sc - se);
|
float t = (sc - r) / (sc - se);
|
||||||
|
|
||||||
Vec3 vt = c + (e - c) * t;
|
vec3 vt = c + (e - c) * t;
|
||||||
|
|
||||||
Vec3 u0 = p[1] - p[0];
|
vec3 u0 = p[1] - p[0];
|
||||||
Vec3 u1 = p[2] - p[0];
|
vec3 u1 = p[2] - p[0];
|
||||||
|
|
||||||
Vec2 v_2d[3] =
|
vec2 v_2d[3] =
|
||||||
{
|
{
|
||||||
Vec2(0.0f, 0.0f),
|
vec2(0.0f, 0.0f),
|
||||||
Vec2(Vec3::Dot(u0, u0), 0.0f),
|
vec2(dot(u0, u0), 0.0f),
|
||||||
Vec2(0.0f, Vec3::Dot(u1, u1))
|
vec2(0.0f, dot(u1, u1))
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec2 point(Vec3::Dot(u0, vt), Vec3::Dot(u1, vt));
|
vec2 point(dot(u0, vt), dot(u1, vt));
|
||||||
|
|
||||||
bool inside = false;
|
bool inside = false;
|
||||||
Vec2 e0 = v_2d[2];
|
vec2 e0 = v_2d[2];
|
||||||
bool y0 = e0.y >= point.y;
|
bool y0 = e0.y >= point.y;
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
Vec2 e1 = v_2d[i];
|
vec2 e1 = v_2d[i];
|
||||||
bool y1 = e1.y >= point.y;
|
bool y1 = e1.y >= point.y;
|
||||||
|
|
||||||
if (y0 != y1 && ((e1.y - point.y) * (e0.x - e1.x) >= (e1.x - point.x) * (e0.y - e1.y)) == y1)
|
if (y0 != y1 && ((e1.y - point.y) * (e0.x - e1.x) >= (e1.x - point.x) * (e0.y - e1.y)) == y1)
|
||||||
|
@ -377,21 +377,21 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
|
||||||
|
|
||||||
// Step 2: Edge intersect test
|
// Step 2: Edge intersect test
|
||||||
|
|
||||||
Vec3 ke[3] =
|
vec3 ke[3] =
|
||||||
{
|
{
|
||||||
p[1] - p[0],
|
p[1] - p[0],
|
||||||
p[2] - p[1],
|
p[2] - p[1],
|
||||||
p[0] - p[2],
|
p[0] - p[2],
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec3 kg[3] =
|
vec3 kg[3] =
|
||||||
{
|
{
|
||||||
p[0] - c,
|
p[0] - c,
|
||||||
p[1] - c,
|
p[1] - c,
|
||||||
p[2] - c,
|
p[2] - c,
|
||||||
};
|
};
|
||||||
|
|
||||||
Vec3 ks = e - c;
|
vec3 ks = e - c;
|
||||||
|
|
||||||
float kgg[3];
|
float kgg[3];
|
||||||
float kgs[3];
|
float kgs[3];
|
||||||
|
@ -399,12 +399,12 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
float kee = Vec3::Dot(ke[i], ke[i]);
|
float kee = dot(ke[i], ke[i]);
|
||||||
float keg = Vec3::Dot(ke[i], kg[i]);
|
float keg = dot(ke[i], kg[i]);
|
||||||
float kes = Vec3::Dot(ke[i], ks);
|
float kes = dot(ke[i], ks);
|
||||||
kgg[i] = Vec3::Dot(kg[i], kg[i]);
|
kgg[i] = dot(kg[i], kg[i]);
|
||||||
kgs[i] = Vec3::Dot(kg[i], ks);
|
kgs[i] = dot(kg[i], ks);
|
||||||
kss[i] = Vec3::Dot(ks, ks);
|
kss[i] = dot(ks, ks);
|
||||||
|
|
||||||
float aa = kee * kss[i] - kes * kes;
|
float aa = kee * kss[i] - kes * kes;
|
||||||
float bb = 2 * (keg * kes - kee * kgs[i]);
|
float bb = 2 * (keg * kes - kee * kgs[i]);
|
||||||
|
@ -425,8 +425,8 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
|
||||||
|
|
||||||
if (t >= 0.0f && t <= 1.0f)
|
if (t >= 0.0f && t <= 1.0f)
|
||||||
{
|
{
|
||||||
Vec3 ct = c + ks * t;
|
vec3 ct = c + ks * t;
|
||||||
float d = Vec3::Dot(ct - p[i], ke[i]);
|
float d = dot(ct - p[i], ke[i]);
|
||||||
if (d >= 0.0f && d <= kee)
|
if (d >= 0.0f && d <= kee)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -486,49 +486,49 @@ bool TriangleMeshShape::overlap_triangle_sphere(TriangleMeshShape *shape1, Spher
|
||||||
|
|
||||||
int element_index = shape1->nodes[shape1_node_index].element_index;
|
int element_index = shape1->nodes[shape1_node_index].element_index;
|
||||||
|
|
||||||
Vec3 P = shape2->center;
|
vec3 P = shape2->center;
|
||||||
Vec3 A = shape1->vertices[shape1->elements[element_index]] - P;
|
vec3 A = shape1->vertices[shape1->elements[element_index]] - P;
|
||||||
Vec3 B = shape1->vertices[shape1->elements[element_index + 1]] - P;
|
vec3 B = shape1->vertices[shape1->elements[element_index + 1]] - P;
|
||||||
Vec3 C = shape1->vertices[shape1->elements[element_index + 2]] - P;
|
vec3 C = shape1->vertices[shape1->elements[element_index + 2]] - P;
|
||||||
float r = shape2->radius;
|
float r = shape2->radius;
|
||||||
float rr = r * r;
|
float rr = r * r;
|
||||||
|
|
||||||
// Testing if sphere lies outside the triangle plane
|
// Testing if sphere lies outside the triangle plane
|
||||||
Vec3 V = Vec3::Cross(B - A, C - A);
|
vec3 V = cross(B - A, C - A);
|
||||||
float d = Vec3::Dot(A, V);
|
float d = dot(A, V);
|
||||||
float e = Vec3::Dot(V, V);
|
float e = dot(V, V);
|
||||||
bool sep1 = d * d > rr * e;
|
bool sep1 = d * d > rr * e;
|
||||||
|
|
||||||
// Testing if sphere lies outside a triangle vertex
|
// Testing if sphere lies outside a triangle vertex
|
||||||
float aa = Vec3::Dot(A, A);
|
float aa = dot(A, A);
|
||||||
float ab = Vec3::Dot(A, B);
|
float ab = dot(A, B);
|
||||||
float ac = Vec3::Dot(A, C);
|
float ac = dot(A, C);
|
||||||
float bb = Vec3::Dot(B, B);
|
float bb = dot(B, B);
|
||||||
float bc = Vec3::Dot(B, C);
|
float bc = dot(B, C);
|
||||||
float cc = Vec3::Dot(C, C);
|
float cc = dot(C, C);
|
||||||
bool sep2 = (aa > rr) && (ab > aa) && (ac > aa);
|
bool sep2 = (aa > rr) && (ab > aa) && (ac > aa);
|
||||||
bool sep3 = (bb > rr) && (ab > bb) && (bc > bb);
|
bool sep3 = (bb > rr) && (ab > bb) && (bc > bb);
|
||||||
bool sep4 = (cc > rr) && (ac > cc) && (bc > cc);
|
bool sep4 = (cc > rr) && (ac > cc) && (bc > cc);
|
||||||
|
|
||||||
// Testing if sphere lies outside a triangle edge
|
// Testing if sphere lies outside a triangle edge
|
||||||
Vec3 AB = B - A;
|
vec3 AB = B - A;
|
||||||
Vec3 BC = C - B;
|
vec3 BC = C - B;
|
||||||
Vec3 CA = A - C;
|
vec3 CA = A - C;
|
||||||
float d1 = ab - aa;
|
float d1 = ab - aa;
|
||||||
float d2 = bc - bb;
|
float d2 = bc - bb;
|
||||||
float d3 = ac - cc;
|
float d3 = ac - cc;
|
||||||
float e1 = Vec3::Dot(AB, AB);
|
float e1 = dot(AB, AB);
|
||||||
float e2 = Vec3::Dot(BC, BC);
|
float e2 = dot(BC, BC);
|
||||||
float e3 = Vec3::Dot(CA, CA);
|
float e3 = dot(CA, CA);
|
||||||
Vec3 Q1 = A * e1 - AB * d1;
|
vec3 Q1 = A * e1 - AB * d1;
|
||||||
Vec3 Q2 = B * e2 - BC * d2;
|
vec3 Q2 = B * e2 - BC * d2;
|
||||||
Vec3 Q3 = C * e3 - CA * d3;
|
vec3 Q3 = C * e3 - CA * d3;
|
||||||
Vec3 QC = C * e1 - Q1;
|
vec3 QC = C * e1 - Q1;
|
||||||
Vec3 QA = A * e2 - Q2;
|
vec3 QA = A * e2 - Q2;
|
||||||
Vec3 QB = B * e3 - Q3;
|
vec3 QB = B * e3 - Q3;
|
||||||
bool sep5 = (Vec3::Dot(Q1, Q1) > rr * e1 * e1) && (Vec3::Dot(Q1, QC) > 0.0f);
|
bool sep5 = (dot(Q1, Q1) > rr * e1 * e1) && (dot(Q1, QC) > 0.0f);
|
||||||
bool sep6 = (Vec3::Dot(Q2, Q2) > rr * e2 * e2) && (Vec3::Dot(Q2, QA) > 0.0f);
|
bool sep6 = (dot(Q2, Q2) > rr * e2 * e2) && (dot(Q2, QA) > 0.0f);
|
||||||
bool sep7 = (Vec3::Dot(Q3, Q3) > rr * e3 * e3) && (Vec3::Dot(Q3, QB) > 0.0f);
|
bool sep7 = (dot(Q3, Q3) > rr * e3 * e3) && (dot(Q3, QB) > 0.0f);
|
||||||
|
|
||||||
bool separated = sep1 || sep2 || sep3 || sep4 || sep5 || sep6 || sep7;
|
bool separated = sep1 || sep2 || sep3 || sep4 || sep5 || sep6 || sep7;
|
||||||
return (!separated);
|
return (!separated);
|
||||||
|
@ -541,7 +541,7 @@ bool TriangleMeshShape::is_leaf(int node_index)
|
||||||
|
|
||||||
float TriangleMeshShape::volume(int node_index)
|
float TriangleMeshShape::volume(int node_index)
|
||||||
{
|
{
|
||||||
const Vec3 &extents = nodes[node_index].aabb.Extents;
|
const vec3 &extents = nodes[node_index].aabb.Extents;
|
||||||
return extents.x * extents.y * extents.z;
|
return extents.x * extents.y * extents.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,14 +591,14 @@ float TriangleMeshShape::get_balanced_depth() const
|
||||||
return std::log2((float)(num_elements / 3));
|
return std::log2((float)(num_elements / 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const Vec3 *centroids, int *work_buffer)
|
int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const vec3 *centroids, int *work_buffer)
|
||||||
{
|
{
|
||||||
if (num_triangles == 0)
|
if (num_triangles == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Find bounding box and median of the triangle centroids
|
// Find bounding box and median of the triangle centroids
|
||||||
Vec3 median;
|
vec3 median;
|
||||||
Vec3 min, max;
|
vec3 min, max;
|
||||||
min = vertices[elements[triangles[0] * 3]];
|
min = vertices[elements[triangles[0] * 3]];
|
||||||
max = min;
|
max = min;
|
||||||
for (int i = 0; i < num_triangles; i++)
|
for (int i = 0; i < num_triangles; i++)
|
||||||
|
@ -606,7 +606,7 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const Vec3 *
|
||||||
int element_index = triangles[i] * 3;
|
int element_index = triangles[i] * 3;
|
||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
const Vec3 &vertex = vertices[elements[element_index + j]];
|
const vec3 &vertex = vertices[elements[element_index + j]];
|
||||||
|
|
||||||
min.x = std::min(min.x, vertex.x);
|
min.x = std::min(min.x, vertex.x);
|
||||||
min.y = std::min(min.y, vertex.y);
|
min.y = std::min(min.y, vertex.y);
|
||||||
|
@ -640,18 +640,18 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const Vec3 *
|
||||||
|
|
||||||
// Try split at longest axis, then if that fails the next longest, and then the remaining one
|
// Try split at longest axis, then if that fails the next longest, and then the remaining one
|
||||||
int left_count, right_count;
|
int left_count, right_count;
|
||||||
Vec3 axis;
|
vec3 axis;
|
||||||
for (int attempt = 0; attempt < 3; attempt++)
|
for (int attempt = 0; attempt < 3; attempt++)
|
||||||
{
|
{
|
||||||
// Find the split plane for axis
|
// Find the split plane for axis
|
||||||
switch (axis_order[attempt])
|
switch (axis_order[attempt])
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case 0: axis = Vec3(1.0f, 0.0f, 0.0f); break;
|
case 0: axis = vec3(1.0f, 0.0f, 0.0f); break;
|
||||||
case 1: axis = Vec3(0.0f, 1.0f, 0.0f); break;
|
case 1: axis = vec3(0.0f, 1.0f, 0.0f); break;
|
||||||
case 2: axis = Vec3(0.0f, 0.0f, 1.0f); break;
|
case 2: axis = vec3(0.0f, 0.0f, 1.0f); break;
|
||||||
}
|
}
|
||||||
Vec4 plane(axis, -Vec3::Dot(median, axis));
|
vec4 plane(axis, -dot(median, axis));
|
||||||
|
|
||||||
// Split triangles into two
|
// Split triangles into two
|
||||||
left_count = 0;
|
left_count = 0;
|
||||||
|
@ -661,7 +661,7 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const Vec3 *
|
||||||
int triangle = triangles[i];
|
int triangle = triangles[i];
|
||||||
int element_index = triangle * 3;
|
int element_index = triangle * 3;
|
||||||
|
|
||||||
float side = Vec4::Dot(Vec4(centroids[triangles[i]], 1.0f), plane);
|
float side = dot(vec4(centroids[triangles[i]], 1.0f), plane);
|
||||||
if (side >= 0.0f)
|
if (side >= 0.0f)
|
||||||
{
|
{
|
||||||
work_buffer[left_count] = triangle;
|
work_buffer[left_count] = triangle;
|
||||||
|
@ -707,10 +707,10 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const Vec3 *
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IntersectionTest::Result IntersectionTest::plane_aabb(const Vec4 &plane, const BBox &aabb)
|
IntersectionTest::Result IntersectionTest::plane_aabb(const vec4 &plane, const BBox &aabb)
|
||||||
{
|
{
|
||||||
Vec3 center = aabb.Center();
|
vec3 center = aabb.Center();
|
||||||
Vec3 extents = aabb.Extents();
|
vec3 extents = aabb.Extents();
|
||||||
float e = extents.x * std::abs(plane.x) + extents.y * std::abs(plane.y) + extents.z * std::abs(plane.z);
|
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;
|
float s = center.x * plane.x + center.y * plane.y + center.z * plane.z + plane.w;
|
||||||
if (s - e > 0)
|
if (s - e > 0)
|
||||||
|
@ -721,12 +721,12 @@ IntersectionTest::Result IntersectionTest::plane_aabb(const Vec4 &plane, const B
|
||||||
return intersecting;
|
return intersecting;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntersectionTest::Result IntersectionTest::plane_obb(const Vec4 &plane, const OrientedBBox &obb)
|
IntersectionTest::Result IntersectionTest::plane_obb(const vec4 &plane, const OrientedBBox &obb)
|
||||||
{
|
{
|
||||||
Vec3 n = plane.ToVec3();
|
vec3 n = plane.xyz();
|
||||||
float d = plane.w;
|
float d = plane.w;
|
||||||
float e = obb.Extents.x * std::abs(Vec3::Dot(obb.axis_x, n)) + obb.Extents.y * std::abs(Vec3::Dot(obb.axis_y, n)) + obb.Extents.z * std::abs(Vec3::Dot(obb.axis_z, n));
|
float e = obb.Extents.x * std::abs(dot(obb.axis_x, n)) + obb.Extents.y * std::abs(dot(obb.axis_y, n)) + obb.Extents.z * std::abs(dot(obb.axis_z, n));
|
||||||
float s = Vec3::Dot(obb.Center, n) + d;
|
float s = dot(obb.Center, n) + d;
|
||||||
if (s - e > 0)
|
if (s - e > 0)
|
||||||
return inside;
|
return inside;
|
||||||
else if (s + e < 0)
|
else if (s + e < 0)
|
||||||
|
@ -735,10 +735,10 @@ IntersectionTest::Result IntersectionTest::plane_obb(const Vec4 &plane, const Or
|
||||||
return intersecting;
|
return intersecting;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntersectionTest::OverlapResult IntersectionTest::sphere(const Vec3 ¢er1, float radius1, const Vec3 ¢er2, float radius2)
|
IntersectionTest::OverlapResult IntersectionTest::sphere(const vec3 ¢er1, float radius1, const vec3 ¢er2, float radius2)
|
||||||
{
|
{
|
||||||
Vec3 h = center1 - center2;
|
vec3 h = center1 - center2;
|
||||||
float square_distance = Vec3::Dot(h, h);
|
float square_distance = dot(h, h);
|
||||||
float radius_sum = radius1 + radius2;
|
float radius_sum = radius1 + radius2;
|
||||||
if (square_distance > radius_sum * radius_sum)
|
if (square_distance > radius_sum * radius_sum)
|
||||||
return disjoint;
|
return disjoint;
|
||||||
|
@ -746,18 +746,18 @@ IntersectionTest::OverlapResult IntersectionTest::sphere(const Vec3 ¢er1, fl
|
||||||
return overlap;
|
return overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntersectionTest::OverlapResult IntersectionTest::sphere_aabb(const Vec3 ¢er, float radius, const BBox &aabb)
|
IntersectionTest::OverlapResult IntersectionTest::sphere_aabb(const vec3 ¢er, float radius, const BBox &aabb)
|
||||||
{
|
{
|
||||||
Vec3 a = aabb.min - center;
|
vec3 a = aabb.min - center;
|
||||||
Vec3 b = center - aabb.max;
|
vec3 b = center - aabb.max;
|
||||||
a.x = std::max(a.x, 0.0f);
|
a.x = std::max(a.x, 0.0f);
|
||||||
a.y = std::max(a.y, 0.0f);
|
a.y = std::max(a.y, 0.0f);
|
||||||
a.z = std::max(a.z, 0.0f);
|
a.z = std::max(a.z, 0.0f);
|
||||||
b.x = std::max(b.x, 0.0f);
|
b.x = std::max(b.x, 0.0f);
|
||||||
b.y = std::max(b.y, 0.0f);
|
b.y = std::max(b.y, 0.0f);
|
||||||
b.z = std::max(b.z, 0.0f);
|
b.z = std::max(b.z, 0.0f);
|
||||||
Vec3 e = a + b;
|
vec3 e = a + b;
|
||||||
float d = Vec3::Dot(e, e);
|
float d = dot(e, e);
|
||||||
if (d > radius * radius)
|
if (d > radius * radius)
|
||||||
return disjoint;
|
return disjoint;
|
||||||
else
|
else
|
||||||
|
@ -847,9 +847,9 @@ IntersectionTest::OverlapResult IntersectionTest::ray_aabb(const RayBBox &ray, c
|
||||||
return (mask & 7) ? disjoint : overlap;
|
return (mask & 7) ? disjoint : overlap;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
const Vec3 &v = ray.v;
|
const vec3 &v = ray.v;
|
||||||
const Vec3 &w = ray.w;
|
const vec3 &w = ray.w;
|
||||||
const Vec3 &h = aabb.Extents;
|
const vec3 &h = aabb.Extents;
|
||||||
auto c = ray.c - aabb.Center;
|
auto c = ray.c - aabb.Center;
|
||||||
|
|
||||||
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)
|
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)
|
||||||
|
@ -870,7 +870,7 @@ FrustumPlanes::FrustumPlanes()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FrustumPlanes::FrustumPlanes(const Mat4 &world_to_projection)
|
FrustumPlanes::FrustumPlanes(const mat4 &world_to_projection)
|
||||||
{
|
{
|
||||||
planes[0] = near_frustum_plane(world_to_projection);
|
planes[0] = near_frustum_plane(world_to_projection);
|
||||||
planes[1] = far_frustum_plane(world_to_projection);
|
planes[1] = far_frustum_plane(world_to_projection);
|
||||||
|
@ -880,68 +880,68 @@ FrustumPlanes::FrustumPlanes(const Mat4 &world_to_projection)
|
||||||
planes[5] = bottom_frustum_plane(world_to_projection);
|
planes[5] = bottom_frustum_plane(world_to_projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 FrustumPlanes::left_frustum_plane(const Mat4 &matrix)
|
vec4 FrustumPlanes::left_frustum_plane(const mat4 &matrix)
|
||||||
{
|
{
|
||||||
Vec4 plane(
|
vec4 plane(
|
||||||
matrix[3 + 0 * 4] + matrix[0 + 0 * 4],
|
matrix[3 + 0 * 4] + matrix[0 + 0 * 4],
|
||||||
matrix[3 + 1 * 4] + matrix[0 + 1 * 4],
|
matrix[3 + 1 * 4] + matrix[0 + 1 * 4],
|
||||||
matrix[3 + 2 * 4] + matrix[0 + 2 * 4],
|
matrix[3 + 2 * 4] + matrix[0 + 2 * 4],
|
||||||
matrix[3 + 3 * 4] + matrix[0 + 3 * 4]);
|
matrix[3 + 3 * 4] + matrix[0 + 3 * 4]);
|
||||||
plane /= plane.ToVec3().Length();
|
plane /= length(plane.xyz());
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 FrustumPlanes::right_frustum_plane(const Mat4 &matrix)
|
vec4 FrustumPlanes::right_frustum_plane(const mat4 &matrix)
|
||||||
{
|
{
|
||||||
Vec4 plane(
|
vec4 plane(
|
||||||
matrix[3 + 0 * 4] - matrix[0 + 0 * 4],
|
matrix[3 + 0 * 4] - matrix[0 + 0 * 4],
|
||||||
matrix[3 + 1 * 4] - matrix[0 + 1 * 4],
|
matrix[3 + 1 * 4] - matrix[0 + 1 * 4],
|
||||||
matrix[3 + 2 * 4] - matrix[0 + 2 * 4],
|
matrix[3 + 2 * 4] - matrix[0 + 2 * 4],
|
||||||
matrix[3 + 3 * 4] - matrix[0 + 3 * 4]);
|
matrix[3 + 3 * 4] - matrix[0 + 3 * 4]);
|
||||||
plane /= plane.ToVec3().Length();
|
plane /= length(plane.xyz());
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 FrustumPlanes::top_frustum_plane(const Mat4 &matrix)
|
vec4 FrustumPlanes::top_frustum_plane(const mat4 &matrix)
|
||||||
{
|
{
|
||||||
Vec4 plane(
|
vec4 plane(
|
||||||
matrix[3 + 0 * 4] - matrix[1 + 0 * 4],
|
matrix[3 + 0 * 4] - matrix[1 + 0 * 4],
|
||||||
matrix[3 + 1 * 4] - matrix[1 + 1 * 4],
|
matrix[3 + 1 * 4] - matrix[1 + 1 * 4],
|
||||||
matrix[3 + 2 * 4] - matrix[1 + 2 * 4],
|
matrix[3 + 2 * 4] - matrix[1 + 2 * 4],
|
||||||
matrix[3 + 3 * 4] - matrix[1 + 3 * 4]);
|
matrix[3 + 3 * 4] - matrix[1 + 3 * 4]);
|
||||||
plane /= plane.ToVec3().Length();
|
plane /= length(plane.xyz());
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 FrustumPlanes::bottom_frustum_plane(const Mat4 &matrix)
|
vec4 FrustumPlanes::bottom_frustum_plane(const mat4 &matrix)
|
||||||
{
|
{
|
||||||
Vec4 plane(
|
vec4 plane(
|
||||||
matrix[3 + 0 * 4] + matrix[1 + 0 * 4],
|
matrix[3 + 0 * 4] + matrix[1 + 0 * 4],
|
||||||
matrix[3 + 1 * 4] + matrix[1 + 1 * 4],
|
matrix[3 + 1 * 4] + matrix[1 + 1 * 4],
|
||||||
matrix[3 + 2 * 4] + matrix[1 + 2 * 4],
|
matrix[3 + 2 * 4] + matrix[1 + 2 * 4],
|
||||||
matrix[3 + 3 * 4] + matrix[1 + 3 * 4]);
|
matrix[3 + 3 * 4] + matrix[1 + 3 * 4]);
|
||||||
plane /= plane.ToVec3().Length();
|
plane /= length(plane.xyz());
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 FrustumPlanes::near_frustum_plane(const Mat4 &matrix)
|
vec4 FrustumPlanes::near_frustum_plane(const mat4 &matrix)
|
||||||
{
|
{
|
||||||
Vec4 plane(
|
vec4 plane(
|
||||||
matrix[3 + 0 * 4] + matrix[2 + 0 * 4],
|
matrix[3 + 0 * 4] + matrix[2 + 0 * 4],
|
||||||
matrix[3 + 1 * 4] + matrix[2 + 1 * 4],
|
matrix[3 + 1 * 4] + matrix[2 + 1 * 4],
|
||||||
matrix[3 + 2 * 4] + matrix[2 + 2 * 4],
|
matrix[3 + 2 * 4] + matrix[2 + 2 * 4],
|
||||||
matrix[3 + 3 * 4] + matrix[2 + 3 * 4]);
|
matrix[3 + 3 * 4] + matrix[2 + 3 * 4]);
|
||||||
plane /= plane.ToVec3().Length();
|
plane /= length(plane.xyz());
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 FrustumPlanes::far_frustum_plane(const Mat4 &matrix)
|
vec4 FrustumPlanes::far_frustum_plane(const mat4 &matrix)
|
||||||
{
|
{
|
||||||
Vec4 plane(
|
vec4 plane(
|
||||||
matrix[3 + 0 * 4] - matrix[2 + 0 * 4],
|
matrix[3 + 0 * 4] - matrix[2 + 0 * 4],
|
||||||
matrix[3 + 1 * 4] - matrix[2 + 1 * 4],
|
matrix[3 + 1 * 4] - matrix[2 + 1 * 4],
|
||||||
matrix[3 + 2 * 4] - matrix[2 + 2 * 4],
|
matrix[3 + 2 * 4] - matrix[2 + 2 * 4],
|
||||||
matrix[3 + 3 * 4] - matrix[2 + 3 * 4]);
|
matrix[3 + 3 * 4] - matrix[2 + 3 * 4]);
|
||||||
plane /= plane.ToVec3().Length();
|
plane /= length(plane.xyz());
|
||||||
return plane;
|
return plane;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ class SphereShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SphereShape() { }
|
SphereShape() { }
|
||||||
SphereShape(const Vec3 ¢er, float radius) : center(center), radius(radius) { }
|
SphereShape(const vec3 ¢er, float radius) : center(center), radius(radius) { }
|
||||||
|
|
||||||
Vec3 center;
|
vec3 center;
|
||||||
float radius = 0.0f;
|
float radius = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class CollisionBBox : public BBox
|
||||||
public:
|
public:
|
||||||
CollisionBBox() = default;
|
CollisionBBox() = default;
|
||||||
|
|
||||||
CollisionBBox(const Vec3 &aabb_min, const Vec3 &aabb_max) : BBox(aabb_min, aabb_max)
|
CollisionBBox(const vec3 &aabb_min, const vec3 &aabb_max) : BBox(aabb_min, aabb_max)
|
||||||
{
|
{
|
||||||
auto halfmin = aabb_min * 0.5f;
|
auto halfmin = aabb_min * 0.5f;
|
||||||
auto halfmax = aabb_max * 0.5f;
|
auto halfmax = aabb_max * 0.5f;
|
||||||
|
@ -57,15 +57,15 @@ public:
|
||||||
Extents = halfmax - halfmin;
|
Extents = halfmax - halfmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 Center;
|
vec3 Center;
|
||||||
Vec3 Extents;
|
vec3 Extents;
|
||||||
float ssePadding = 0.0f; // Needed to safely load Extents directly into a sse register
|
float ssePadding = 0.0f; // Needed to safely load Extents directly into a sse register
|
||||||
};
|
};
|
||||||
|
|
||||||
class RayBBox
|
class RayBBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RayBBox(const Vec3 &ray_start, const Vec3 &ray_end) : start(ray_start), end(ray_end)
|
RayBBox(const vec3 &ray_start, const vec3 &ray_end) : start(ray_start), end(ray_end)
|
||||||
{
|
{
|
||||||
c = (ray_start + ray_end) * 0.5f;
|
c = (ray_start + ray_end) * 0.5f;
|
||||||
w = ray_end - c;
|
w = ray_end - c;
|
||||||
|
@ -74,15 +74,15 @@ public:
|
||||||
v.z = std::abs(w.z);
|
v.z = std::abs(w.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 start, end;
|
vec3 start, end;
|
||||||
Vec3 c, w, v;
|
vec3 c, w, v;
|
||||||
float ssePadding = 0.0f; // Needed to safely load v directly into a sse register
|
float ssePadding = 0.0f; // Needed to safely load v directly into a sse register
|
||||||
};
|
};
|
||||||
|
|
||||||
class TriangleMeshShape
|
class TriangleMeshShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TriangleMeshShape(const Vec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements);
|
TriangleMeshShape(const vec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements);
|
||||||
|
|
||||||
int get_min_depth() const;
|
int get_min_depth() const;
|
||||||
int get_max_depth() const;
|
int get_max_depth() const;
|
||||||
|
@ -91,20 +91,20 @@ public:
|
||||||
|
|
||||||
const CollisionBBox &get_bbox() const { return nodes[root].aabb; }
|
const CollisionBBox &get_bbox() const { return nodes[root].aabb; }
|
||||||
|
|
||||||
static float sweep(TriangleMeshShape *shape1, SphereShape *shape2, const Vec3 &target);
|
static float sweep(TriangleMeshShape *shape1, SphereShape *shape2, const vec3 &target);
|
||||||
|
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, TriangleMeshShape *shape2);
|
static bool find_any_hit(TriangleMeshShape *shape1, TriangleMeshShape *shape2);
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2);
|
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2);
|
||||||
static bool find_any_hit(TriangleMeshShape *shape, const Vec3 &ray_start, const Vec3 &ray_end);
|
static bool find_any_hit(TriangleMeshShape *shape, const vec3 &ray_start, const vec3 &ray_end);
|
||||||
|
|
||||||
static TraceHit find_first_hit(TriangleMeshShape *shape, const Vec3 &ray_start, const Vec3 &ray_end);
|
static TraceHit find_first_hit(TriangleMeshShape *shape, const vec3 &ray_start, const vec3 &ray_end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
Node() = default;
|
Node() = default;
|
||||||
Node(const Vec3 &aabb_min, const Vec3 &aabb_max, int element_index) : aabb(aabb_min, aabb_max), element_index(element_index) { }
|
Node(const vec3 &aabb_min, const vec3 &aabb_max, int element_index) : aabb(aabb_min, aabb_max), element_index(element_index) { }
|
||||||
Node(const Vec3 &aabb_min, const Vec3 &aabb_max, int left, int right) : aabb(aabb_min, aabb_max), left(left), right(right) { }
|
Node(const vec3 &aabb_min, const vec3 &aabb_max, int left, int right) : aabb(aabb_min, aabb_max), left(left), right(right) { }
|
||||||
|
|
||||||
CollisionBBox aabb;
|
CollisionBBox aabb;
|
||||||
int left = -1;
|
int left = -1;
|
||||||
|
@ -112,7 +112,7 @@ private:
|
||||||
int element_index = -1;
|
int element_index = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vec3 *vertices = nullptr;
|
const vec3 *vertices = nullptr;
|
||||||
const int num_vertices = 0;
|
const int num_vertices = 0;
|
||||||
const unsigned int *elements = nullptr;
|
const unsigned int *elements = nullptr;
|
||||||
int num_elements = 0;
|
int num_elements = 0;
|
||||||
|
@ -120,7 +120,7 @@ private:
|
||||||
std::vector<Node> nodes;
|
std::vector<Node> nodes;
|
||||||
int root = -1;
|
int root = -1;
|
||||||
|
|
||||||
static float sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const Vec3 &target);
|
static float sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const vec3 &target);
|
||||||
|
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, TriangleMeshShape *shape2, int a, int b);
|
static bool find_any_hit(TriangleMeshShape *shape1, TriangleMeshShape *shape2, int a, int b);
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2, int a);
|
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2, int a);
|
||||||
|
@ -131,8 +131,8 @@ private:
|
||||||
inline static bool overlap_bv_ray(TriangleMeshShape *shape, const RayBBox &ray, int a);
|
inline static bool overlap_bv_ray(TriangleMeshShape *shape, const RayBBox &ray, int a);
|
||||||
inline static float intersect_triangle_ray(TriangleMeshShape *shape, const RayBBox &ray, int a, float &barycentricB, float &barycentricC);
|
inline static float intersect_triangle_ray(TriangleMeshShape *shape, const RayBBox &ray, int a, float &barycentricB, float &barycentricC);
|
||||||
|
|
||||||
inline static bool sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const Vec3 &target);
|
inline static bool sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const vec3 &target);
|
||||||
inline static float sweep_intersect_triangle_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const Vec3 &target);
|
inline static float sweep_intersect_triangle_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const vec3 &target);
|
||||||
|
|
||||||
inline static bool overlap_bv(TriangleMeshShape *shape1, TriangleMeshShape *shape2, int a, int b);
|
inline static bool overlap_bv(TriangleMeshShape *shape1, TriangleMeshShape *shape2, int a, int b);
|
||||||
inline static bool overlap_bv_triangle(TriangleMeshShape *shape1, TriangleMeshShape *shape2, int a, int b);
|
inline static bool overlap_bv_triangle(TriangleMeshShape *shape1, TriangleMeshShape *shape2, int a, int b);
|
||||||
|
@ -143,34 +143,34 @@ private:
|
||||||
inline bool is_leaf(int node_index);
|
inline bool is_leaf(int node_index);
|
||||||
inline float volume(int node_index);
|
inline float volume(int node_index);
|
||||||
|
|
||||||
int subdivide(int *triangles, int num_triangles, const Vec3 *centroids, int *work_buffer);
|
int subdivide(int *triangles, int num_triangles, const vec3 *centroids, int *work_buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
class OrientedBBox
|
class OrientedBBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Vec3 Center;
|
vec3 Center;
|
||||||
Vec3 Extents;
|
vec3 Extents;
|
||||||
Vec3 axis_x;
|
vec3 axis_x;
|
||||||
Vec3 axis_y;
|
vec3 axis_y;
|
||||||
Vec3 axis_z;
|
vec3 axis_z;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrustumPlanes
|
class FrustumPlanes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FrustumPlanes();
|
FrustumPlanes();
|
||||||
explicit FrustumPlanes(const Mat4 &world_to_projection);
|
explicit FrustumPlanes(const mat4 &world_to_projection);
|
||||||
|
|
||||||
Vec4 planes[6];
|
vec4 planes[6];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Vec4 left_frustum_plane(const Mat4 &matrix);
|
static vec4 left_frustum_plane(const mat4 &matrix);
|
||||||
static Vec4 right_frustum_plane(const Mat4 &matrix);
|
static vec4 right_frustum_plane(const mat4 &matrix);
|
||||||
static Vec4 top_frustum_plane(const Mat4 &matrix);
|
static vec4 top_frustum_plane(const mat4 &matrix);
|
||||||
static Vec4 bottom_frustum_plane(const Mat4 &matrix);
|
static vec4 bottom_frustum_plane(const mat4 &matrix);
|
||||||
static Vec4 near_frustum_plane(const Mat4 &matrix);
|
static vec4 near_frustum_plane(const mat4 &matrix);
|
||||||
static Vec4 far_frustum_plane(const Mat4 &matrix);
|
static vec4 far_frustum_plane(const mat4 &matrix);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IntersectionTest
|
class IntersectionTest
|
||||||
|
@ -189,10 +189,10 @@ public:
|
||||||
overlap
|
overlap
|
||||||
};
|
};
|
||||||
|
|
||||||
static Result plane_aabb(const Vec4 &plane, const BBox &aabb);
|
static Result plane_aabb(const vec4 &plane, const BBox &aabb);
|
||||||
static Result plane_obb(const Vec4 &plane, const OrientedBBox &obb);
|
static Result plane_obb(const vec4 &plane, const OrientedBBox &obb);
|
||||||
static OverlapResult sphere(const Vec3 ¢er1, float radius1, const Vec3 ¢er2, float radius2);
|
static OverlapResult sphere(const vec3 ¢er1, float radius1, const vec3 ¢er2, float radius2);
|
||||||
static OverlapResult sphere_aabb(const Vec3 ¢er, float radius, const BBox &aabb);
|
static OverlapResult sphere_aabb(const vec3 ¢er, float radius, const BBox &aabb);
|
||||||
static OverlapResult aabb(const BBox &a, const BBox &b);
|
static OverlapResult aabb(const BBox &a, const BBox &b);
|
||||||
static Result frustum_aabb(const FrustumPlanes &frustum, const BBox &box);
|
static Result frustum_aabb(const FrustumPlanes &frustum, const BBox &box);
|
||||||
static Result frustum_obb(const FrustumPlanes &frustum, const OrientedBBox &box);
|
static Result frustum_obb(const FrustumPlanes &frustum, const OrientedBBox &box);
|
||||||
|
|
|
@ -73,7 +73,7 @@ void CPURaytracer::RaytraceTask(const CPUTraceTask& task)
|
||||||
if (task.id >= 0)
|
if (task.id >= 0)
|
||||||
{
|
{
|
||||||
Surface* surface = mesh->surfaces[task.id].get();
|
Surface* surface = mesh->surfaces[task.id].get();
|
||||||
Vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
||||||
state.StartPosition = pos;
|
state.StartPosition = pos;
|
||||||
state.StartSurface = surface;
|
state.StartSurface = surface;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ void CPURaytracer::RaytraceTask(const CPUTraceTask& task)
|
||||||
|
|
||||||
void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
||||||
{
|
{
|
||||||
Vec3 origin;
|
vec3 origin;
|
||||||
Surface* surface;
|
Surface* surface;
|
||||||
if (state.PassType == 2)
|
if (state.PassType == 2)
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,7 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
||||||
surface = state.StartSurface;
|
surface = state.StartSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 incoming(0.0f, 0.0f, 0.0f);
|
vec3 incoming(0.0f, 0.0f, 0.0f);
|
||||||
float incomingAttenuation = 1.0f;
|
float incomingAttenuation = 1.0f;
|
||||||
|
|
||||||
if (state.PassType == 0)
|
if (state.PassType == 0)
|
||||||
|
@ -166,7 +166,7 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
||||||
if (state.PassType == 1)
|
if (state.PassType == 1)
|
||||||
incomingAttenuation = 1.0f / float(state.SampleCount);
|
incomingAttenuation = 1.0f / float(state.SampleCount);
|
||||||
|
|
||||||
Vec3 normal;
|
vec3 normal;
|
||||||
if (surface)
|
if (surface)
|
||||||
{
|
{
|
||||||
normal = surface->plane.Normal();
|
normal = surface->plane.Normal();
|
||||||
|
@ -175,19 +175,19 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
||||||
{
|
{
|
||||||
switch (state.SampleIndex % 6)
|
switch (state.SampleIndex % 6)
|
||||||
{
|
{
|
||||||
case 0: normal = Vec3( 1.0f, 0.0f, 0.0f); break;
|
case 0: normal = vec3( 1.0f, 0.0f, 0.0f); break;
|
||||||
case 1: normal = Vec3(-1.0f, 0.0f, 0.0f); break;
|
case 1: normal = vec3(-1.0f, 0.0f, 0.0f); break;
|
||||||
case 2: normal = Vec3( 0.0f, 1.0f, 0.0f); break;
|
case 2: normal = vec3( 0.0f, 1.0f, 0.0f); break;
|
||||||
case 3: normal = Vec3( 0.0f, -1.0f, 0.0f); break;
|
case 3: normal = vec3( 0.0f, -1.0f, 0.0f); break;
|
||||||
case 4: normal = Vec3( 0.0f, 0.0f, 1.0f); break;
|
case 4: normal = vec3( 0.0f, 0.0f, 1.0f); break;
|
||||||
case 5: normal = Vec3( 0.0f, 0.0f, -1.0f); break;
|
case 5: normal = vec3( 0.0f, 0.0f, -1.0f); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 H = ImportanceSample(state.HemisphereVec, normal);
|
vec3 H = ImportanceSample(state.HemisphereVec, normal);
|
||||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
vec3 L = normalize(H * (2.0f * dot(normal, H)) - normal);
|
||||||
|
|
||||||
float NdotL = std::max(Vec3::Dot(normal, L), 0.0f);
|
float NdotL = std::max(dot(normal, L), 0.0f);
|
||||||
|
|
||||||
const float p = (float)(1 / (2 * 3.14159265359));
|
const float p = (float)(1 / (2 * 3.14159265359));
|
||||||
incomingAttenuation *= NdotL / p;
|
incomingAttenuation *= NdotL / p;
|
||||||
|
@ -195,19 +195,19 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
||||||
state.EndTrace = true;
|
state.EndTrace = true;
|
||||||
if (NdotL > 0.0f)
|
if (NdotL > 0.0f)
|
||||||
{
|
{
|
||||||
Vec3 start = origin + normal * 0.1f;
|
vec3 start = origin + normal * 0.1f;
|
||||||
Vec3 end = start + L * 32768.0f;
|
vec3 end = start + L * 32768.0f;
|
||||||
LevelTraceHit hit = Trace(start, end);
|
LevelTraceHit hit = Trace(start, end);
|
||||||
if (hit.fraction < 1.0f)
|
if (hit.fraction < 1.0f)
|
||||||
{
|
{
|
||||||
state.EndTrace = false;
|
state.EndTrace = false;
|
||||||
surface = hit.hitSurface;
|
surface = hit.hitSurface;
|
||||||
Vec3 hitPosition = start * (1.0f - hit.fraction) + end * hit.fraction;
|
vec3 hitPosition = start * (1.0f - hit.fraction) + end * hit.fraction;
|
||||||
|
|
||||||
CPUEmissiveSurface emissive = GetEmissive(surface);
|
CPUEmissiveSurface emissive = GetEmissive(surface);
|
||||||
if (emissive.Distance > 0.0f)
|
if (emissive.Distance > 0.0f)
|
||||||
{
|
{
|
||||||
float hitDistance = (hitPosition - origin).Length();
|
float hitDistance = length(hitPosition - origin);
|
||||||
float attenuation = std::max(1.0f - (hitDistance / emissive.Distance), 0.0f);
|
float attenuation = std::max(1.0f - (hitDistance / emissive.Distance), 0.0f);
|
||||||
incoming += emissive.Color * (emissive.Intensity * attenuation * incomingAttenuation);
|
incoming += emissive.Color * (emissive.Intensity * attenuation * incomingAttenuation);
|
||||||
}
|
}
|
||||||
|
@ -227,15 +227,15 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
|
||||||
|
|
||||||
void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
||||||
{
|
{
|
||||||
Vec3 incoming = state.Output;
|
vec3 incoming = state.Output;
|
||||||
float incomingAttenuation = state.OutputAttenuation;
|
float incomingAttenuation = state.OutputAttenuation;
|
||||||
if (incomingAttenuation <= 0.0f)
|
if (incomingAttenuation <= 0.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Surface* surface = state.Surf;
|
Surface* surface = state.Surf;
|
||||||
|
|
||||||
Vec3 origin = state.Position;
|
vec3 origin = state.Position;
|
||||||
Vec3 normal;
|
vec3 normal;
|
||||||
if (surface)
|
if (surface)
|
||||||
{
|
{
|
||||||
normal = surface->plane.Normal();
|
normal = surface->plane.Normal();
|
||||||
|
@ -251,17 +251,17 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
||||||
float attenuation = 0.0f;
|
float attenuation = 0.0f;
|
||||||
if (state.PassType == 0 && surface)
|
if (state.PassType == 0 && surface)
|
||||||
{
|
{
|
||||||
Vec3 e0 = Vec3::Normalize(Vec3::Cross(normal, std::abs(normal.x) < std::abs(normal.y) ? Vec3(1.0f, 0.0f, 0.0f) : Vec3(0.0f, 1.0f, 0.0f)));
|
vec3 e0 = normalize(cross(normal, std::abs(normal.x) < std::abs(normal.y) ? vec3(1.0f, 0.0f, 0.0f) : vec3(0.0f, 1.0f, 0.0f)));
|
||||||
Vec3 e1 = Vec3::Cross(normal, e0);
|
vec3 e1 = cross(normal, e0);
|
||||||
e0 = Vec3::Cross(normal, e1);
|
e0 = cross(normal, e1);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < state.SampleCount; i++)
|
for (uint32_t i = 0; i < state.SampleCount; i++)
|
||||||
{
|
{
|
||||||
Vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
|
vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
|
||||||
Vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
|
vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
|
||||||
|
|
||||||
Vec3 start = origin2;
|
vec3 start = origin2;
|
||||||
Vec3 end = start + state.SunDir * dist;
|
vec3 end = start + state.SunDir * dist;
|
||||||
LevelTraceHit hit = Trace(start, end);
|
LevelTraceHit hit = Trace(start, end);
|
||||||
if (hit.fraction < 1.0f && hit.hitSurface->bSky)
|
if (hit.fraction < 1.0f && hit.hitSurface->bSky)
|
||||||
attenuation += 1.0f;
|
attenuation += 1.0f;
|
||||||
|
@ -270,8 +270,8 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vec3 start = origin;
|
vec3 start = origin;
|
||||||
Vec3 end = start + state.SunDir * dist;
|
vec3 end = start + state.SunDir * dist;
|
||||||
LevelTraceHit hit = Trace(start, end);
|
LevelTraceHit hit = Trace(start, end);
|
||||||
attenuation = (hit.fraction < 1.0f && hit.hitSurface->bSky) ? 1.0f : 0.0f;
|
attenuation = (hit.fraction < 1.0f && hit.hitSurface->bSky) ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
|
@ -282,21 +282,21 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
||||||
{
|
{
|
||||||
const CPULightInfo& light = Lights.data()[j]; // MSVC vector operator[] is very slow
|
const CPULightInfo& light = Lights.data()[j]; // MSVC vector operator[] is very slow
|
||||||
|
|
||||||
float dist = (light.Origin - origin).Length();
|
float dist = length(light.Origin - origin);
|
||||||
if (dist > minDistance && dist < light.Radius)
|
if (dist > minDistance && dist < light.Radius)
|
||||||
{
|
{
|
||||||
Vec3 dir = Vec3::Normalize(light.Origin - origin);
|
vec3 dir = normalize(light.Origin - origin);
|
||||||
|
|
||||||
float distAttenuation = std::max(1.0f - (dist / light.Radius), 0.0f);
|
float distAttenuation = std::max(1.0f - (dist / light.Radius), 0.0f);
|
||||||
float angleAttenuation = 1.0f;
|
float angleAttenuation = 1.0f;
|
||||||
if (surface)
|
if (surface)
|
||||||
{
|
{
|
||||||
angleAttenuation = std::max(Vec3::Dot(normal, dir), 0.0f);
|
angleAttenuation = std::max(dot(normal, dir), 0.0f);
|
||||||
}
|
}
|
||||||
float spotAttenuation = 1.0f;
|
float spotAttenuation = 1.0f;
|
||||||
if (light.OuterAngleCos > -1.0f)
|
if (light.OuterAngleCos > -1.0f)
|
||||||
{
|
{
|
||||||
float cosDir = Vec3::Dot(dir, light.SpotDir);
|
float cosDir = dot(dir, light.SpotDir);
|
||||||
spotAttenuation = smoothstep(light.OuterAngleCos, light.InnerAngleCos, cosDir);
|
spotAttenuation = smoothstep(light.OuterAngleCos, light.InnerAngleCos, cosDir);
|
||||||
spotAttenuation = std::max(spotAttenuation, 0.0f);
|
spotAttenuation = std::max(spotAttenuation, 0.0f);
|
||||||
}
|
}
|
||||||
|
@ -308,13 +308,13 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
||||||
|
|
||||||
if (state.PassType == 0 && surface)
|
if (state.PassType == 0 && surface)
|
||||||
{
|
{
|
||||||
Vec3 e0 = Vec3::Normalize(Vec3::Cross(normal, std::abs(normal.x) < std::abs(normal.y) ? Vec3(1.0f, 0.0f, 0.0f) : Vec3(0.0f, 1.0f, 0.0f)));
|
vec3 e0 = normalize(cross(normal, std::abs(normal.x) < std::abs(normal.y) ? vec3(1.0f, 0.0f, 0.0f) : vec3(0.0f, 1.0f, 0.0f)));
|
||||||
Vec3 e1 = Vec3::Cross(normal, e0);
|
vec3 e1 = cross(normal, e0);
|
||||||
e0 = Vec3::Cross(normal, e1);
|
e0 = cross(normal, e1);
|
||||||
for (uint32_t i = 0; i < state.SampleCount; i++)
|
for (uint32_t i = 0; i < state.SampleCount; i++)
|
||||||
{
|
{
|
||||||
Vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
|
vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
|
||||||
Vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
|
vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
|
||||||
|
|
||||||
LevelTraceHit hit = Trace(origin2, light.Origin);
|
LevelTraceHit hit = Trace(origin2, light.Origin);
|
||||||
if (hit.fraction == 1.0f)
|
if (hit.fraction == 1.0f)
|
||||||
|
@ -338,20 +338,20 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
|
||||||
state.Output = incoming;
|
state.Output = incoming;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 CPURaytracer::ImportanceSample(const Vec3& HemisphereVec, Vec3 N)
|
vec3 CPURaytracer::ImportanceSample(const vec3& HemisphereVec, vec3 N)
|
||||||
{
|
{
|
||||||
// from tangent-space vector to world-space sample vector
|
// from tangent-space vector to world-space sample vector
|
||||||
Vec3 up = std::abs(N.x) < std::abs(N.y) ? Vec3(1.0f, 0.0f, 0.0f) : Vec3(0.0f, 1.0f, 0.0f);
|
vec3 up = std::abs(N.x) < std::abs(N.y) ? vec3(1.0f, 0.0f, 0.0f) : vec3(0.0f, 1.0f, 0.0f);
|
||||||
Vec3 tangent = Vec3::Normalize(Vec3::Cross(up, N));
|
vec3 tangent = normalize(cross(up, N));
|
||||||
Vec3 bitangent = Vec3::Cross(N, tangent);
|
vec3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
Vec3 sampleVec = tangent * HemisphereVec.x + bitangent * HemisphereVec.y + N * HemisphereVec.z;
|
vec3 sampleVec = tangent * HemisphereVec.x + bitangent * HemisphereVec.y + N * HemisphereVec.z;
|
||||||
return Vec3::Normalize(sampleVec);
|
return normalize(sampleVec);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 CPURaytracer::Hammersley(uint32_t i, uint32_t N)
|
vec2 CPURaytracer::Hammersley(uint32_t i, uint32_t N)
|
||||||
{
|
{
|
||||||
return Vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
float CPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
float CPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
||||||
|
@ -371,12 +371,12 @@ void CPURaytracer::CreateHemisphereVectors()
|
||||||
HemisphereVectors.reserve(bounceSampleCount);
|
HemisphereVectors.reserve(bounceSampleCount);
|
||||||
for (int i = 0; i < bounceSampleCount; i++)
|
for (int i = 0; i < bounceSampleCount; i++)
|
||||||
{
|
{
|
||||||
Vec2 Xi = Hammersley(i, bounceSampleCount);
|
vec2 Xi = Hammersley(i, bounceSampleCount);
|
||||||
Vec3 H;
|
vec3 H;
|
||||||
H.x = Xi.x * 2.0f - 1.0f;
|
H.x = Xi.x * 2.0f - 1.0f;
|
||||||
H.y = Xi.y * 2.0f - 1.0f;
|
H.y = Xi.y * 2.0f - 1.0f;
|
||||||
H.z = RadicalInverse_VdC(i) + 0.01f;
|
H.z = RadicalInverse_VdC(i) + 0.01f;
|
||||||
H.Normalize();
|
H = normalize(H);
|
||||||
HemisphereVectors.push_back(H);
|
HemisphereVectors.push_back(H);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,13 +440,13 @@ CPUEmissiveSurface CPURaytracer::GetEmissive(Surface* surface)
|
||||||
{
|
{
|
||||||
info.Distance = 0.0f;
|
info.Distance = 0.0f;
|
||||||
info.Intensity = 0.0f;
|
info.Intensity = 0.0f;
|
||||||
info.Color = Vec3(0.0f, 0.0f, 0.0f);
|
info.Color = vec3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelTraceHit CPURaytracer::Trace(const Vec3& startVec, const Vec3& endVec)
|
LevelTraceHit CPURaytracer::Trace(const vec3& startVec, const vec3& endVec)
|
||||||
{
|
{
|
||||||
TraceHit hit = TriangleMeshShape::find_first_hit(CollisionMesh.get(), startVec, endVec);
|
TraceHit hit = TriangleMeshShape::find_first_hit(CollisionMesh.get(), startVec, endVec);
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ LevelTraceHit CPURaytracer::Trace(const Vec3& startVec, const Vec3& endVec)
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPURaytracer::TraceAnyHit(const Vec3& startVec, const Vec3& endVec)
|
bool CPURaytracer::TraceAnyHit(const vec3& startVec, const vec3& endVec)
|
||||||
{
|
{
|
||||||
return TriangleMeshShape::find_any_hit(CollisionMesh.get(), startVec, endVec);
|
return TriangleMeshShape::find_any_hit(CollisionMesh.get(), startVec, endVec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,13 @@ struct CPUTraceTask
|
||||||
|
|
||||||
struct CPULightInfo
|
struct CPULightInfo
|
||||||
{
|
{
|
||||||
Vec3 Origin;
|
vec3 Origin;
|
||||||
float Radius;
|
float Radius;
|
||||||
float Intensity;
|
float Intensity;
|
||||||
float InnerAngleCos;
|
float InnerAngleCos;
|
||||||
float OuterAngleCos;
|
float OuterAngleCos;
|
||||||
Vec3 SpotDir;
|
vec3 SpotDir;
|
||||||
Vec3 Color;
|
vec3 Color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CPUTraceState
|
struct CPUTraceState
|
||||||
|
@ -25,19 +25,19 @@ struct CPUTraceState
|
||||||
uint32_t SampleCount;
|
uint32_t SampleCount;
|
||||||
uint32_t PassType;
|
uint32_t PassType;
|
||||||
uint32_t LightCount;
|
uint32_t LightCount;
|
||||||
Vec3 SunDir;
|
vec3 SunDir;
|
||||||
float SampleDistance;
|
float SampleDistance;
|
||||||
Vec3 SunColor;
|
vec3 SunColor;
|
||||||
float SunIntensity;
|
float SunIntensity;
|
||||||
Vec3 HemisphereVec;
|
vec3 HemisphereVec;
|
||||||
|
|
||||||
Vec3 StartPosition;
|
vec3 StartPosition;
|
||||||
Surface* StartSurface;
|
Surface* StartSurface;
|
||||||
|
|
||||||
Vec3 Position;
|
vec3 Position;
|
||||||
Surface* Surf;
|
Surface* Surf;
|
||||||
|
|
||||||
Vec3 Output;
|
vec3 Output;
|
||||||
float OutputAttenuation;
|
float OutputAttenuation;
|
||||||
|
|
||||||
bool EndTrace;
|
bool EndTrace;
|
||||||
|
@ -47,13 +47,13 @@ struct CPUEmissiveSurface
|
||||||
{
|
{
|
||||||
float Distance;
|
float Distance;
|
||||||
float Intensity;
|
float Intensity;
|
||||||
Vec3 Color;
|
vec3 Color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LevelTraceHit
|
struct LevelTraceHit
|
||||||
{
|
{
|
||||||
Vec3 start;
|
vec3 start;
|
||||||
Vec3 end;
|
vec3 end;
|
||||||
float fraction;
|
float fraction;
|
||||||
|
|
||||||
Surface* hitSurface;
|
Surface* hitSurface;
|
||||||
|
@ -79,19 +79,19 @@ private:
|
||||||
void CreateHemisphereVectors();
|
void CreateHemisphereVectors();
|
||||||
void CreateLights();
|
void CreateLights();
|
||||||
|
|
||||||
LevelTraceHit Trace(const Vec3& startVec, const Vec3& endVec);
|
LevelTraceHit Trace(const vec3& startVec, const vec3& endVec);
|
||||||
bool TraceAnyHit(const Vec3& startVec, const Vec3& endVec);
|
bool TraceAnyHit(const vec3& startVec, const vec3& endVec);
|
||||||
|
|
||||||
static Vec3 ImportanceSample(const Vec3& HemisphereVec, Vec3 N);
|
static vec3 ImportanceSample(const vec3& HemisphereVec, vec3 N);
|
||||||
|
|
||||||
static float RadicalInverse_VdC(uint32_t bits);
|
static float RadicalInverse_VdC(uint32_t bits);
|
||||||
static Vec2 Hammersley(uint32_t i, uint32_t N);
|
static vec2 Hammersley(uint32_t i, uint32_t N);
|
||||||
|
|
||||||
const int coverageSampleCount = 256;
|
const int coverageSampleCount = 256;
|
||||||
const int bounceSampleCount = 2048;
|
const int bounceSampleCount = 2048;
|
||||||
|
|
||||||
LevelMesh* mesh = nullptr;
|
LevelMesh* mesh = nullptr;
|
||||||
std::vector<Vec3> HemisphereVectors;
|
std::vector<vec3> HemisphereVectors;
|
||||||
std::vector<CPULightInfo> Lights;
|
std::vector<CPULightInfo> Lights;
|
||||||
|
|
||||||
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
||||||
|
|
|
@ -73,16 +73,16 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Vec3> HemisphereVectors;
|
std::vector<vec3> HemisphereVectors;
|
||||||
HemisphereVectors.reserve(bounceSampleCount);
|
HemisphereVectors.reserve(bounceSampleCount);
|
||||||
for (int i = 0; i < bounceSampleCount; i++)
|
for (int i = 0; i < bounceSampleCount; i++)
|
||||||
{
|
{
|
||||||
Vec2 Xi = Hammersley(i, bounceSampleCount);
|
vec2 Xi = Hammersley(i, bounceSampleCount);
|
||||||
Vec3 H;
|
vec3 H;
|
||||||
H.x = Xi.x * 2.0f - 1.0f;
|
H.x = Xi.x * 2.0f - 1.0f;
|
||||||
H.y = Xi.y * 2.0f - 1.0f;
|
H.y = Xi.y * 2.0f - 1.0f;
|
||||||
H.z = RadicalInverse_VdC(i) + 0.01f;
|
H.z = RadicalInverse_VdC(i) + 0.01f;
|
||||||
H.Normalize();
|
H = normalize(H);
|
||||||
HemisphereVectors.push_back(H);
|
HemisphereVectors.push_back(H);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,9 +172,9 @@ void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size)
|
||||||
if (size > maxTasks)
|
if (size > maxTasks)
|
||||||
throw std::runtime_error("Ray trace task count is too large");
|
throw std::runtime_error("Ray trace task count is too large");
|
||||||
|
|
||||||
size_t imageSize = sizeof(Vec4) * rayTraceImageSize * rayTraceImageSize;
|
size_t imageSize = sizeof(vec4) * rayTraceImageSize * rayTraceImageSize;
|
||||||
uint8_t* imageData = (uint8_t*)imageTransferBuffer->Map(0, imageSize);
|
uint8_t* imageData = (uint8_t*)imageTransferBuffer->Map(0, imageSize);
|
||||||
Vec4* startPositions = (Vec4*)imageData;
|
vec4* startPositions = (vec4*)imageData;
|
||||||
for (size_t i = 0; i < size; i++)
|
for (size_t i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
const TraceTask& task = tasks[i];
|
const TraceTask& task = tasks[i];
|
||||||
|
@ -182,19 +182,19 @@ void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size)
|
||||||
if (task.id >= 0)
|
if (task.id >= 0)
|
||||||
{
|
{
|
||||||
Surface* surface = mesh->surfaces[task.id].get();
|
Surface* surface = mesh->surfaces[task.id].get();
|
||||||
Vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
||||||
startPositions[i] = Vec4(pos, (float)task.id);
|
startPositions[i] = vec4(pos, (float)task.id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LightProbeSample& probe = mesh->lightProbes[(size_t)(-task.id) - 2];
|
LightProbeSample& probe = mesh->lightProbes[(size_t)(-task.id) - 2];
|
||||||
startPositions[i] = Vec4(probe.Position, (float)-2);
|
startPositions[i] = vec4(probe.Position, (float)-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
for (size_t i = size; i < maxTasks; i++)
|
for (size_t i = size; i < maxTasks; i++)
|
||||||
{
|
{
|
||||||
startPositions[i] = Vec4(0.0f, 0.0f, 0.0f, -1.0f);
|
startPositions[i] = vec4(0.0f, 0.0f, 0.0f, -1.0f);
|
||||||
}
|
}
|
||||||
imageTransferBuffer->Unmap();
|
imageTransferBuffer->Unmap();
|
||||||
|
|
||||||
|
@ -303,9 +303,9 @@ void GPURaytracer::DownloadTasks(const TraceTask* tasks, size_t size)
|
||||||
|
|
||||||
SubmitCommands();
|
SubmitCommands();
|
||||||
|
|
||||||
size_t imageSize = sizeof(Vec4) * rayTraceImageSize * rayTraceImageSize;
|
size_t imageSize = sizeof(vec4) * rayTraceImageSize * rayTraceImageSize;
|
||||||
uint8_t* imageData = (uint8_t*)imageTransferBuffer->Map(0, imageSize);
|
uint8_t* imageData = (uint8_t*)imageTransferBuffer->Map(0, imageSize);
|
||||||
Vec4* output = (Vec4*)imageData;
|
vec4* output = (vec4*)imageData;
|
||||||
for (size_t i = 0; i < size; i++)
|
for (size_t i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
const TraceTask& task = tasks[i];
|
const TraceTask& task = tasks[i];
|
||||||
|
@ -313,12 +313,12 @@ void GPURaytracer::DownloadTasks(const TraceTask* tasks, size_t size)
|
||||||
{
|
{
|
||||||
Surface* surface = mesh->surfaces[task.id].get();
|
Surface* surface = mesh->surfaces[task.id].get();
|
||||||
size_t sampleWidth = surface->lightmapDims[0];
|
size_t sampleWidth = surface->lightmapDims[0];
|
||||||
surface->samples[task.x + task.y * sampleWidth] = Vec3(output[i].x, output[i].y, output[i].z);
|
surface->samples[task.x + task.y * sampleWidth] = vec3(output[i].x, output[i].y, output[i].z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LightProbeSample& probe = mesh->lightProbes[(size_t)(-task.id) - 2];
|
LightProbeSample& probe = mesh->lightProbes[(size_t)(-task.id) - 2];
|
||||||
probe.Color = Vec3(output[i].x, output[i].y, output[i].z);
|
probe.Color = vec3(output[i].x, output[i].y, output[i].z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imageTransferBuffer->Unmap();
|
imageTransferBuffer->Unmap();
|
||||||
|
@ -370,7 +370,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
{
|
{
|
||||||
info.EmissiveDistance = 0.0f;
|
info.EmissiveDistance = 0.0f;
|
||||||
info.EmissiveIntensity = 0.0f;
|
info.EmissiveIntensity = 0.0f;
|
||||||
info.EmissiveColor = Vec3(0.0f, 0.0f, 0.0f);
|
info.EmissiveColor = vec3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
surfaces.push_back(info);
|
surfaces.push_back(info);
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
if (lights.empty()) // vulkan doesn't support zero byte buffers
|
if (lights.empty()) // vulkan doesn't support zero byte buffers
|
||||||
lights.push_back(LightInfo());
|
lights.push_back(LightInfo());
|
||||||
|
|
||||||
size_t vertexbuffersize = (size_t)mesh->MeshVertices.Size() * sizeof(Vec3);
|
size_t vertexbuffersize = (size_t)mesh->MeshVertices.Size() * sizeof(vec3);
|
||||||
size_t indexbuffersize = (size_t)mesh->MeshElements.Size() * sizeof(uint32_t);
|
size_t indexbuffersize = (size_t)mesh->MeshElements.Size() * sizeof(uint32_t);
|
||||||
size_t surfaceindexbuffersize = (size_t)mesh->MeshSurfaces.Size() * sizeof(uint32_t);
|
size_t surfaceindexbuffersize = (size_t)mesh->MeshSurfaces.Size() * sizeof(uint32_t);
|
||||||
size_t surfacebuffersize = (size_t)surfaces.size() * sizeof(SurfaceInfo);
|
size_t surfacebuffersize = (size_t)surfaces.size() * sizeof(SurfaceInfo);
|
||||||
|
@ -472,7 +472,7 @@ void GPURaytracer::CreateBottomLevelAccelerationStructure()
|
||||||
VkAccelerationStructureGeometryTrianglesDataKHR triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
VkAccelerationStructureGeometryTrianglesDataKHR triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
||||||
triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
triangles.vertexData.deviceAddress = vertexAddress;
|
triangles.vertexData.deviceAddress = vertexAddress;
|
||||||
triangles.vertexStride = sizeof(Vec3);
|
triangles.vertexStride = sizeof(vec3);
|
||||||
triangles.indexType = VK_INDEX_TYPE_UINT32;
|
triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||||
triangles.indexData.deviceAddress = indexAddress;
|
triangles.indexData.deviceAddress = indexAddress;
|
||||||
triangles.maxVertex = mesh->MeshVertices.Size();
|
triangles.maxVertex = mesh->MeshVertices.Size();
|
||||||
|
@ -823,7 +823,7 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
|
|
||||||
BufferBuilder itbuilder;
|
BufferBuilder itbuilder;
|
||||||
itbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
itbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||||
itbuilder.setSize(2 * sizeof(Vec4) * rayTraceImageSize * rayTraceImageSize);
|
itbuilder.setSize(2 * sizeof(vec4) * rayTraceImageSize * rayTraceImageSize);
|
||||||
imageTransferBuffer = itbuilder.create(device.get());
|
imageTransferBuffer = itbuilder.create(device.get());
|
||||||
imageTransferBuffer->SetDebugName("imageTransferBuffer");
|
imageTransferBuffer->SetDebugName("imageTransferBuffer");
|
||||||
|
|
||||||
|
@ -910,9 +910,9 @@ void GPURaytracer::PrintVulkanInfo()
|
||||||
printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.c_str(), driverVersion.c_str());
|
printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.c_str(), driverVersion.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 GPURaytracer::Hammersley(uint32_t i, uint32_t N)
|
vec2 GPURaytracer::Hammersley(uint32_t i, uint32_t N)
|
||||||
{
|
{
|
||||||
return Vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
float GPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
float GPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
||||||
|
|
|
@ -12,19 +12,19 @@ struct Uniforms
|
||||||
uint32_t SampleCount;
|
uint32_t SampleCount;
|
||||||
uint32_t PassType;
|
uint32_t PassType;
|
||||||
uint32_t LightCount;
|
uint32_t LightCount;
|
||||||
Vec3 SunDir;
|
vec3 SunDir;
|
||||||
float SampleDistance;
|
float SampleDistance;
|
||||||
Vec3 SunColor;
|
vec3 SunColor;
|
||||||
float SunIntensity;
|
float SunIntensity;
|
||||||
Vec3 HemisphereVec;
|
vec3 HemisphereVec;
|
||||||
float Padding1;
|
float Padding1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceInfo
|
struct SurfaceInfo
|
||||||
{
|
{
|
||||||
Vec3 Normal;
|
vec3 Normal;
|
||||||
float EmissiveDistance;
|
float EmissiveDistance;
|
||||||
Vec3 EmissiveColor;
|
vec3 EmissiveColor;
|
||||||
float EmissiveIntensity;
|
float EmissiveIntensity;
|
||||||
float Sky;
|
float Sky;
|
||||||
float Padding0, Padding1, Padding2;
|
float Padding0, Padding1, Padding2;
|
||||||
|
@ -32,15 +32,15 @@ struct SurfaceInfo
|
||||||
|
|
||||||
struct LightInfo
|
struct LightInfo
|
||||||
{
|
{
|
||||||
Vec3 Origin;
|
vec3 Origin;
|
||||||
float Padding0;
|
float Padding0;
|
||||||
float Radius;
|
float Radius;
|
||||||
float Intensity;
|
float Intensity;
|
||||||
float InnerAngleCos;
|
float InnerAngleCos;
|
||||||
float OuterAngleCos;
|
float OuterAngleCos;
|
||||||
Vec3 SpotDir;
|
vec3 SpotDir;
|
||||||
float Padding1;
|
float Padding1;
|
||||||
Vec3 Color;
|
vec3 Color;
|
||||||
float Padding2;
|
float Padding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ private:
|
||||||
void PrintVulkanInfo();
|
void PrintVulkanInfo();
|
||||||
|
|
||||||
static float RadicalInverse_VdC(uint32_t bits);
|
static float RadicalInverse_VdC(uint32_t bits);
|
||||||
static Vec2 Hammersley(uint32_t i, uint32_t N);
|
static vec2 Hammersley(uint32_t i, uint32_t N);
|
||||||
|
|
||||||
const int coverageSampleCount = 256;
|
const int coverageSampleCount = 256;
|
||||||
const int bounceSampleCount = 2048;
|
const int bounceSampleCount = 2048;
|
||||||
|
|
|
@ -120,11 +120,11 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
|
||||||
{
|
{
|
||||||
Plane* plane;
|
Plane* plane;
|
||||||
BBox bounds;
|
BBox bounds;
|
||||||
Vec3 roundedSize;
|
vec3 roundedSize;
|
||||||
int i;
|
int i;
|
||||||
Plane::PlaneAxis axis;
|
Plane::PlaneAxis axis;
|
||||||
Vec3 tCoords[2];
|
vec3 tCoords[2];
|
||||||
Vec3 tOrigin;
|
vec3 tOrigin;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
float d;
|
float d;
|
||||||
|
@ -141,8 +141,8 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
|
||||||
roundedSize[i] = (bounds.max[i] - bounds.min[i]) / samples + 1;
|
roundedSize[i] = (bounds.max[i] - bounds.min[i]) / samples + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tCoords[0].Clear();
|
tCoords[0] = vec3(0.0f);
|
||||||
tCoords[1].Clear();
|
tCoords[1] = vec3(0.0f);
|
||||||
|
|
||||||
axis = plane->BestAxis();
|
axis = plane->BestAxis();
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
tCoords[i].Normalize();
|
tCoords[i] = normalize(tCoords[i]);
|
||||||
d = plane->Distance(tCoords[i]) / plane->Normal()[axis];
|
d = plane->Distance(tCoords[i]) / plane->Normal()[axis];
|
||||||
tCoords[i][axis] -= d;
|
tCoords[i][axis] -= d;
|
||||||
}
|
}
|
||||||
|
@ -217,8 +217,8 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
|
||||||
|
|
||||||
BBox LevelMesh::GetBoundsFromSurface(const Surface* surface)
|
BBox LevelMesh::GetBoundsFromSurface(const Surface* surface)
|
||||||
{
|
{
|
||||||
Vec3 low(M_INFINITY, M_INFINITY, M_INFINITY);
|
vec3 low(M_INFINITY, M_INFINITY, M_INFINITY);
|
||||||
Vec3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
vec3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
||||||
|
|
||||||
BBox bounds;
|
BBox bounds;
|
||||||
bounds.Clear();
|
bounds.Clear();
|
||||||
|
@ -256,11 +256,11 @@ void LevelMesh::FinishSurface(Surface* surface)
|
||||||
{
|
{
|
||||||
int sampleWidth = surface->lightmapDims[0];
|
int sampleWidth = surface->lightmapDims[0];
|
||||||
int sampleHeight = surface->lightmapDims[1];
|
int sampleHeight = surface->lightmapDims[1];
|
||||||
Vec3* colorSamples = surface->samples.data();
|
vec3* colorSamples = surface->samples.data();
|
||||||
|
|
||||||
if (!surface->indirect.empty())
|
if (!surface->indirect.empty())
|
||||||
{
|
{
|
||||||
Vec3* indirect = surface->indirect.data();
|
vec3* indirect = surface->indirect.data();
|
||||||
for (int i = 0; i < sampleHeight; i++)
|
for (int i = 0; i < sampleHeight; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < sampleWidth; j++)
|
for (int j = 0; j < sampleWidth; j++)
|
||||||
|
@ -298,9 +298,9 @@ void LevelMesh::FinishSurface(Surface* surface)
|
||||||
// calculate texture coordinates
|
// calculate texture coordinates
|
||||||
for (int i = 0; i < surface->numVerts; i++)
|
for (int i = 0; i < surface->numVerts; i++)
|
||||||
{
|
{
|
||||||
Vec3 tDelta = surface->verts[i] - surface->bounds.min;
|
vec3 tDelta = surface->verts[i] - surface->bounds.min;
|
||||||
surface->lightmapCoords[i * 2 + 0] = (tDelta.Dot(surface->textureCoords[0]) + x + 0.5f) / (float)textureWidth;
|
surface->lightmapCoords[i * 2 + 0] = (dot(tDelta, surface->textureCoords[0]) + x + 0.5f) / (float)textureWidth;
|
||||||
surface->lightmapCoords[i * 2 + 1] = (tDelta.Dot(surface->textureCoords[1]) + y + 0.5f) / (float)textureHeight;
|
surface->lightmapCoords[i * 2 + 1] = (dot(tDelta, surface->textureCoords[1]) + y + 0.5f) / (float)textureHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->lightmapOffs[0] = x;
|
surface->lightmapOffs[0] = x;
|
||||||
|
@ -311,11 +311,11 @@ void LevelMesh::FinishSurface(Surface* surface)
|
||||||
float weights[9] = { 0.125f, 0.25f, 0.125f, 0.25f, 0.50f, 0.25f, 0.125f, 0.25f, 0.125f };
|
float weights[9] = { 0.125f, 0.25f, 0.125f, 0.25f, 0.50f, 0.25f, 0.125f, 0.25f, 0.125f };
|
||||||
for (int y = 0; y < sampleHeight; y++)
|
for (int y = 0; y < sampleHeight; y++)
|
||||||
{
|
{
|
||||||
Vec3* src = &colorSamples[y * sampleWidth];
|
vec3* src = &colorSamples[y * sampleWidth];
|
||||||
for (int x = 0; x < sampleWidth; x++)
|
for (int x = 0; x < sampleWidth; x++)
|
||||||
{
|
{
|
||||||
// gaussian blur with a 3x3 kernel
|
// gaussian blur with a 3x3 kernel
|
||||||
Vec3 color = { 0.0f };
|
vec3 color = { 0.0f };
|
||||||
for (int yy = -1; yy <= 1; yy++)
|
for (int yy = -1; yy <= 1; yy++)
|
||||||
{
|
{
|
||||||
int yyy = clamp(y + yy, 0, sampleHeight - 1) - y;
|
int yyy = clamp(y + yy, 0, sampleHeight - 1) - y;
|
||||||
|
@ -407,9 +407,9 @@ void LevelMesh::CreateLightProbes(FLevel& map)
|
||||||
if (delta > doubleGridSize)
|
if (delta > doubleGridSize)
|
||||||
{
|
{
|
||||||
LightProbeSample p[3];
|
LightProbeSample p[3];
|
||||||
p[0].Position = Vec3(x, y, z0 + halfGridSize);
|
p[0].Position = vec3(x, y, z0 + halfGridSize);
|
||||||
p[1].Position = Vec3(x, y, z0 + (z1 - z0) * 0.5f);
|
p[1].Position = vec3(x, y, z0 + (z1 - z0) * 0.5f);
|
||||||
p[2].Position = Vec3(x, y, z1 - halfGridSize);
|
p[2].Position = vec3(x, y, z1 - halfGridSize);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
|
@ -462,8 +462,8 @@ void LevelMesh::CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
|
||||||
|
|
||||||
int typeIndex = side - &doomMap.Sides[0];
|
int typeIndex = side - &doomMap.Sides[0];
|
||||||
|
|
||||||
Vec2 dx(v2.x - v1.x, v2.y - v1.y);
|
vec2 dx(v2.x - v1.x, v2.y - v1.y);
|
||||||
float distance = std::sqrt(dx.Dot(dx));
|
float distance = length(dx);
|
||||||
|
|
||||||
if (back)
|
if (back)
|
||||||
{
|
{
|
||||||
|
@ -785,7 +785,7 @@ void LevelMesh::CreateSubsectorSurfaces(FLevel &doomMap)
|
||||||
printf("\nLeaf surfaces: %i\n", (int)surfaces.size() - doomMap.NumGLSubsectors);
|
printf("\nLeaf surfaces: %i\n", (int)surfaces.size() - doomMap.NumGLSubsectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LevelMesh::IsDegenerate(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2)
|
bool LevelMesh::IsDegenerate(const vec3 &v0, const vec3 &v1, const vec3 &v2)
|
||||||
{
|
{
|
||||||
// A degenerate triangle has a zero cross product for two of its sides.
|
// A degenerate triangle has a zero cross product for two of its sides.
|
||||||
float ax = v1.x - v0.x;
|
float ax = v1.x - v0.x;
|
||||||
|
@ -928,9 +928,9 @@ void LevelMesh::Export(std::string filename)
|
||||||
for (int i = 0; i < 3; i++) mtlfilename.pop_back();
|
for (int i = 0; i < 3; i++) mtlfilename.pop_back();
|
||||||
mtlfilename += "mtl";
|
mtlfilename += "mtl";
|
||||||
|
|
||||||
TArray<Vec3> outvertices;
|
TArray<vec3> outvertices;
|
||||||
TArray<Vec2> outuv;
|
TArray<vec2> outuv;
|
||||||
TArray<Vec3> outnormal;
|
TArray<vec3> outnormal;
|
||||||
TArray<int> outface;
|
TArray<int> outface;
|
||||||
|
|
||||||
outvertices.Resize(MeshVertices.Size());
|
outvertices.Resize(MeshVertices.Size());
|
||||||
|
@ -947,7 +947,7 @@ void LevelMesh::Export(std::string filename)
|
||||||
int uvindex = MeshUVIndex[vertexidx];
|
int uvindex = MeshUVIndex[vertexidx];
|
||||||
|
|
||||||
outvertices[vertexidx] = MeshVertices[vertexidx];
|
outvertices[vertexidx] = MeshVertices[vertexidx];
|
||||||
outuv[vertexidx] = Vec2(surface->lightmapCoords[uvindex * 2], surface->lightmapCoords[uvindex * 2 + 1]);
|
outuv[vertexidx] = vec2(surface->lightmapCoords[uvindex * 2], surface->lightmapCoords[uvindex * 2 + 1]);
|
||||||
outnormal[vertexidx] = surface->plane.Normal();
|
outnormal[vertexidx] = surface->plane.Normal();
|
||||||
outface.Push(vertexidx);
|
outface.Push(vertexidx);
|
||||||
|
|
||||||
|
|
|
@ -57,20 +57,20 @@ struct Surface
|
||||||
int lightmapNum;
|
int lightmapNum;
|
||||||
int lightmapOffs[2];
|
int lightmapOffs[2];
|
||||||
int lightmapDims[2];
|
int lightmapDims[2];
|
||||||
Vec3 lightmapOrigin;
|
vec3 lightmapOrigin;
|
||||||
Vec3 lightmapSteps[2];
|
vec3 lightmapSteps[2];
|
||||||
Vec3 textureCoords[2];
|
vec3 textureCoords[2];
|
||||||
BBox bounds;
|
BBox bounds;
|
||||||
int numVerts;
|
int numVerts;
|
||||||
std::vector<Vec3> verts;
|
std::vector<vec3> verts;
|
||||||
std::vector<float> lightmapCoords;
|
std::vector<float> lightmapCoords;
|
||||||
std::vector<Vec3> samples;
|
std::vector<vec3> samples;
|
||||||
std::vector<Vec3> indirect;
|
std::vector<vec3> indirect;
|
||||||
SurfaceType type;
|
SurfaceType type;
|
||||||
int typeIndex;
|
int typeIndex;
|
||||||
IntSector *controlSector;
|
IntSector *controlSector;
|
||||||
bool bSky;
|
bool bSky;
|
||||||
std::vector<Vec2> uvs;
|
std::vector<vec2> uvs;
|
||||||
std::string material;
|
std::string material;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ private:
|
||||||
class LightProbeSample
|
class LightProbeSample
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Vec3 Position = Vec3(0.0f, 0.0f, 0.0f);
|
vec3 Position = vec3(0.0f, 0.0f, 0.0f);
|
||||||
Vec3 Color = Vec3(0.0f, 0.0f, 0.0f);
|
vec3 Color = vec3(0.0f, 0.0f, 0.0f);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LevelMesh
|
class LevelMesh
|
||||||
|
@ -166,7 +166,7 @@ public:
|
||||||
int textureWidth = 128;
|
int textureWidth = 128;
|
||||||
int textureHeight = 128;
|
int textureHeight = 128;
|
||||||
|
|
||||||
TArray<Vec3> MeshVertices;
|
TArray<vec3> MeshVertices;
|
||||||
TArray<int> MeshUVIndex;
|
TArray<int> MeshUVIndex;
|
||||||
TArray<unsigned int> MeshElements;
|
TArray<unsigned int> MeshElements;
|
||||||
TArray<int> MeshSurfaces;
|
TArray<int> MeshSurfaces;
|
||||||
|
@ -183,5 +183,5 @@ private:
|
||||||
void FinishSurface(Surface* surface);
|
void FinishSurface(Surface* surface);
|
||||||
uint16_t* AllocTextureRoom(Surface* surface, int* x, int* y);
|
uint16_t* AllocTextureRoom(Surface* surface, int* x, int* y);
|
||||||
|
|
||||||
static bool IsDegenerate(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2);
|
static bool IsDegenerate(const vec3 &v0, const vec3 &v1, const vec3 &v2);
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,7 +45,7 @@ Angle::Angle(const float yaw, const float pitch, const float roll)
|
||||||
this->roll = roll;
|
this->roll = roll;
|
||||||
}
|
}
|
||||||
|
|
||||||
Angle::Angle(const Vec3 &vector)
|
Angle::Angle(const vec3 &vector)
|
||||||
{
|
{
|
||||||
this->yaw = vector.x;
|
this->yaw = vector.x;
|
||||||
this->pitch = vector.y;
|
this->pitch = vector.y;
|
||||||
|
@ -158,7 +158,7 @@ Angle Angle::Diff(Angle &angle)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Angle::ToAxis(Vec3 *forward, Vec3 *up, Vec3 *right)
|
void Angle::ToAxis(vec3 *forward, vec3 *up, vec3 *right)
|
||||||
{
|
{
|
||||||
float sy = Math::Sin(yaw);
|
float sy = Math::Sin(yaw);
|
||||||
float cy = Math::Cos(yaw);
|
float cy = Math::Cos(yaw);
|
||||||
|
@ -187,46 +187,38 @@ void Angle::ToAxis(Vec3 *forward, Vec3 *up, Vec3 *right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 Angle::ToForwardAxis()
|
vec3 Angle::ToForwardAxis()
|
||||||
{
|
{
|
||||||
Vec3 vec;
|
vec3 vec;
|
||||||
|
|
||||||
ToAxis(&vec, nullptr, nullptr);
|
ToAxis(&vec, nullptr, nullptr);
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 Angle::ToUpAxis()
|
vec3 Angle::ToUpAxis()
|
||||||
{
|
{
|
||||||
Vec3 vec;
|
vec3 vec;
|
||||||
|
|
||||||
ToAxis(nullptr, &vec, nullptr);
|
ToAxis(nullptr, &vec, nullptr);
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 Angle::ToRightAxis()
|
vec3 Angle::ToRightAxis()
|
||||||
{
|
{
|
||||||
Vec3 vec;
|
vec3 vec;
|
||||||
|
|
||||||
ToAxis(nullptr, nullptr, &vec);
|
ToAxis(nullptr, nullptr, &vec);
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vec3 &Angle::ToVec3() const
|
const vec3 &Angle::ToVec3() const
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<const Vec3*>(&yaw);
|
return *reinterpret_cast<const vec3*>(&yaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &Angle::ToVec3()
|
vec3 &Angle::ToVec3()
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<Vec3*>(&yaw);
|
return *reinterpret_cast<vec3*>(&yaw);
|
||||||
}
|
|
||||||
|
|
||||||
Quat Angle::ToQuat()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(Quat(pitch, Vec3::vecRight) *
|
|
||||||
(Quat(yaw, Vec3::vecUp) *
|
|
||||||
Quat(roll, Vec3::vecForward)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Angle Angle::operator+(const Angle &angle)
|
Angle Angle::operator+(const Angle &angle)
|
||||||
|
@ -268,7 +260,7 @@ Angle &Angle::operator=(const Angle &angle)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Angle &Angle::operator=(const Vec3 &vector)
|
Angle &Angle::operator=(const vec3 &vector)
|
||||||
{
|
{
|
||||||
yaw = vector.x;
|
yaw = vector.x;
|
||||||
pitch = vector.y;
|
pitch = vector.y;
|
||||||
|
|
|
@ -34,7 +34,7 @@ BBox::BBox()
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
BBox::BBox(const Vec3 &vMin, const Vec3 &vMax)
|
BBox::BBox(const vec3 &vMin, const vec3 &vMax)
|
||||||
{
|
{
|
||||||
this->min = vMin;
|
this->min = vMin;
|
||||||
this->max = vMax;
|
this->max = vMax;
|
||||||
|
@ -42,11 +42,11 @@ BBox::BBox(const Vec3 &vMin, const Vec3 &vMax)
|
||||||
|
|
||||||
void BBox::Clear()
|
void BBox::Clear()
|
||||||
{
|
{
|
||||||
min.Set(M_INFINITY, M_INFINITY, M_INFINITY);
|
min = vec3(M_INFINITY, M_INFINITY, M_INFINITY);
|
||||||
max.Set(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
max = vec3(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BBox::AddPoint(const Vec3 &vec)
|
void BBox::AddPoint(const vec3 &vec)
|
||||||
{
|
{
|
||||||
float lowx = min.x;
|
float lowx = min.x;
|
||||||
float lowy = min.y;
|
float lowy = min.y;
|
||||||
|
@ -62,8 +62,8 @@ void BBox::AddPoint(const Vec3 &vec)
|
||||||
if (vec.y > hiy) { hiy = vec.y; }
|
if (vec.y > hiy) { hiy = vec.y; }
|
||||||
if (vec.z > hiz) { hiz = vec.z; }
|
if (vec.z > hiz) { hiz = vec.z; }
|
||||||
|
|
||||||
min.Set(lowx, lowy, lowz);
|
min = vec3(lowx, lowy, lowz);
|
||||||
max.Set(hix, hiy, hiz);
|
max = vec3(hix, hiy, hiz);
|
||||||
}
|
}
|
||||||
|
|
||||||
float BBox::Radius() const
|
float BBox::Radius() const
|
||||||
|
@ -91,7 +91,7 @@ float BBox::Radius() const
|
||||||
return Math::Sqrt(r);
|
return Math::Sqrt(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BBox::PointInside(const Vec3 &vec) const
|
bool BBox::PointInside(const vec3 &vec) const
|
||||||
{
|
{
|
||||||
return !(vec[0] < min[0] || vec[1] < min[1] || vec[2] < min[2] ||
|
return !(vec[0] < min[0] || vec[1] < min[1] || vec[2] < min[2] ||
|
||||||
vec[0] > max[0] || vec[1] > max[1] || vec[2] > max[2]);
|
vec[0] > max[0] || vec[1] > max[1] || vec[2] > max[2]);
|
||||||
|
@ -111,7 +111,7 @@ bool BBox::IntersectingBox2D(const BBox &box) const
|
||||||
|
|
||||||
float BBox::DistanceToPlane(Plane &plane)
|
float BBox::DistanceToPlane(Plane &plane)
|
||||||
{
|
{
|
||||||
Vec3 c;
|
vec3 c;
|
||||||
float distStart;
|
float distStart;
|
||||||
float distEnd;
|
float distEnd;
|
||||||
float dist = 0;
|
float dist = 0;
|
||||||
|
@ -144,8 +144,8 @@ float BBox::DistanceToPlane(Plane &plane)
|
||||||
|
|
||||||
BBox BBox::operator+(const float radius) const
|
BBox BBox::operator+(const float radius) const
|
||||||
{
|
{
|
||||||
Vec3 vmin = min;
|
vec3 vmin = min;
|
||||||
Vec3 vmax = max;
|
vec3 vmax = max;
|
||||||
|
|
||||||
vmin.x -= radius;
|
vmin.x -= radius;
|
||||||
vmin.y -= radius;
|
vmin.y -= radius;
|
||||||
|
@ -169,10 +169,10 @@ BBox &BBox::operator+=(const float radius)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BBox BBox::operator+(const Vec3 &vec) const
|
BBox BBox::operator+(const vec3 &vec) const
|
||||||
{
|
{
|
||||||
Vec3 vmin = min;
|
vec3 vmin = min;
|
||||||
Vec3 vmax = max;
|
vec3 vmax = max;
|
||||||
|
|
||||||
vmin.x += vec.x;
|
vmin.x += vec.x;
|
||||||
vmin.y += vec.y;
|
vmin.y += vec.y;
|
||||||
|
@ -187,8 +187,8 @@ BBox BBox::operator+(const Vec3 &vec) const
|
||||||
|
|
||||||
BBox BBox::operator-(const float radius) const
|
BBox BBox::operator-(const float radius) const
|
||||||
{
|
{
|
||||||
Vec3 vmin = min;
|
vec3 vmin = min;
|
||||||
Vec3 vmax = max;
|
vec3 vmax = max;
|
||||||
|
|
||||||
vmin.x += radius;
|
vmin.x += radius;
|
||||||
vmin.y += radius;
|
vmin.y += radius;
|
||||||
|
@ -201,10 +201,10 @@ BBox BBox::operator-(const float radius) const
|
||||||
return BBox(vmin, vmax);
|
return BBox(vmin, vmax);
|
||||||
}
|
}
|
||||||
|
|
||||||
BBox BBox::operator-(const Vec3 &vec) const
|
BBox BBox::operator-(const vec3 &vec) const
|
||||||
{
|
{
|
||||||
Vec3 vmin = min;
|
vec3 vmin = min;
|
||||||
Vec3 vmax = max;
|
vec3 vmax = max;
|
||||||
|
|
||||||
vmin.x -= vec.x;
|
vmin.x -= vec.x;
|
||||||
vmin.y -= vec.y;
|
vmin.y -= vec.y;
|
||||||
|
@ -228,51 +228,7 @@ BBox &BBox::operator-=(const float radius)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BBox BBox::operator*(const Mat4 &matrix) const
|
BBox BBox::operator*(const vec3 &vec) const
|
||||||
{
|
|
||||||
Vec3 c = Center();
|
|
||||||
Vec3 ct = c * matrix;
|
|
||||||
BBox box(ct, ct);
|
|
||||||
|
|
||||||
Mat4 mtx(matrix);
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
mtx.vectors[i].x = Math::Fabs(mtx.vectors[i].x);
|
|
||||||
mtx.vectors[i].y = Math::Fabs(mtx.vectors[i].y);
|
|
||||||
mtx.vectors[i].z = Math::Fabs(mtx.vectors[i].z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 ht = (max - c) * mtx;
|
|
||||||
box.min -= ht;
|
|
||||||
box.max += ht;
|
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
BBox &BBox::operator*=(const Mat4 &matrix)
|
|
||||||
{
|
|
||||||
Vec3 c = Center();
|
|
||||||
Vec3 ct = c * matrix;
|
|
||||||
|
|
||||||
Mat4 mtx(matrix);
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
mtx.vectors[i].x = Math::Fabs(mtx.vectors[i].x);
|
|
||||||
mtx.vectors[i].y = Math::Fabs(mtx.vectors[i].y);
|
|
||||||
mtx.vectors[i].z = Math::Fabs(mtx.vectors[i].z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 ht = (max - c) * mtx;
|
|
||||||
|
|
||||||
min = (ct - ht);
|
|
||||||
max = (ct + ht);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BBox BBox::operator*(const Vec3 &vec) const
|
|
||||||
{
|
{
|
||||||
BBox box = *this;
|
BBox box = *this;
|
||||||
|
|
||||||
|
@ -286,7 +242,7 @@ BBox BBox::operator*(const Vec3 &vec) const
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
BBox &BBox::operator*=(const Vec3 &vec)
|
BBox &BBox::operator*=(const vec3 &vec)
|
||||||
{
|
{
|
||||||
if (vec.x < 0) { min.x += (vec.x - 1); }
|
if (vec.x < 0) { min.x += (vec.x - 1); }
|
||||||
else { max.x += (vec.x + 1); }
|
else { max.x += (vec.x + 1); }
|
||||||
|
@ -306,26 +262,26 @@ BBox &BBox::operator=(const BBox &bbox)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 BBox::operator[](int index) const
|
vec3 BBox::operator[](int index) const
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index < 2);
|
assert(index >= 0 && index < 2);
|
||||||
return index == 0 ? min : max;
|
return index == 0 ? min : max;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &BBox::operator[](int index)
|
vec3 &BBox::operator[](int index)
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index < 2);
|
assert(index >= 0 && index < 2);
|
||||||
return index == 0 ? min : max;
|
return index == 0 ? min : max;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BBox::LineIntersect(const Vec3 &start, const Vec3 &end)
|
bool BBox::LineIntersect(const vec3 &start, const vec3 &end)
|
||||||
{
|
{
|
||||||
float ld[3];
|
float ld[3];
|
||||||
Vec3 center = Center();
|
vec3 center = Center();
|
||||||
Vec3 extents = max - center;
|
vec3 extents = max - center;
|
||||||
Vec3 lineDir = (end - start) * 0.5f;
|
vec3 lineDir = (end - start) * 0.5f;
|
||||||
Vec3 lineCenter = lineDir + start;
|
vec3 lineCenter = lineDir + start;
|
||||||
Vec3 dir = lineCenter - center;
|
vec3 dir = lineCenter - center;
|
||||||
|
|
||||||
ld[0] = Math::Fabs(lineDir.x);
|
ld[0] = Math::Fabs(lineDir.x);
|
||||||
if (Math::Fabs(dir.x) > extents.x + ld[0]) { return false; }
|
if (Math::Fabs(dir.x) > extents.x + ld[0]) { return false; }
|
||||||
|
@ -334,11 +290,11 @@ bool BBox::LineIntersect(const Vec3 &start, const Vec3 &end)
|
||||||
ld[2] = Math::Fabs(lineDir.z);
|
ld[2] = Math::Fabs(lineDir.z);
|
||||||
if (Math::Fabs(dir.z) > extents.z + ld[2]) { return false; }
|
if (Math::Fabs(dir.z) > extents.z + ld[2]) { return false; }
|
||||||
|
|
||||||
Vec3 cross = lineDir.Cross(dir);
|
vec3 crossprod = cross(lineDir, dir);
|
||||||
|
|
||||||
if (Math::Fabs(cross.x) > extents.y * ld[2] + extents.z * ld[1]) { return false; }
|
if (Math::Fabs(crossprod.x) > extents.y * ld[2] + extents.z * ld[1]) { return false; }
|
||||||
if (Math::Fabs(cross.y) > extents.x * ld[2] + extents.z * ld[0]) { return false; }
|
if (Math::Fabs(crossprod.y) > extents.x * ld[2] + extents.z * ld[0]) { return false; }
|
||||||
if (Math::Fabs(cross.z) > extents.x * ld[1] + extents.y * ld[0]) { return false; }
|
if (Math::Fabs(crossprod.z) > extents.x * ld[1] + extents.y * ld[0]) { return false; }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +329,7 @@ void BBox::ToPoints(float *points) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes vectors is an array of 8
|
// Assumes vectors is an array of 8
|
||||||
void BBox::ToVectors(Vec3 *vectors) const
|
void BBox::ToVectors(vec3 *vectors) const
|
||||||
{
|
{
|
||||||
vectors[0][0] = max[0];
|
vectors[0][0] = max[0];
|
||||||
vectors[0][1] = min[1];
|
vectors[0][1] = min[1];
|
||||||
|
|
336
src/math/mat.cpp
Normal file
336
src/math/mat.cpp
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
|
||||||
|
#include "mat.h"
|
||||||
|
#include <cmath>
|
||||||
|
#ifndef NO_SSE
|
||||||
|
#include <emmintrin.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
mat4 mat4::null()
|
||||||
|
{
|
||||||
|
mat4 m;
|
||||||
|
memset(m.matrix, 0, sizeof(m.matrix));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::identity()
|
||||||
|
{
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0] = 1.0f;
|
||||||
|
m.matrix[5] = 1.0f;
|
||||||
|
m.matrix[10] = 1.0f;
|
||||||
|
m.matrix[15] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::from_values(float *matrix)
|
||||||
|
{
|
||||||
|
mat4 m;
|
||||||
|
memcpy(m.matrix, matrix, sizeof(m.matrix));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::transpose(const mat4 &matrix)
|
||||||
|
{
|
||||||
|
mat4 m;
|
||||||
|
for (int y = 0; y < 4; y++)
|
||||||
|
for (int x = 0; x < 4; x++)
|
||||||
|
m.matrix[x + y * 4] = matrix.matrix[y + x * 4];
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::translate(float x, float y, float z)
|
||||||
|
{
|
||||||
|
mat4 m = identity();
|
||||||
|
m.matrix[0 + 3 * 4] = x;
|
||||||
|
m.matrix[1 + 3 * 4] = y;
|
||||||
|
m.matrix[2 + 3 * 4] = z;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::scale(float x, float y, float z)
|
||||||
|
{
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0 + 0 * 4] = x;
|
||||||
|
m.matrix[1 + 1 * 4] = y;
|
||||||
|
m.matrix[2 + 2 * 4] = z;
|
||||||
|
m.matrix[3 + 3 * 4] = 1;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::rotate(float angle, float x, float y, float z)
|
||||||
|
{
|
||||||
|
float c = cosf(angle);
|
||||||
|
float s = sinf(angle);
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0 + 0 * 4] = (x*x*(1.0f - c) + c);
|
||||||
|
m.matrix[0 + 1 * 4] = (x*y*(1.0f - c) - z*s);
|
||||||
|
m.matrix[0 + 2 * 4] = (x*z*(1.0f - c) + y*s);
|
||||||
|
m.matrix[1 + 0 * 4] = (y*x*(1.0f - c) + z*s);
|
||||||
|
m.matrix[1 + 1 * 4] = (y*y*(1.0f - c) + c);
|
||||||
|
m.matrix[1 + 2 * 4] = (y*z*(1.0f - c) - x*s);
|
||||||
|
m.matrix[2 + 0 * 4] = (x*z*(1.0f - c) - y*s);
|
||||||
|
m.matrix[2 + 1 * 4] = (y*z*(1.0f - c) + x*s);
|
||||||
|
m.matrix[2 + 2 * 4] = (z*z*(1.0f - c) + c);
|
||||||
|
m.matrix[3 + 3 * 4] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::quaternion(float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
mat4 m = mat4::null();
|
||||||
|
m.matrix[0 * 4 + 0] = 1.0f - 2.0f * y*y - 2.0f * z*z;
|
||||||
|
m.matrix[1 * 4 + 0] = 2.0f * x*y - 2.0f * w*z;
|
||||||
|
m.matrix[2 * 4 + 0] = 2.0f * x*z + 2.0f * w*y;
|
||||||
|
m.matrix[0 * 4 + 1] = 2.0f * x*y + 2.0f * w*z;
|
||||||
|
m.matrix[1 * 4 + 1] = 1.0f - 2.0f * x*x - 2.0f * z*z;
|
||||||
|
m.matrix[2 * 4 + 1] = 2.0f * y*z - 2.0f * w*x;
|
||||||
|
m.matrix[0 * 4 + 2] = 2.0f * x*z - 2.0f * w*y;
|
||||||
|
m.matrix[1 * 4 + 2] = 2.0f * y*z + 2.0f * w*x;
|
||||||
|
m.matrix[2 * 4 + 2] = 1.0f - 2.0f * x*x - 2.0f * y*y;
|
||||||
|
m.matrix[3 * 4 + 3] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::swap_yz()
|
||||||
|
{
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0 + 0 * 4] = 1.0f;
|
||||||
|
m.matrix[1 + 2 * 4] = 1.0f;
|
||||||
|
m.matrix[2 + 1 * 4] = -1.0f;
|
||||||
|
m.matrix[3 + 3 * 4] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::perspective(float fovy, float aspect, float z_near, float z_far, handedness handedness, clipzrange clipZ)
|
||||||
|
{
|
||||||
|
float f = (float)(1.0 / tan(fovy * 3.14159265359 / 360.0));
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0 + 0 * 4] = f / aspect;
|
||||||
|
m.matrix[1 + 1 * 4] = f;
|
||||||
|
m.matrix[2 + 2 * 4] = (z_far + z_near) / (z_near - z_far);
|
||||||
|
m.matrix[2 + 3 * 4] = (2.0f * z_far * z_near) / (z_near - z_far);
|
||||||
|
m.matrix[3 + 2 * 4] = -1.0f;
|
||||||
|
|
||||||
|
if (handedness == handedness::left)
|
||||||
|
{
|
||||||
|
m = m * mat4::scale(1.0f, 1.0f, -1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipZ == clipzrange::zero_positive_w)
|
||||||
|
{
|
||||||
|
mat4 scale_translate = identity();
|
||||||
|
scale_translate.matrix[2 + 2 * 4] = 0.5f;
|
||||||
|
scale_translate.matrix[2 + 3 * 4] = 0.5f;
|
||||||
|
m = scale_translate * m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::frustum(float left, float right, float bottom, float top, float z_near, float z_far, handedness handedness, clipzrange clipZ)
|
||||||
|
{
|
||||||
|
float a = (right + left) / (right - left);
|
||||||
|
float b = (top + bottom) / (top - bottom);
|
||||||
|
float c = -(z_far + z_near) / (z_far - z_near);
|
||||||
|
float d = -(2.0f * z_far) / (z_far - z_near);
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0 + 0 * 4] = 2.0f * z_near / (right - left);
|
||||||
|
m.matrix[1 + 1 * 4] = 2.0f * z_near / (top - bottom);
|
||||||
|
m.matrix[0 + 2 * 4] = a;
|
||||||
|
m.matrix[1 + 2 * 4] = b;
|
||||||
|
m.matrix[2 + 2 * 4] = c;
|
||||||
|
m.matrix[2 + 3 * 4] = d;
|
||||||
|
m.matrix[3 + 2 * 4] = -1;
|
||||||
|
|
||||||
|
if (handedness == handedness::left)
|
||||||
|
{
|
||||||
|
m = m * mat4::scale(1.0f, 1.0f, -1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipZ == clipzrange::zero_positive_w)
|
||||||
|
{
|
||||||
|
mat4 scale_translate = identity();
|
||||||
|
scale_translate.matrix[2 + 2 * 4] = 0.5f;
|
||||||
|
scale_translate.matrix[2 + 3 * 4] = 0.5f;
|
||||||
|
m = scale_translate * m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::look_at(vec3 eye, vec3 center, vec3 up)
|
||||||
|
{
|
||||||
|
vec3 f = normalize(center - eye);
|
||||||
|
vec3 s = cross(f, normalize(up));
|
||||||
|
vec3 u = cross(s, f);
|
||||||
|
|
||||||
|
mat4 m = null();
|
||||||
|
m.matrix[0 + 0 * 4] = s.x;
|
||||||
|
m.matrix[0 + 1 * 4] = s.y;
|
||||||
|
m.matrix[0 + 2 * 4] = s.z;
|
||||||
|
m.matrix[1 + 0 * 4] = u.x;
|
||||||
|
m.matrix[1 + 1 * 4] = u.y;
|
||||||
|
m.matrix[1 + 2 * 4] = u.z;
|
||||||
|
m.matrix[2 + 0 * 4] = -f.x;
|
||||||
|
m.matrix[2 + 1 * 4] = -f.y;
|
||||||
|
m.matrix[2 + 2 * 4] = -f.z;
|
||||||
|
m.matrix[3 + 3 * 4] = 1.0f;
|
||||||
|
return m * translate(-eye.x, -eye.y, -eye.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 mat4::operator*(const mat4 &mult) const
|
||||||
|
{
|
||||||
|
mat4 result;
|
||||||
|
for (int x = 0; x < 4; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < 4; y++)
|
||||||
|
{
|
||||||
|
result.matrix[x + y * 4] =
|
||||||
|
matrix[0 * 4 + x] * mult.matrix[y * 4 + 0] +
|
||||||
|
matrix[1 * 4 + x] * mult.matrix[y * 4 + 1] +
|
||||||
|
matrix[2 * 4 + x] * mult.matrix[y * 4 + 2] +
|
||||||
|
matrix[3 * 4 + x] * mult.matrix[y * 4 + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 mat4::operator*(const vec4 &v) const
|
||||||
|
{
|
||||||
|
#ifdef NO_SSE
|
||||||
|
vec4 result;
|
||||||
|
result.x = matrix[0 * 4 + 0] * v.x + matrix[1 * 4 + 0] * v.y + matrix[2 * 4 + 0] * v.z + matrix[3 * 4 + 0] * v.w;
|
||||||
|
result.y = matrix[0 * 4 + 1] * v.x + matrix[1 * 4 + 1] * v.y + matrix[2 * 4 + 1] * v.z + matrix[3 * 4 + 1] * v.w;
|
||||||
|
result.z = matrix[0 * 4 + 2] * v.x + matrix[1 * 4 + 2] * v.y + matrix[2 * 4 + 2] * v.z + matrix[3 * 4 + 2] * v.w;
|
||||||
|
result.w = matrix[0 * 4 + 3] * v.x + matrix[1 * 4 + 3] * v.y + matrix[2 * 4 + 3] * v.z + matrix[3 * 4 + 3] * v.w;
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
__m128 m0 = _mm_loadu_ps(matrix);
|
||||||
|
__m128 m1 = _mm_loadu_ps(matrix + 4);
|
||||||
|
__m128 m2 = _mm_loadu_ps(matrix + 8);
|
||||||
|
__m128 m3 = _mm_loadu_ps(matrix + 12);
|
||||||
|
__m128 mv = _mm_loadu_ps(&v.x);
|
||||||
|
m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0)));
|
||||||
|
m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1)));
|
||||||
|
m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2)));
|
||||||
|
m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3)));
|
||||||
|
mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3);
|
||||||
|
vec4 result;
|
||||||
|
_mm_storeu_ps(&result.x, mv);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
mat3::mat3(const mat4 &initmatrix)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < 3; y++)
|
||||||
|
for (int x = 0; x < 3; x++)
|
||||||
|
matrix[x + y * 3] = initmatrix.matrix[x + y * 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::null()
|
||||||
|
{
|
||||||
|
mat3 m;
|
||||||
|
memset(m.matrix, 0, sizeof(m.matrix));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::identity()
|
||||||
|
{
|
||||||
|
mat3 m = null();
|
||||||
|
m.matrix[0] = 1.0f;
|
||||||
|
m.matrix[4] = 1.0f;
|
||||||
|
m.matrix[8] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::from_values(float *matrix)
|
||||||
|
{
|
||||||
|
mat3 m;
|
||||||
|
memcpy(m.matrix, matrix, sizeof(m.matrix));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::transpose(const mat3 &matrix)
|
||||||
|
{
|
||||||
|
mat3 m;
|
||||||
|
for (int y = 0; y < 3; y++)
|
||||||
|
for (int x = 0; x < 3; x++)
|
||||||
|
m.matrix[x + y * 3] = matrix.matrix[y + x * 3];
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
double mat3::determinant(const mat3 &m)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
value = m.matrix[0 * 3 + 0] * ((m.matrix[1 * 3 + 1] * m.matrix[2 * 3 + 2]) - (m.matrix[2 * 3 + 1] * m.matrix[1 * 3 + 2]));
|
||||||
|
value -= m.matrix[0 * 3 + 1] * ((m.matrix[1 * 3 + 0] * m.matrix[2 * 3 + 2]) - (m.matrix[2 * 3 + 0] * m.matrix[1 * 3 + 2]));
|
||||||
|
value += m.matrix[0 * 3 + 2] * ((m.matrix[1 * 3 + 0] * m.matrix[2 * 3 + 1]) - (m.matrix[2 * 3 + 0] * m.matrix[1 * 3 + 1]));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::adjoint(const mat3 &m)
|
||||||
|
{
|
||||||
|
mat3 result;
|
||||||
|
result.matrix[0 * 3 + 0] = ((m.matrix[1 * 3 + 1] * m.matrix[2 * 3 + 2]) - (m.matrix[1 * 3 + 2] * m.matrix[2 * 3 + 1]));
|
||||||
|
result.matrix[1 * 3 + 0] = -((m.matrix[1 * 3 + 0] * m.matrix[2 * 3 + 2]) - (m.matrix[1 * 3 + 2] * m.matrix[2 * 3 + 0]));
|
||||||
|
result.matrix[2 * 3 + 0] = ((m.matrix[1 * 3 + 0] * m.matrix[2 * 3 + 1]) - (m.matrix[1 * 3 + 1] * m.matrix[2 * 3 + 0]));
|
||||||
|
result.matrix[0 * 3 + 1] = -((m.matrix[0 * 3 + 1] * m.matrix[2 * 3 + 2]) - (m.matrix[0 * 3 + 2] * m.matrix[2 * 3 + 1]));
|
||||||
|
result.matrix[1 * 3 + 1] = ((m.matrix[0 * 3 + 0] * m.matrix[2 * 3 + 2]) - (m.matrix[0 * 3 + 2] * m.matrix[2 * 3 + 0]));
|
||||||
|
result.matrix[2 * 3 + 1] = -((m.matrix[0 * 3 + 0] * m.matrix[2 * 3 + 1]) - (m.matrix[0 * 3 + 1] * m.matrix[2 * 3 + 0]));
|
||||||
|
result.matrix[0 * 3 + 2] = ((m.matrix[0 * 3 + 1] * m.matrix[1 * 3 + 2]) - (m.matrix[0 * 3 + 2] * m.matrix[1 * 3 + 1]));
|
||||||
|
result.matrix[1 * 3 + 2] = -((m.matrix[0 * 3 + 0] * m.matrix[1 * 3 + 2]) - (m.matrix[0 * 3 + 2] * m.matrix[1 * 3 + 0]));
|
||||||
|
result.matrix[2 * 3 + 2] = ((m.matrix[0 * 3 + 0] * m.matrix[1 * 3 + 1]) - (m.matrix[0 * 3 + 1] * m.matrix[1 * 3 + 0]));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::inverse(const mat3 &matrix)
|
||||||
|
{
|
||||||
|
double d = mat3::determinant(matrix);
|
||||||
|
|
||||||
|
// Inverse unknown when determinant is close to zero
|
||||||
|
if (fabs(d) < 1e-15)
|
||||||
|
{
|
||||||
|
return null();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mat3 result = mat3::adjoint(matrix);
|
||||||
|
|
||||||
|
d = 1.0 / d; // Inverse the determinant
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
result.matrix[i] = (float)(result.matrix[i] * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 mat3::operator*(const mat3 &mult) const
|
||||||
|
{
|
||||||
|
mat3 result;
|
||||||
|
for (int x = 0; x < 3; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < 3; y++)
|
||||||
|
{
|
||||||
|
result.matrix[x + y * 3] =
|
||||||
|
matrix[0 * 3 + x] * mult.matrix[y * 3 + 0] +
|
||||||
|
matrix[1 * 3 + x] * mult.matrix[y * 3 + 1] +
|
||||||
|
matrix[2 * 3 + x] * mult.matrix[y * 3 + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 mat3::operator*(const vec3 &v) const
|
||||||
|
{
|
||||||
|
vec3 result;
|
||||||
|
result.x = matrix[0 * 3 + 0] * v.x + matrix[1 * 3 + 0] * v.y + matrix[2 * 3 + 0] * v.z;
|
||||||
|
result.y = matrix[0 * 3 + 1] * v.x + matrix[1 * 3 + 1] * v.y + matrix[2 * 3 + 1] * v.z;
|
||||||
|
result.z = matrix[0 * 3 + 2] * v.x + matrix[1 * 3 + 2] * v.y + matrix[2 * 3 + 2] * v.z;
|
||||||
|
return result;
|
||||||
|
}
|
117
src/math/mat.h
Normal file
117
src/math/mat.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vec.h"
|
||||||
|
|
||||||
|
enum class handedness
|
||||||
|
{
|
||||||
|
left,
|
||||||
|
right
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class clipzrange
|
||||||
|
{
|
||||||
|
negative_positive_w, // OpenGL, -wclip <= zclip <= wclip
|
||||||
|
zero_positive_w // Direct3D, 0 <= zclip <= wclip
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat4
|
||||||
|
{
|
||||||
|
mat4() = default;
|
||||||
|
|
||||||
|
static mat4 null();
|
||||||
|
static mat4 identity();
|
||||||
|
static mat4 from_values(float *matrix);
|
||||||
|
static mat4 transpose(const mat4 &matrix);
|
||||||
|
static mat4 translate(float x, float y, float z);
|
||||||
|
static mat4 translate(const vec3 &v) { return translate(v.x, v.y, v.z); }
|
||||||
|
static mat4 scale(float x, float y, float z);
|
||||||
|
static mat4 scale(const vec3 &v) { return scale(v.x, v.y, v.z); }
|
||||||
|
static mat4 rotate(float angle, float x, float y, float z);
|
||||||
|
static mat4 rotate(float angle, const vec3 &v) { return rotate(angle, v.x, v.y, v.z); }
|
||||||
|
static mat4 quaternion(float x, float y, float z, float w); // This function assumes that the quarternion is normalized.
|
||||||
|
static mat4 quaternion(const vec4 &q) { return quaternion(q.x, q.y, q.z, q.w); }
|
||||||
|
static mat4 swap_yz();
|
||||||
|
static mat4 perspective(float fovy, float aspect, float z_near, float z_far, handedness handedness, clipzrange clipz);
|
||||||
|
static mat4 frustum(float left, float right, float bottom, float top, float z_near, float z_far, handedness handedness, clipzrange clipz);
|
||||||
|
static mat4 look_at(vec3 eye, vec3 center, vec3 up);
|
||||||
|
|
||||||
|
vec4 operator*(const vec4 &v) const;
|
||||||
|
mat4 operator*(const mat4 &m) const;
|
||||||
|
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
|
||||||
|
float matrix[4 * 4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat3
|
||||||
|
{
|
||||||
|
mat3() = default;
|
||||||
|
mat3(const mat4 &m);
|
||||||
|
|
||||||
|
static mat3 null();
|
||||||
|
static mat3 identity();
|
||||||
|
static mat3 from_values(float *matrix);
|
||||||
|
static mat3 transpose(const mat3 &matrix);
|
||||||
|
static mat3 inverse(const mat3 &matrix);
|
||||||
|
static mat3 adjoint(const mat3 &matrix);
|
||||||
|
|
||||||
|
static double determinant(const mat3 &m);
|
||||||
|
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
|
||||||
|
vec3 operator*(const vec3 &v) const;
|
||||||
|
mat3 operator*(const mat3 &m) const;
|
||||||
|
|
||||||
|
float matrix[3 * 3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat2
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[2 * 2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat4x3
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[4 * 3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat4x2
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[4 * 2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat3x4
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[3 * 4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat3x2
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[3 * 2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat2x4
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[2 * 4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mat2x3
|
||||||
|
{
|
||||||
|
float operator[](size_t i) const { return matrix[i]; }
|
||||||
|
float &operator[](size_t i) { return matrix[i]; }
|
||||||
|
float matrix[2 * 3];
|
||||||
|
};
|
|
@ -44,7 +44,7 @@ int Math::RoundPowerOfTwo(int x)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Math::CubicCurve(const Vec3 &start, const Vec3 &end, const float time, const Vec3 &point, Vec3 *vec)
|
void Math::CubicCurve(const vec3 &start, const vec3 &end, const float time, const vec3 &point, vec3 *vec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float xyz[3];
|
float xyz[3];
|
||||||
|
@ -60,7 +60,7 @@ void Math::CubicCurve(const Vec3 &start, const Vec3 &end, const float time, cons
|
||||||
vec->z = xyz[2];
|
vec->z = xyz[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Math::QuadraticCurve(const Vec3 &start, const Vec3 &end, const float time, const Vec3 &pt1, const Vec3 &pt2, Vec3 *vec)
|
void Math::QuadraticCurve(const vec3 &start, const vec3 &end, const float time, const vec3 &pt1, const vec3 &pt2, vec3 *vec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float xyz[3];
|
float xyz[3];
|
||||||
|
|
1253
src/math/mathlib.h
1253
src/math/mathlib.h
File diff suppressed because it is too large
Load diff
|
@ -1,599 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Note: this is a modified version of dlight. It is not the original software.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
|
||||||
// svkaiser@gmail.com
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// DESCRIPTION: Matrix (left handed) operations
|
|
||||||
//
|
|
||||||
// Reference:
|
|
||||||
// _________________
|
|
||||||
// | 0 4 8 12 |
|
|
||||||
// | 1 5 9 13 |
|
|
||||||
// | 2 6 10 14 |
|
|
||||||
// | 3 7 11 15 |
|
|
||||||
// _________________
|
|
||||||
//
|
|
||||||
// translation
|
|
||||||
// _________________
|
|
||||||
// | 0 4 8 x |
|
|
||||||
// | 1 5 9 y |
|
|
||||||
// | 2 6 10 z |
|
|
||||||
// | 3 7 11 15 |
|
|
||||||
// _________________
|
|
||||||
//
|
|
||||||
// rotation x
|
|
||||||
// _________________
|
|
||||||
// |(1) 4 8 x |
|
|
||||||
// | 1 xc -xs y |
|
|
||||||
// | 2 xs xs z |
|
|
||||||
// | 3 7 11 (1) |
|
|
||||||
// _________________
|
|
||||||
//
|
|
||||||
// rotation y
|
|
||||||
// _________________
|
|
||||||
// | yc 4 ys 12 |
|
|
||||||
// | 1 (1) 9 13 |
|
|
||||||
// |-ys 6 yc 14 |
|
|
||||||
// | 3 7 11 (1) |
|
|
||||||
// _________________
|
|
||||||
//
|
|
||||||
// rotation z
|
|
||||||
// _________________
|
|
||||||
// | zc -zs 8 12 |
|
|
||||||
// | zs zc 9 13 |
|
|
||||||
// | 2 6 (1) 14 |
|
|
||||||
// | 3 7 11 (1) |
|
|
||||||
// _________________
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "mathlib.h"
|
|
||||||
|
|
||||||
Mat4::Mat4()
|
|
||||||
{
|
|
||||||
Identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4::Mat4(const Mat4 &mtx)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
vectors[i].x = mtx.vectors[i].x;
|
|
||||||
vectors[i].y = mtx.vectors[i].y;
|
|
||||||
vectors[i].z = mtx.vectors[i].z;
|
|
||||||
vectors[i].w = mtx.vectors[i].w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4::Mat4(const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
Identity(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4::Mat4(const Quat &quat)
|
|
||||||
{
|
|
||||||
float xx = quat.x * quat.x;
|
|
||||||
float yx = quat.y * quat.x;
|
|
||||||
float zx = quat.z * quat.x;
|
|
||||||
float wx = quat.w * quat.x;
|
|
||||||
float yy = quat.y * quat.y;
|
|
||||||
float zy = quat.z * quat.y;
|
|
||||||
float wy = quat.w * quat.y;
|
|
||||||
float zz = quat.z * quat.z;
|
|
||||||
float wz = quat.w * quat.z;
|
|
||||||
float ww = quat.w * quat.w;
|
|
||||||
|
|
||||||
vectors[0].Set(
|
|
||||||
((ww + xx) - yy) - zz,
|
|
||||||
(wz + wz) + (yx + yx),
|
|
||||||
(zx + zx) - (wy + wy),
|
|
||||||
0);
|
|
||||||
vectors[1].Set(
|
|
||||||
(yx + yx) - (wz + wz),
|
|
||||||
(yy + (ww - xx)) - zz,
|
|
||||||
(wx + wx) + (zy + zy),
|
|
||||||
0);
|
|
||||||
vectors[2].Set(
|
|
||||||
(wy + wy + zx + zx),
|
|
||||||
(zy + zy) - (wx + wx),
|
|
||||||
((ww - xx) - yy) + zz,
|
|
||||||
0);
|
|
||||||
vectors[3].Set(0, 0, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4::Mat4(const float angle, const int axis)
|
|
||||||
{
|
|
||||||
float s;
|
|
||||||
float c;
|
|
||||||
|
|
||||||
s = Math::Sin(angle);
|
|
||||||
c = Math::Cos(angle);
|
|
||||||
|
|
||||||
Identity();
|
|
||||||
|
|
||||||
switch (axis)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
this->vectors[0].x = c;
|
|
||||||
this->vectors[0].z = -s;
|
|
||||||
this->vectors[3].x = s;
|
|
||||||
this->vectors[3].z = c;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this->vectors[1].y = c;
|
|
||||||
this->vectors[1].z = s;
|
|
||||||
this->vectors[2].y = -s;
|
|
||||||
this->vectors[2].z = c;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this->vectors[0].x = c;
|
|
||||||
this->vectors[0].y = s;
|
|
||||||
this->vectors[1].x = -s;
|
|
||||||
this->vectors[1].y = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::Identity()
|
|
||||||
{
|
|
||||||
vectors[0].Set(1, 0, 0, 0);
|
|
||||||
vectors[1].Set(0, 1, 0, 0);
|
|
||||||
vectors[2].Set(0, 0, 1, 0);
|
|
||||||
vectors[3].Set(0, 0, 0, 1);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::Identity(const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
vectors[0].Set(x, 0, 0, 0);
|
|
||||||
vectors[1].Set(0, y, 0, 0);
|
|
||||||
vectors[2].Set(0, 0, z, 0);
|
|
||||||
vectors[3].Set(0, 0, 0, 1);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::SetTranslation(const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
vectors[3].ToVec3().Set(x, y, z);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::SetTranslation(const Vec3 &vector)
|
|
||||||
{
|
|
||||||
vectors[3].ToVec3() = vector;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::AddTranslation(const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
vectors[3].x += x;
|
|
||||||
vectors[3].y += y;
|
|
||||||
vectors[3].z += z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::AddTranslation(const Vec3 &vector)
|
|
||||||
{
|
|
||||||
vectors[3].ToVec3() += vector;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::Scale(const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
vectors[0].ToVec3() *= x;
|
|
||||||
vectors[1].ToVec3() *= y;
|
|
||||||
vectors[2].ToVec3() *= z;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::Scale(const Vec3 &vector)
|
|
||||||
{
|
|
||||||
vectors[0].ToVec3() *= vector.x;
|
|
||||||
vectors[1].ToVec3() *= vector.y;
|
|
||||||
vectors[2].ToVec3() *= vector.z;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 Mat4::Scale(const Mat4 &mtx, const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
Mat4 out;
|
|
||||||
|
|
||||||
out.vectors[0].ToVec3() = mtx.vectors[0].ToVec3() * x;
|
|
||||||
out.vectors[1].ToVec3() = mtx.vectors[1].ToVec3() * y;
|
|
||||||
out.vectors[2].ToVec3() = mtx.vectors[2].ToVec3() * z;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::Transpose()
|
|
||||||
{
|
|
||||||
Vec3 v1 = vectors[1].ToVec3();
|
|
||||||
Vec3 v2 = vectors[2].ToVec3();
|
|
||||||
|
|
||||||
vectors[1].ToVec3() = v2;
|
|
||||||
vectors[2].ToVec3() = v1;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 Mat4::Transpose(const Mat4 &mtx)
|
|
||||||
{
|
|
||||||
Mat4 out;
|
|
||||||
|
|
||||||
out.vectors[0].ToVec3() = mtx.vectors[0].ToVec3();
|
|
||||||
out.vectors[1].ToVec3() = mtx.vectors[2].ToVec3();
|
|
||||||
out.vectors[2].ToVec3() = mtx.vectors[1].ToVec3();
|
|
||||||
out.vectors[3].ToVec3() = mtx.vectors[3].ToVec3();
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 Mat4::Invert(Mat4 &mtx)
|
|
||||||
{
|
|
||||||
float d;
|
|
||||||
float *m;
|
|
||||||
|
|
||||||
m = mtx.ToFloatPtr();
|
|
||||||
|
|
||||||
d = m[0] * m[10] * m[5] -
|
|
||||||
m[0] * m[9] * m[6] -
|
|
||||||
m[1] * m[4] * m[10] +
|
|
||||||
m[2] * m[4] * m[9] +
|
|
||||||
m[1] * m[6] * m[8] -
|
|
||||||
m[2] * m[5] * m[8];
|
|
||||||
|
|
||||||
if (d != 0.0f)
|
|
||||||
{
|
|
||||||
Mat4 inv;
|
|
||||||
|
|
||||||
d = (1.0f / d);
|
|
||||||
|
|
||||||
inv.vectors[0].x = (m[10] * m[5] - m[9] * m[6]) * d;
|
|
||||||
inv.vectors[0].y = -((m[1] * m[10] - m[2] * m[9]) * d);
|
|
||||||
inv.vectors[0].z = (m[1] * m[6] - m[2] * m[5]) * d;
|
|
||||||
inv.vectors[0].w = 0;
|
|
||||||
inv.vectors[1].x = (m[6] * m[8] - m[4] * m[10]) * d;
|
|
||||||
inv.vectors[1].y = (m[0] * m[10] - m[2] * m[8]) * d;
|
|
||||||
inv.vectors[1].z = -((m[0] * m[6] - m[2] * m[4]) * d);
|
|
||||||
inv.vectors[1].w = 0;
|
|
||||||
inv.vectors[2].x = -((m[5] * m[8] - m[4] * m[9]) * d);
|
|
||||||
inv.vectors[2].y = (m[1] * m[8] - m[0] * m[9]) * d;
|
|
||||||
inv.vectors[2].z = -((m[1] * m[4] - m[0] * m[5]) * d);
|
|
||||||
inv.vectors[2].w = 0;
|
|
||||||
inv.vectors[3].x = (
|
|
||||||
(m[13] * m[10] - m[14] * m[9]) * m[4]
|
|
||||||
+ m[14] * m[5] * m[8]
|
|
||||||
- m[13] * m[6] * m[8]
|
|
||||||
- m[12] * m[10] * m[5]
|
|
||||||
+ m[12] * m[9] * m[6]) * d;
|
|
||||||
inv.vectors[3].y = (
|
|
||||||
m[0] * m[14] * m[9]
|
|
||||||
- m[0] * m[13] * m[10]
|
|
||||||
- m[14] * m[1] * m[8]
|
|
||||||
+ m[13] * m[2] * m[8]
|
|
||||||
+ m[12] * m[1] * m[10]
|
|
||||||
- m[12] * m[2] * m[9]) * d;
|
|
||||||
inv.vectors[3].z = -(
|
|
||||||
(m[0] * m[14] * m[5]
|
|
||||||
- m[0] * m[13] * m[6]
|
|
||||||
- m[14] * m[1] * m[4]
|
|
||||||
+ m[13] * m[2] * m[4]
|
|
||||||
+ m[12] * m[1] * m[6]
|
|
||||||
- m[12] * m[2] * m[5]) * d);
|
|
||||||
inv.vectors[3].w = 1.0f;
|
|
||||||
|
|
||||||
return inv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mtx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mat4::SetViewProjection(float aspect, float fov, float zNear, float zFar)
|
|
||||||
{
|
|
||||||
float top = zNear * Math::Tan(fov * M_PI / 360.0f);
|
|
||||||
float bottom = -top;
|
|
||||||
float left = bottom * aspect;
|
|
||||||
float right = top * aspect;
|
|
||||||
|
|
||||||
vectors[0].x = (2 * zNear) / (right - left);
|
|
||||||
vectors[1].y = (2 * zNear) / (top - bottom);
|
|
||||||
vectors[3].z = -(2 * zFar * zNear) / (zFar - zNear);
|
|
||||||
|
|
||||||
vectors[2].x = (right + left) / (right - left);
|
|
||||||
vectors[2].y = (top + bottom) / (top - bottom);
|
|
||||||
vectors[2].z = -(zFar + zNear) / (zFar - zNear);
|
|
||||||
|
|
||||||
vectors[0].y = 0;
|
|
||||||
vectors[0].z = 0;
|
|
||||||
vectors[0].w = 0;
|
|
||||||
vectors[1].x = 0;
|
|
||||||
vectors[1].w = 0;
|
|
||||||
vectors[1].z = 0;
|
|
||||||
vectors[2].w = -1;
|
|
||||||
vectors[3].x = 0;
|
|
||||||
vectors[3].y = 0;
|
|
||||||
vectors[3].w = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mat4::SetOrtho(float left, float right, float bottom, float top, float zNear, float zFar)
|
|
||||||
{
|
|
||||||
vectors[0].x = 2 / (right - left);
|
|
||||||
vectors[1].y = 2 / (top - bottom);
|
|
||||||
vectors[2].z = -2 / (zFar - zNear);
|
|
||||||
|
|
||||||
vectors[3].x = -(right + left) / (right - left);
|
|
||||||
vectors[3].y = -(top + bottom) / (top - bottom);
|
|
||||||
vectors[3].z = -(zFar + zNear) / (zFar - zNear);
|
|
||||||
vectors[3].w = 1;
|
|
||||||
|
|
||||||
vectors[0].y = 0;
|
|
||||||
vectors[0].z = 0;
|
|
||||||
vectors[0].w = 0;
|
|
||||||
vectors[1].x = 0;
|
|
||||||
vectors[1].z = 0;
|
|
||||||
vectors[1].w = 0;
|
|
||||||
vectors[2].x = 0;
|
|
||||||
vectors[2].y = 0;
|
|
||||||
vectors[2].w = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Mat4::ToQuat()
|
|
||||||
{
|
|
||||||
float t;
|
|
||||||
float d;
|
|
||||||
float mx;
|
|
||||||
float my;
|
|
||||||
float mz;
|
|
||||||
float m21;
|
|
||||||
float m20;
|
|
||||||
float m10;
|
|
||||||
Quat q;
|
|
||||||
|
|
||||||
mx = vectors[0][0];
|
|
||||||
my = vectors[1][1];
|
|
||||||
mz = vectors[2][2];
|
|
||||||
|
|
||||||
m21 = (vectors[2][1] - vectors[1][2]);
|
|
||||||
m20 = (vectors[2][0] - vectors[0][2]);
|
|
||||||
m10 = (vectors[1][0] - vectors[0][1]);
|
|
||||||
|
|
||||||
t = 1.0f + mx + my + mz;
|
|
||||||
|
|
||||||
if (t > 0)
|
|
||||||
{
|
|
||||||
d = 0.5f / Math::Sqrt(t);
|
|
||||||
q.x = m21 * d;
|
|
||||||
q.y = m20 * d;
|
|
||||||
q.z = m10 * d;
|
|
||||||
q.w = 0.25f / d;
|
|
||||||
}
|
|
||||||
else if (mx > my && mx > mz)
|
|
||||||
{
|
|
||||||
d = Math::Sqrt(1.0f + mx - my - mz) * 2;
|
|
||||||
q.x = 0.5f / d;
|
|
||||||
q.y = m10 / d;
|
|
||||||
q.z = m20 / d;
|
|
||||||
q.w = m21 / d;
|
|
||||||
}
|
|
||||||
else if (my > mz)
|
|
||||||
{
|
|
||||||
d = Math::Sqrt(1.0f + my - mx - mz) * 2;
|
|
||||||
q.x = m10 / d;
|
|
||||||
q.y = 0.5f / d;
|
|
||||||
q.z = m21 / d;
|
|
||||||
q.w = m20 / d;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d = Math::Sqrt(1.0f + mz - mx - my) * 2;
|
|
||||||
q.x = m20 / d;
|
|
||||||
q.y = m21 / d;
|
|
||||||
q.z = 0.5f / d;
|
|
||||||
q.w = m10 / d;
|
|
||||||
}
|
|
||||||
|
|
||||||
q.Normalize();
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 Mat4::operator*(const Vec3 &vector)
|
|
||||||
{
|
|
||||||
Mat4 out(*this);
|
|
||||||
|
|
||||||
out.vectors[3].ToVec3() +=
|
|
||||||
vectors[0].ToVec3() * vector.x +
|
|
||||||
vectors[1].ToVec3() * vector.y +
|
|
||||||
vectors[2].ToVec3() * vector.z;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::operator*=(const Vec3 &vector)
|
|
||||||
{
|
|
||||||
vectors[3].ToVec3() +=
|
|
||||||
vectors[0].ToVec3() * vector.x +
|
|
||||||
vectors[1].ToVec3() * vector.y +
|
|
||||||
vectors[2].ToVec3() * vector.z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
float *Mat4::ToFloatPtr()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<float*>(vectors);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 Mat4::operator*(const Mat4 &matrix)
|
|
||||||
{
|
|
||||||
Mat4 out;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
out.vectors[i].x =
|
|
||||||
vectors[i].x * matrix.vectors[0].x +
|
|
||||||
vectors[i].y * matrix.vectors[1].x +
|
|
||||||
vectors[i].z * matrix.vectors[2].x +
|
|
||||||
vectors[i].w * matrix.vectors[3].x;
|
|
||||||
out.vectors[i].y =
|
|
||||||
vectors[i].x * matrix.vectors[0].y +
|
|
||||||
vectors[i].y * matrix.vectors[1].y +
|
|
||||||
vectors[i].z * matrix.vectors[2].y +
|
|
||||||
vectors[i].w * matrix.vectors[3].y;
|
|
||||||
out.vectors[i].z =
|
|
||||||
vectors[i].x * matrix.vectors[0].z +
|
|
||||||
vectors[i].y * matrix.vectors[1].z +
|
|
||||||
vectors[i].z * matrix.vectors[2].z +
|
|
||||||
vectors[i].w * matrix.vectors[3].z;
|
|
||||||
out.vectors[i].w =
|
|
||||||
vectors[i].x * matrix.vectors[0].w +
|
|
||||||
vectors[i].y * matrix.vectors[1].w +
|
|
||||||
vectors[i].z * matrix.vectors[2].w +
|
|
||||||
vectors[i].w * matrix.vectors[3].w;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::operator*=(const Mat4 &matrix)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
vectors[i].x =
|
|
||||||
vectors[i].x * matrix.vectors[0].x +
|
|
||||||
vectors[i].y * matrix.vectors[1].x +
|
|
||||||
vectors[i].z * matrix.vectors[2].x +
|
|
||||||
vectors[i].w * matrix.vectors[3].x;
|
|
||||||
vectors[i].y =
|
|
||||||
vectors[i].x * matrix.vectors[0].y +
|
|
||||||
vectors[i].y * matrix.vectors[1].y +
|
|
||||||
vectors[i].z * matrix.vectors[2].y +
|
|
||||||
vectors[i].w * matrix.vectors[3].y;
|
|
||||||
vectors[i].z =
|
|
||||||
vectors[i].x * matrix.vectors[0].z +
|
|
||||||
vectors[i].y * matrix.vectors[1].z +
|
|
||||||
vectors[i].z * matrix.vectors[2].z +
|
|
||||||
vectors[i].w * matrix.vectors[3].z;
|
|
||||||
vectors[i].w =
|
|
||||||
vectors[i].x * matrix.vectors[0].w +
|
|
||||||
vectors[i].y * matrix.vectors[1].w +
|
|
||||||
vectors[i].z * matrix.vectors[2].w +
|
|
||||||
vectors[i].w * matrix.vectors[3].w;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 operator*(const Mat4 &m1, const Mat4 &m2)
|
|
||||||
{
|
|
||||||
Mat4 out;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
out.vectors[i].x =
|
|
||||||
m1.vectors[i].x * m2.vectors[0].x +
|
|
||||||
m1.vectors[i].y * m2.vectors[1].x +
|
|
||||||
m1.vectors[i].z * m2.vectors[2].x +
|
|
||||||
m1.vectors[i].w * m2.vectors[3].x;
|
|
||||||
out.vectors[i].y =
|
|
||||||
m1.vectors[i].x * m2.vectors[0].y +
|
|
||||||
m1.vectors[i].y * m2.vectors[1].y +
|
|
||||||
m1.vectors[i].z * m2.vectors[2].y +
|
|
||||||
m1.vectors[i].w * m2.vectors[3].y;
|
|
||||||
out.vectors[i].z =
|
|
||||||
m1.vectors[i].x * m2.vectors[0].z +
|
|
||||||
m1.vectors[i].y * m2.vectors[1].z +
|
|
||||||
m1.vectors[i].z * m2.vectors[2].z +
|
|
||||||
m1.vectors[i].w * m2.vectors[3].z;
|
|
||||||
out.vectors[i].w =
|
|
||||||
m1.vectors[i].x * m2.vectors[0].w +
|
|
||||||
m1.vectors[i].y * m2.vectors[1].w +
|
|
||||||
m1.vectors[i].z * m2.vectors[2].w +
|
|
||||||
m1.vectors[i].w * m2.vectors[3].w;
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 Mat4::operator|(const Mat4 &matrix)
|
|
||||||
{
|
|
||||||
Mat4 out;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
out.vectors[i].x =
|
|
||||||
vectors[i].x * matrix.vectors[0].x +
|
|
||||||
vectors[i].y * matrix.vectors[1].x +
|
|
||||||
vectors[i].z * matrix.vectors[2].x;
|
|
||||||
out.vectors[i].y =
|
|
||||||
vectors[i].x * matrix.vectors[0].y +
|
|
||||||
vectors[i].y * matrix.vectors[1].y +
|
|
||||||
vectors[i].z * matrix.vectors[2].y;
|
|
||||||
out.vectors[i].z =
|
|
||||||
vectors[i].x * matrix.vectors[0].z +
|
|
||||||
vectors[i].y * matrix.vectors[1].z +
|
|
||||||
vectors[i].z * matrix.vectors[2].z;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.vectors[3].x =
|
|
||||||
vectors[3].x * matrix.vectors[0].x +
|
|
||||||
vectors[3].y * matrix.vectors[1].x +
|
|
||||||
vectors[3].z * matrix.vectors[2].x + matrix.vectors[3].x;
|
|
||||||
out.vectors[3].y =
|
|
||||||
vectors[3].x * matrix.vectors[0].y +
|
|
||||||
vectors[3].y * matrix.vectors[1].y +
|
|
||||||
vectors[3].z * matrix.vectors[2].y + matrix.vectors[3].y;
|
|
||||||
out.vectors[3].z =
|
|
||||||
vectors[3].x * matrix.vectors[0].z +
|
|
||||||
vectors[3].y * matrix.vectors[1].z +
|
|
||||||
vectors[3].z * matrix.vectors[2].z + matrix.vectors[3].z;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::operator=(const Mat4 &matrix)
|
|
||||||
{
|
|
||||||
vectors[0] = matrix.vectors[0];
|
|
||||||
vectors[1] = matrix.vectors[1];
|
|
||||||
vectors[2] = matrix.vectors[2];
|
|
||||||
vectors[3] = matrix.vectors[3];
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4 &Mat4::operator=(const float *m)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < 4; j++)
|
|
||||||
{
|
|
||||||
vectors[i][j] = m[i * 4 + j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
|
@ -44,18 +44,18 @@ Plane::Plane(const float a, const float b, const float c, const float d)
|
||||||
this->d = d;
|
this->d = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane::Plane(const Vec3 &pt1, const Vec3 &pt2, const Vec3 &pt3)
|
Plane::Plane(const vec3 &pt1, const vec3 &pt2, const vec3 &pt3)
|
||||||
{
|
{
|
||||||
SetNormal(pt1, pt2, pt3);
|
SetNormal(pt1, pt2, pt3);
|
||||||
this->d = Vec3::Dot(pt1, Normal());
|
this->d = dot(pt1, Normal());
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane::Plane(const Vec3 &normal, const Vec3 &point)
|
Plane::Plane(const vec3 &normal, const vec3 &point)
|
||||||
{
|
{
|
||||||
this->a = normal.x;
|
this->a = normal.x;
|
||||||
this->b = normal.y;
|
this->b = normal.y;
|
||||||
this->c = normal.z;
|
this->c = normal.z;
|
||||||
this->d = point.Dot(normal);
|
this->d = dot(point, normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane::Plane(const Plane &plane)
|
Plane::Plane(const Plane &plane)
|
||||||
|
@ -66,36 +66,36 @@ Plane::Plane(const Plane &plane)
|
||||||
this->d = plane.d;
|
this->d = plane.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane &Plane::SetNormal(const Vec3 &normal)
|
Plane &Plane::SetNormal(const vec3 &normal)
|
||||||
{
|
{
|
||||||
Normal() = normal;
|
Normal() = normal;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane &Plane::SetNormal(const Vec3 &pt1, const Vec3 &pt2, const Vec3 &pt3)
|
Plane &Plane::SetNormal(const vec3 &pt1, const vec3 &pt2, const vec3 &pt3)
|
||||||
{
|
{
|
||||||
Normal() = (pt2 - pt1).Cross(pt3 - pt2).Normalize();
|
Normal() = normalize(cross(pt2 - pt1, pt3 - pt2));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 const &Plane::Normal() const
|
vec3 const &Plane::Normal() const
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<const Vec3*>(&a);
|
return *reinterpret_cast<const vec3*>(&a);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 &Plane::Normal()
|
vec3 &Plane::Normal()
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<Vec3*>(&a);
|
return *reinterpret_cast<vec3*>(&a);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Plane::Distance(const Vec3 &point)
|
float Plane::Distance(const vec3 &point)
|
||||||
{
|
{
|
||||||
return point.Dot(Normal());
|
return dot(point, Normal());
|
||||||
}
|
}
|
||||||
|
|
||||||
Plane &Plane::SetDistance(const Vec3 &point)
|
Plane &Plane::SetDistance(const vec3 &point)
|
||||||
{
|
{
|
||||||
this->d = point.Dot(Normal());
|
this->d = dot(point, Normal());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ bool Plane::IsFacing(const float yaw)
|
||||||
|
|
||||||
float Plane::ToYaw()
|
float Plane::ToYaw()
|
||||||
{
|
{
|
||||||
float d = Normal().Unit();
|
float d = length(Normal());
|
||||||
|
|
||||||
if (d != 0)
|
if (d != 0)
|
||||||
{
|
{
|
||||||
|
@ -125,23 +125,17 @@ float Plane::ToYaw()
|
||||||
|
|
||||||
float Plane::ToPitch()
|
float Plane::ToPitch()
|
||||||
{
|
{
|
||||||
return Math::ACos(Vec3::vecUp.Dot(Normal()));
|
return Math::ACos(dot(vec3(0.0f, 0.0f, 1.0f), Normal()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Quat Plane::ToQuat()
|
vec4 const &Plane::ToVec4() const
|
||||||
{
|
{
|
||||||
Vec3 cross = Vec3::vecUp.Cross(Normal()).Normalize();
|
return *reinterpret_cast<const vec4*>(&a);
|
||||||
return Quat(Math::ACos(Vec3::vecUp.Dot(Normal())), cross);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 const &Plane::ToVec4() const
|
vec4 &Plane::ToVec4()
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<const Vec4*>(&a);
|
return *reinterpret_cast<vec4*>(&a);
|
||||||
}
|
|
||||||
|
|
||||||
Vec4 &Plane::ToVec4()
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<Vec4*>(&a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Plane::PlaneAxis Plane::BestAxis() const
|
const Plane::PlaneAxis Plane::BestAxis() const
|
||||||
|
@ -163,8 +157,8 @@ const Plane::PlaneAxis Plane::BestAxis() const
|
||||||
return AXIS_XY;
|
return AXIS_XY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 Plane::GetInclination()
|
vec3 Plane::GetInclination()
|
||||||
{
|
{
|
||||||
Vec3 dir = Normal() * Vec3::vecUp.Dot(Normal());
|
vec3 dir = Normal() * dot(vec3(0.0f, 0.0f, 1.0f), Normal());
|
||||||
return (Vec3::vecUp - dir).Normalize();
|
return normalize(vec3(0.0f, 0.0f, 1.0f) - dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,333 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Note: this is a modified version of dlight. It is not the original software.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
|
||||||
// svkaiser@gmail.com
|
|
||||||
//
|
|
||||||
// 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 <math.h>
|
|
||||||
#include "mathlib.h"
|
|
||||||
|
|
||||||
Quat::Quat()
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat::Quat(const float angle, const float x, const float y, const float z)
|
|
||||||
{
|
|
||||||
float s = Math::Sin(angle * 0.5f);
|
|
||||||
float c = Math::Cos(angle * 0.5f);
|
|
||||||
|
|
||||||
this->x = x * s;
|
|
||||||
this->y = y * s;
|
|
||||||
this->z = z * s;
|
|
||||||
this->w = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat::Quat(const float angle, Vec3 &vector)
|
|
||||||
{
|
|
||||||
float s = Math::Sin(angle * 0.5f);
|
|
||||||
float c = Math::Cos(angle * 0.5f);
|
|
||||||
|
|
||||||
this->x = vector.x * s;
|
|
||||||
this->y = vector.y * s;
|
|
||||||
this->z = vector.z * s;
|
|
||||||
this->w = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat::Quat(const float angle, const Vec3 &vector)
|
|
||||||
{
|
|
||||||
float s = Math::Sin(angle * 0.5f);
|
|
||||||
float c = Math::Cos(angle * 0.5f);
|
|
||||||
|
|
||||||
this->x = vector.x * s;
|
|
||||||
this->y = vector.y * s;
|
|
||||||
this->z = vector.z * s;
|
|
||||||
this->w = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Quat::Set(const float x, const float y, const float z, const float w)
|
|
||||||
{
|
|
||||||
this->x = x;
|
|
||||||
this->y = y;
|
|
||||||
this->z = z;
|
|
||||||
this->w = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Quat::Clear()
|
|
||||||
{
|
|
||||||
x = y = z = 0.0f;
|
|
||||||
w = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Quat::UnitSq() const
|
|
||||||
{
|
|
||||||
return x * x + y * y + z * z + w * w;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Quat::Unit() const
|
|
||||||
{
|
|
||||||
return Math::Sqrt(UnitSq());
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::Normalize()
|
|
||||||
{
|
|
||||||
float d = Unit();
|
|
||||||
if (d != 0.0f)
|
|
||||||
{
|
|
||||||
d = 1.0f / d;
|
|
||||||
*this *= d;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::Inverse() const
|
|
||||||
{
|
|
||||||
Quat out;
|
|
||||||
out.Set(-x, -y, -z, -w);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::operator+(const Quat &quat)
|
|
||||||
{
|
|
||||||
Quat out;
|
|
||||||
out.x = x + quat.x;
|
|
||||||
out.y = y + quat.y;
|
|
||||||
out.z = z + quat.z;
|
|
||||||
out.w = w + quat.w;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator+=(const Quat &quat)
|
|
||||||
{
|
|
||||||
x += quat.x;
|
|
||||||
y += quat.y;
|
|
||||||
z += quat.z;
|
|
||||||
w += quat.w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::operator-(const Quat &quat)
|
|
||||||
{
|
|
||||||
Quat out;
|
|
||||||
out.x = x - quat.x;
|
|
||||||
out.y = y - quat.y;
|
|
||||||
out.z = z - quat.z;
|
|
||||||
out.w = w - quat.w;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator-=(const Quat &quat)
|
|
||||||
{
|
|
||||||
x -= quat.x;
|
|
||||||
y -= quat.y;
|
|
||||||
z -= quat.z;
|
|
||||||
w -= quat.w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::operator*(const Quat &quat)
|
|
||||||
{
|
|
||||||
Quat out;
|
|
||||||
|
|
||||||
out.x = x * quat.w - y * quat.z + quat.x * w + quat.y * z;
|
|
||||||
out.y = x * quat.z + y * quat.w - quat.x * z + w * quat.y;
|
|
||||||
out.z = quat.x * y + w * quat.z + z * quat.w - x * quat.y;
|
|
||||||
out.w = w * quat.w - quat.y * y + z * quat.z + quat.x * x;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator*=(const Quat &quat)
|
|
||||||
{
|
|
||||||
float tx = x;
|
|
||||||
float ty = y;
|
|
||||||
float tz = z;
|
|
||||||
float tw = w;
|
|
||||||
|
|
||||||
x = tx * quat.w - ty * quat.z + quat.x * tw + quat.y * z;
|
|
||||||
y = tx * quat.z + ty * quat.w - quat.x * tz + tw * quat.y;
|
|
||||||
z = quat.x * ty + tw * quat.z + tz * quat.w - tx * quat.y;
|
|
||||||
w = tw * quat.w - quat.y * ty + tz * quat.z + quat.x * x;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::operator*(const float val) const
|
|
||||||
{
|
|
||||||
Quat out;
|
|
||||||
out.x = x * val;
|
|
||||||
out.y = y * val;
|
|
||||||
out.z = z * val;
|
|
||||||
out.w = w * val;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator*=(const float val)
|
|
||||||
{
|
|
||||||
x *= val;
|
|
||||||
y *= val;
|
|
||||||
z *= val;
|
|
||||||
w *= val;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 Quat::operator|(const Vec3 &vector)
|
|
||||||
{
|
|
||||||
float xx = x * x;
|
|
||||||
float yx = y * x;
|
|
||||||
float zx = z * x;
|
|
||||||
float wx = w * x;
|
|
||||||
float yy = y * y;
|
|
||||||
float zy = z * y;
|
|
||||||
float wy = w * y;
|
|
||||||
float zz = z * z;
|
|
||||||
float wz = w * z;
|
|
||||||
float ww = w * w;
|
|
||||||
|
|
||||||
return Vec3(
|
|
||||||
((yx + yx) - (wz + wz)) * vector.y +
|
|
||||||
((wy + wy + zx + zx)) * vector.z +
|
|
||||||
(((ww + xx) - yy) - zz) * vector.x,
|
|
||||||
((yy + (ww - xx)) - zz) * vector.y +
|
|
||||||
((zy + zy) - (wx + wx)) * vector.z +
|
|
||||||
((wz + wz) + (yx + yx)) * vector.x,
|
|
||||||
((wx + wx) + (zy + zy)) * vector.y +
|
|
||||||
(((ww - xx) - yy) + zz) * vector.z +
|
|
||||||
((zx + zx) - (wy + wy)) * vector.x
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Quat::Dot(const Quat &quat) const
|
|
||||||
{
|
|
||||||
return (x * quat.x + y * quat.y + z * quat.z + w * quat.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::Slerp(const Quat &quat, float movement) const
|
|
||||||
{
|
|
||||||
Quat rdest = quat;
|
|
||||||
float d1 = Dot(quat);
|
|
||||||
float d2 = Dot(quat.Inverse());
|
|
||||||
|
|
||||||
if (d1 < d2)
|
|
||||||
{
|
|
||||||
rdest = quat.Inverse();
|
|
||||||
d1 = d2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d1 <= 0.7071067811865001f)
|
|
||||||
{
|
|
||||||
float halfcos = Math::ACos(d1);
|
|
||||||
float halfsin = Math::Sin(halfcos);
|
|
||||||
|
|
||||||
if (halfsin == 0)
|
|
||||||
{
|
|
||||||
Quat out;
|
|
||||||
out.Set(x, y, z, w);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float d;
|
|
||||||
float ms1;
|
|
||||||
float ms2;
|
|
||||||
|
|
||||||
d = 1.0f / halfsin;
|
|
||||||
ms1 = Math::Sin((1.0f - movement) * halfcos) * d;
|
|
||||||
ms2 = Math::Sin(halfcos * movement) * d;
|
|
||||||
|
|
||||||
if (ms2 < 0)
|
|
||||||
{
|
|
||||||
rdest = quat.Inverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this * ms1 + rdest * ms2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Quat out = (rdest - *this) * movement + *this;
|
|
||||||
out.Normalize();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat Quat::RotateFrom(const Vec3 &location, const Vec3 &target, float maxAngle)
|
|
||||||
{
|
|
||||||
Vec3 axis;
|
|
||||||
Vec3 dir;
|
|
||||||
Vec3 cp;
|
|
||||||
Quat prot;
|
|
||||||
float an;
|
|
||||||
|
|
||||||
dir = (*this | Vec3::vecForward);
|
|
||||||
axis = (target - location).Normalize();
|
|
||||||
cp = dir.Cross(axis).Normalize();
|
|
||||||
|
|
||||||
an = Math::ACos(axis.Dot(dir));
|
|
||||||
|
|
||||||
if (maxAngle != 0 && an >= maxAngle)
|
|
||||||
{
|
|
||||||
an = maxAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (*this * Quat(an, cp));
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator=(const Quat &quat)
|
|
||||||
{
|
|
||||||
x = quat.x;
|
|
||||||
y = quat.y;
|
|
||||||
z = quat.z;
|
|
||||||
w = quat.w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator=(const Vec4 &vec)
|
|
||||||
{
|
|
||||||
x = vec.x;
|
|
||||||
y = vec.y;
|
|
||||||
z = vec.z;
|
|
||||||
w = vec.w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quat &Quat::operator=(const float *vecs)
|
|
||||||
{
|
|
||||||
x = vecs[0];
|
|
||||||
y = vecs[1];
|
|
||||||
z = vecs[2];
|
|
||||||
w = vecs[3];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 const &Quat::ToVec3() const
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<const Vec3*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 &Quat::ToVec3()
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<Vec3*>(this);
|
|
||||||
}
|
|
270
src/math/quaternion.h
Normal file
270
src/math/quaternion.h
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vec.h"
|
||||||
|
#include "mat.h"
|
||||||
|
#include <cfloat>
|
||||||
|
|
||||||
|
enum class EulerOrder
|
||||||
|
{
|
||||||
|
xyz,
|
||||||
|
xzy,
|
||||||
|
yzx,
|
||||||
|
yxz,
|
||||||
|
zxy,
|
||||||
|
zyx
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct quaternionT
|
||||||
|
{
|
||||||
|
quaternionT() : x((T)0), y((T)0), z((T)0), w((T)1) { }
|
||||||
|
quaternionT(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) { }
|
||||||
|
quaternionT(const vec4T<T> &v) : x(v.x), y(v.y), z(v.z), w(v.w) { }
|
||||||
|
quaternionT(T angle, const vec3T<T> &axis);
|
||||||
|
|
||||||
|
static quaternionT euler(T x, T y, T z, EulerOrder order = EulerOrder::yxz);
|
||||||
|
static quaternionT euler(const vec3T<T> &xyz, EulerOrder order = EulerOrder::yxz);
|
||||||
|
static quaternionT rotation_matrix(const mat4 &matrix);
|
||||||
|
|
||||||
|
operator vec4T<T>() const { return vec4T<T>(x, y, z, w); }
|
||||||
|
|
||||||
|
T x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Linear Quaternion Interpolation
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> lerp(const quaternionT<T> &quaternion_initial, const quaternionT<T> &quaternion_final, T lerp_time)
|
||||||
|
{
|
||||||
|
quaternionT<T> q(
|
||||||
|
quaternion_initial.x * (((T) 1.0) - lerp_time) + quaternion_final.x * lerp_time,
|
||||||
|
quaternion_initial.y * (((T) 1.0) - lerp_time) + quaternion_final.y * lerp_time,
|
||||||
|
quaternion_initial.z * (((T) 1.0) - lerp_time) + quaternion_final.z * lerp_time,
|
||||||
|
quaternion_initial.w * (((T) 1.0) - lerp_time) + quaternion_final.w * lerp_time
|
||||||
|
);
|
||||||
|
return normalize(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spherical Quaternion Interpolation
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> slerp(const quaternionT<T> &quaternion_initial, const quaternionT<T> &quaternion_final, T slerp_time)
|
||||||
|
{
|
||||||
|
T q2[4];
|
||||||
|
|
||||||
|
q2[0] = quaternion_final.x;
|
||||||
|
q2[1] = quaternion_final.y;
|
||||||
|
q2[2] = quaternion_final.z;
|
||||||
|
q2[3] = quaternion_final.w;
|
||||||
|
|
||||||
|
T cos_theta = quaternion_initial.x * quaternion_final.x
|
||||||
|
+ quaternion_initial.y * quaternion_final.y
|
||||||
|
+ quaternion_initial.z * quaternion_final.z
|
||||||
|
+ quaternion_initial.w * quaternion_final.w;
|
||||||
|
|
||||||
|
if (cos_theta < ((T) 0.0))
|
||||||
|
{
|
||||||
|
q2[0] = -q2[0];
|
||||||
|
q2[1] = -q2[1];
|
||||||
|
q2[2] = -q2[2];
|
||||||
|
q2[3] = -q2[3];
|
||||||
|
cos_theta = -cos_theta;
|
||||||
|
}
|
||||||
|
|
||||||
|
T beta = ((T) 1.0) - slerp_time;
|
||||||
|
|
||||||
|
if (((T) 1.0) - cos_theta > ((T) 0.001))
|
||||||
|
{
|
||||||
|
cos_theta = acos(cos_theta);
|
||||||
|
T sin_theta = 1.0f / sin(cos_theta);
|
||||||
|
beta = sin(cos_theta * beta) * sin_theta;
|
||||||
|
slerp_time = sin(cos_theta * slerp_time) * sin_theta;
|
||||||
|
}
|
||||||
|
|
||||||
|
quaternionT<T> quat;
|
||||||
|
quat.x = beta * quaternion_initial.x + slerp_time * q2[0];
|
||||||
|
quat.y = beta * quaternion_initial.y + slerp_time * q2[1];
|
||||||
|
quat.z = beta * quaternion_initial.z + slerp_time * q2[2];
|
||||||
|
quat.w = beta * quaternion_initial.w + slerp_time * q2[3];
|
||||||
|
return quat;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T magnitude(const quaternionT<T> &q)
|
||||||
|
{
|
||||||
|
return std::sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> normalize(const quaternionT<T> &q)
|
||||||
|
{
|
||||||
|
T m = magnitude(q);
|
||||||
|
if (m != T(0))
|
||||||
|
return quaternionT<T>(q.x / m, q.y / m, q.z / m, q.w / m);
|
||||||
|
else
|
||||||
|
return quaternionT<T>(T(0), T(0), T(0), T(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse this quaternion
|
||||||
|
/// This is the same as the conjugate of a quaternion
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> inverse(const quaternionT<T> &q)
|
||||||
|
{
|
||||||
|
return { -q.x, -q.y, -q.z, q.w };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shortest arc quaternion between two vectors
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> rotation_between(vec3T<T> v0, vec3T<T> v1)
|
||||||
|
{
|
||||||
|
v0 = normalize(v0);
|
||||||
|
v1 = normalize(v1);
|
||||||
|
|
||||||
|
T d = dot(v0, v1);
|
||||||
|
if (d >= 1.0f) // v0 and v1 is the same vector
|
||||||
|
{
|
||||||
|
return quaternionT<T>();
|
||||||
|
}
|
||||||
|
else if (d < T(1e-6 - 1.0)) // v0 and v1 are parallel but pointing in opposite directions
|
||||||
|
{
|
||||||
|
// We can rotate around any axis - find one using the cross product:
|
||||||
|
vec3T<T> axis = cross(vec3T<T>(T(1), T(0), T(0)), v0);
|
||||||
|
if (dot(axis, axis) < T(1e-6)) // colinear
|
||||||
|
axis = cross(vec3T<T>(T(0), T(1), T(0)), v0);
|
||||||
|
axis = normalize(axis);
|
||||||
|
return quaternionT<T>((T)3.14159265359, axis);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T s = std::sqrt((1 + d) * 2);
|
||||||
|
T rcp_s = T(1) / s;
|
||||||
|
vec3T<T> c = cross(v0, v1);
|
||||||
|
quaternionT<T> q(vec4T<T>(c * rcp_s, s * T(0.5)));
|
||||||
|
return normalize(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> quaternionT<T>::euler(T x, T y, T z, EulerOrder order)
|
||||||
|
{
|
||||||
|
quaternionT<T> q_x(x, vec3T<T>((T)1, (T)0, (T)0));
|
||||||
|
quaternionT<T> q_y(y, vec3T<T>((T)0, (T)1, (T)0));
|
||||||
|
quaternionT<T> q_z(z, vec3T<T>((T)0, (T)0, (T)1));
|
||||||
|
|
||||||
|
switch (order)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case EulerOrder::xyz:
|
||||||
|
return q_x * q_y * q_z;
|
||||||
|
case EulerOrder::xzy:
|
||||||
|
return q_x * q_z * q_y;
|
||||||
|
case EulerOrder::yzx:
|
||||||
|
return q_y * q_z * q_x;
|
||||||
|
case EulerOrder::yxz:
|
||||||
|
return q_y * q_x * q_z;
|
||||||
|
case EulerOrder::zxy:
|
||||||
|
return q_z * q_x * q_y;
|
||||||
|
case EulerOrder::zyx:
|
||||||
|
return q_z * q_y * q_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> quaternionT<T>::euler(const vec3T<T> &angles, EulerOrder order)
|
||||||
|
{
|
||||||
|
return euler(angles.x, angles.y, angles.z, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T>::quaternionT(T angle, const vec3T<T> &axis)
|
||||||
|
{
|
||||||
|
T len = length(axis);
|
||||||
|
T half_angle_radians = angle / T(2);
|
||||||
|
quaternionT<T> q;
|
||||||
|
q.w = std::cos(half_angle_radians);
|
||||||
|
q.x = axis.x * std::sin(half_angle_radians) / len;
|
||||||
|
q.y = axis.y * std::sin(half_angle_radians) / len;
|
||||||
|
q.z = axis.z * std::sin(half_angle_radians) / len;
|
||||||
|
*this = normalize(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> quaternionT<T>::rotation_matrix(const mat4 &m)
|
||||||
|
{
|
||||||
|
float x, y, z, w;
|
||||||
|
float size;
|
||||||
|
|
||||||
|
// We assume that this is a pure rotation matrix without any scale or translation
|
||||||
|
float trace = m.matrix[0 * 4 + 0] + m.matrix[1 * 4 + 1] + m.matrix[2 * 4 + 2] + (float)1;
|
||||||
|
if (trace > (float) 16.0*FLT_EPSILON)
|
||||||
|
{
|
||||||
|
size = sqrt(trace) * (float)2;
|
||||||
|
x = (m.matrix[1 * 4 + 2] - m.matrix[2 * 4 + 1]) / size;
|
||||||
|
y = (m.matrix[2 * 4 + 0] - m.matrix[0 * 4 + 2]) / size;
|
||||||
|
z = (m.matrix[0 * 4 + 1] - m.matrix[1 * 4 + 0]) / size;
|
||||||
|
w = (float) 0.25 * size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the trace of the matrix is equal to zero then identify which major diagonal element has the greatest value.
|
||||||
|
|
||||||
|
if (m.matrix[0 * 4 + 0] > m.matrix[1 * 4 + 1] && m.matrix[0 * 4 + 0] > m.matrix[2 * 4 + 2])
|
||||||
|
{
|
||||||
|
// Column 0:
|
||||||
|
size = sqrt((float) 1.0 + m.matrix[0 * 4 + 0] - m.matrix[1 * 4 + 1] - m.matrix[2 * 4 + 2]) * (float)2;
|
||||||
|
x = (float) 0.25 * size;
|
||||||
|
y = (m.matrix[0 * 4 + 1] + m.matrix[1 * 4 + 0]) / size;
|
||||||
|
z = (m.matrix[2 * 4 + 0] + m.matrix[0 * 4 + 2]) / size;
|
||||||
|
w = (m.matrix[1 * 4 + 2] - m.matrix[2 * 4 + 1]) / size;
|
||||||
|
}
|
||||||
|
else if (m.matrix[1 * 4 + 1] > m.matrix[2 * 4 + 2])
|
||||||
|
{
|
||||||
|
// Column 1:
|
||||||
|
size = sqrt((float) 1.0 + m.matrix[1 * 4 + 1] - m.matrix[0 * 4 + 0] - m.matrix[2 * 4 + 2]) * (float)2;
|
||||||
|
x = (m.matrix[0 * 4 + 1] + m.matrix[1 * 4 + 0]) / size;
|
||||||
|
y = (float) 0.25 * size;
|
||||||
|
z = (m.matrix[1 * 4 + 2] + m.matrix[2 * 4 + 1]) / size;
|
||||||
|
w = (m.matrix[2 * 4 + 0] - m.matrix[0 * 4 + 2]) / size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Column 2:
|
||||||
|
size = sqrt((float) 1.0 + m.matrix[2 * 4 + 2] - m.matrix[0 * 4 + 0] - m.matrix[1 * 4 + 1]) * (float)2;
|
||||||
|
x = (m.matrix[2 * 4 + 0] + m.matrix[0 * 4 + 2]) / size;
|
||||||
|
y = (m.matrix[1 * 4 + 2] + m.matrix[2 * 4 + 1]) / size;
|
||||||
|
z = (float) 0.25 * size;
|
||||||
|
w = (m.matrix[0 * 4 + 1] - m.matrix[1 * 4 + 0]) / size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { x, y, z, w };
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> operator*(const quaternionT<T> &quaternion_1, const quaternionT<T> &quaternion_2)
|
||||||
|
{
|
||||||
|
quaternionT<T> quaternion_dest;
|
||||||
|
quaternion_dest.x = quaternion_1.w*quaternion_2.x + quaternion_1.x*quaternion_2.w + quaternion_1.y*quaternion_2.z - quaternion_1.z*quaternion_2.y;
|
||||||
|
quaternion_dest.y = quaternion_1.w*quaternion_2.y + quaternion_1.y*quaternion_2.w + quaternion_1.z*quaternion_2.x - quaternion_1.x*quaternion_2.z;
|
||||||
|
quaternion_dest.z = quaternion_1.w*quaternion_2.z + quaternion_1.z*quaternion_2.w + quaternion_1.x*quaternion_2.y - quaternion_1.y*quaternion_2.x;
|
||||||
|
quaternion_dest.w = quaternion_1.w*quaternion_2.w - quaternion_1.x*quaternion_2.x - quaternion_1.y*quaternion_2.y - quaternion_1.z*quaternion_2.z;
|
||||||
|
return quaternion_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
vec3T<T> operator*(const quaternionT<T> &q, const vec3T<T> &v)
|
||||||
|
{
|
||||||
|
vec3T<T> q3(q.x, q.y, q.z);
|
||||||
|
return v + cross(q3, cross(q3, v) + v * q.w) * ((T) 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
quaternionT<T> operator*(const quaternionT<T> &q, const mat4 &m)
|
||||||
|
{
|
||||||
|
quaternionT<T> result;
|
||||||
|
result.x = m.matrix[(4 * 0) + 0] * q.x + m.matrix[(4 * 0) + 1] * q.y + m.matrix[(4 * 0) + 2] * q.z + m.matrix[(4 * 0) + 3] * q.w;
|
||||||
|
result.y = m.matrix[(4 * 1) + 0] * q.x + m.matrix[(4 * 1) + 1] * q.y + m.matrix[(4 * 1) + 2] * q.z + m.matrix[(4 * 1) + 3] * q.w;
|
||||||
|
result.z = m.matrix[(4 * 2) + 0] * q.x + m.matrix[(4 * 2) + 1] * q.y + m.matrix[(4 * 2) + 2] * q.z + m.matrix[(4 * 2) + 3] * q.w;
|
||||||
|
result.w = m.matrix[(4 * 3) + 0] * q.x + m.matrix[(4 * 3) + 1] * q.y + m.matrix[(4 * 3) + 2] * q.z + m.matrix[(4 * 3) + 3] * q.w;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef quaternionT<float> quaternion;
|
||||||
|
typedef quaternionT<double> dquaternion;
|
398
src/math/vec.h
Normal file
398
src/math/vec.h
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
|
class Pointf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Pointf() = default;
|
||||||
|
Pointf(float x, float y) : x(x), y(y) { }
|
||||||
|
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sizef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sizef() = default;
|
||||||
|
Sizef(float w, float h) : width(w), height(h) { }
|
||||||
|
|
||||||
|
float width = 0.0f;
|
||||||
|
float height = 0.0f;
|
||||||
|
|
||||||
|
inline Sizef &operator+=(Sizef b) { width += b.width; height += b.height; return *this; }
|
||||||
|
inline Sizef &operator-=(Sizef b) { width -= b.width; height -= b.height; return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Sizef operator+(Sizef a, Sizef b) { return { a.width + b.width, a.height + b.height }; }
|
||||||
|
inline Sizef operator-(Sizef a, Sizef b) { return { a.width - b.width, a.height - b.height }; }
|
||||||
|
|
||||||
|
class Rectf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Rectf() = default;
|
||||||
|
Rectf(float left, float top, float right, float bottom) : left(left), top(top), right(right), bottom(bottom) { }
|
||||||
|
Rectf(Pointf pos, Sizef size) : left(pos.x), top(pos.y), right(pos.x + size.width), bottom(pos.y + size.height) { }
|
||||||
|
|
||||||
|
static Rectf xywh(float x, float y, float width, float height) { return Rectf(x, y, x + width, y + height); }
|
||||||
|
|
||||||
|
Pointf position() const { return { left, top }; }
|
||||||
|
Sizef size() const { return { right - left, bottom - top }; }
|
||||||
|
|
||||||
|
Rectf &boundingRect(const Rectf &rect)
|
||||||
|
{
|
||||||
|
Rectf result;
|
||||||
|
result.left = std::min(left, rect.left);
|
||||||
|
result.right = std::max(right, rect.right);
|
||||||
|
result.top = std::min(top, rect.top);
|
||||||
|
result.bottom = std::max(bottom, rect.bottom);
|
||||||
|
*this = result;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const Pointf &p) const
|
||||||
|
{
|
||||||
|
return (p.x >= left && p.x < right) && (p.y >= top && p.y < bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
float left = 0.0f;
|
||||||
|
float top = 0.0f;
|
||||||
|
float right = 0.0f;
|
||||||
|
float bottom = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct vec2T
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { T x, y; };
|
||||||
|
struct { T r, g; };
|
||||||
|
struct { T s, t; };
|
||||||
|
struct { T v[2]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2T() = default;
|
||||||
|
vec2T(T v) : x(v), y(v) { }
|
||||||
|
vec2T(T x, T y) : x(x), y(y) { }
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit vec2T(const vec2T<U> &v2) : x(static_cast<T>(v2.x)), y(static_cast<T>(v2.y)) { }
|
||||||
|
|
||||||
|
vec2T<T> yx() const { return vec2T<T>(y, x); }
|
||||||
|
vec2T<T> gr() const { return vec2T<T>(g, r); }
|
||||||
|
vec2T<T> ts() const { return vec2T<T>(t, s); }
|
||||||
|
|
||||||
|
vec2T<T> swizzle(int a, int b) const { return vec2T<T>(v[a], v[b]); }
|
||||||
|
|
||||||
|
inline vec2T operator-() const { return vec2T(-x, -y); }
|
||||||
|
|
||||||
|
inline vec2T &operator+=(vec2T b) { x += b.x; y += b.y; return *this; }
|
||||||
|
inline vec2T &operator-=(vec2T b) { x -= b.x; y -= b.y; return *this; }
|
||||||
|
inline vec2T &operator*=(vec2T b) { x *= b.x; y *= b.y; return *this; }
|
||||||
|
inline vec2T &operator/=(vec2T b) { x /= b.x; y /= b.y; return *this; }
|
||||||
|
|
||||||
|
inline vec2T &operator+=(T b) { x += b; y += b; return *this; }
|
||||||
|
inline vec2T &operator-=(T b) { x -= b; y -= b; return *this; }
|
||||||
|
inline vec2T &operator*=(T b) { x *= b; y *= b; return *this; }
|
||||||
|
inline vec2T &operator/=(T b) { x /= b; y /= b; return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct vec3T
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { T x, y, z; };
|
||||||
|
struct { T r, g, b; };
|
||||||
|
struct { T s, t, p; };
|
||||||
|
struct { T v[3]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3T() = default;
|
||||||
|
vec3T(T v) : x(v), y(v), z(v) { }
|
||||||
|
vec3T(const vec2T<T> &v2, T z) : x(v2.x), y(v2.y), z(z) { }
|
||||||
|
vec3T(T x, T y, T z) : x(x), y(y), z(z) { }
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit vec3T(const vec3T<U> &v3) : x(static_cast<T>(v3.x)), y(static_cast<T>(v3.y)), z(static_cast<T>(v3.z)) { }
|
||||||
|
|
||||||
|
vec2T<T> xy() const { return vec2T<T>(x, y); }
|
||||||
|
vec2T<T> rg() const { return vec2T<T>(r, g); }
|
||||||
|
vec2T<T> st() const { return vec2T<T>(s, t); }
|
||||||
|
|
||||||
|
vec2T<T> yx() const { return vec2T<T>(y, x); }
|
||||||
|
vec2T<T> gr() const { return vec2T<T>(g, r); }
|
||||||
|
vec2T<T> ts() const { return vec2T<T>(t, s); }
|
||||||
|
|
||||||
|
vec3T<T> zyx() const { return vec3T<T>(z, y, x); }
|
||||||
|
vec3T<T> bgr() const { return vec3T<T>(b, g, r); }
|
||||||
|
vec3T<T> pts() const { return vec3T<T>(p, t, s); }
|
||||||
|
|
||||||
|
vec2T<T> swizzle(int a, int b) const { return vec2T<T>(v[a], v[b]); }
|
||||||
|
vec3T<T> swizzle(int a, int b, int c) const { return vec3T<T>(v[a], v[b], v[c]); }
|
||||||
|
|
||||||
|
T &operator[](int i) { return v[i]; }
|
||||||
|
const T &operator[](int i) const { return v[i]; }
|
||||||
|
|
||||||
|
inline vec3T operator-() const { return vec3T(-x, -y, -z); }
|
||||||
|
|
||||||
|
inline vec3T &operator+=(vec3T b) { x += b.x; y += b.y; z += b.z; return *this; }
|
||||||
|
inline vec3T &operator-=(vec3T b) { x -= b.x; y -= b.y; z -= b.z; return *this; }
|
||||||
|
inline vec3T &operator*=(vec3T b) { x *= b.x; y *= b.y; z *= b.z; return *this; }
|
||||||
|
inline vec3T &operator/=(vec3T b) { x /= b.x; y /= b.y; z /= b.z; return *this; }
|
||||||
|
|
||||||
|
inline vec3T &operator+=(T b) { x += b; y += b; z += b; return *this; }
|
||||||
|
inline vec3T &operator-=(T b) { x -= b; y -= b; z -= b; return *this; }
|
||||||
|
inline vec3T &operator*=(T b) { x *= b; y *= b; z *= b; return *this; }
|
||||||
|
inline vec3T &operator/=(T b) { x /= b; y /= b; z /= b; return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct vec4T
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { T x, y, z, w; };
|
||||||
|
struct { T r, g, b, a; };
|
||||||
|
struct { T s, t, p, q; };
|
||||||
|
struct { T v[4]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
vec4T() = default;
|
||||||
|
vec4T(T v) : x(v), y(v), z(v), w(v) { }
|
||||||
|
vec4T(const vec2T<T> &a, const vec2T<T> &b) : x(a.x), y(a.y), z(b.x), w(b.y) { }
|
||||||
|
vec4T(const vec3T<T> &v3, T w) : x(v3.x), y(v3.y), z(v3.z), w(w) { }
|
||||||
|
vec4T(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) { }
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit vec4T(const vec4T<U> &v4) : x(static_cast<T>(v4.x)), y(static_cast<T>(v4.y)), z(static_cast<T>(v4.z)), w(static_cast<T>(v4.w)) { }
|
||||||
|
|
||||||
|
vec2T<T> xy() const { return vec2T<T>(x, y); }
|
||||||
|
vec2T<T> rg() const { return vec2T<T>(r, g); }
|
||||||
|
vec2T<T> st() const { return vec2T<T>(s, t); }
|
||||||
|
|
||||||
|
vec2T<T> yx() const { return vec2T<T>(y, x); }
|
||||||
|
vec2T<T> gr() const { return vec2T<T>(g, r); }
|
||||||
|
vec2T<T> ts() const { return vec2T<T>(t, s); }
|
||||||
|
|
||||||
|
vec3T<T> xyz() const { return vec3T<T>(x, y, z); }
|
||||||
|
vec3T<T> rgb() const { return vec3T<T>(r, g, b); }
|
||||||
|
vec3T<T> stp() const { return vec3T<T>(s, t, p); }
|
||||||
|
|
||||||
|
vec3T<T> zyx() const { return vec3T<T>(z, y, x); }
|
||||||
|
vec3T<T> bgr() const { return vec3T<T>(b, g, r); }
|
||||||
|
vec3T<T> pts() const { return vec3T<T>(p, t, s); }
|
||||||
|
|
||||||
|
vec4T<T> wzyx() const { return vec4T<T>(w, z, y, x); }
|
||||||
|
vec4T<T> abgr() const { return vec4T<T>(a, b, g, r); }
|
||||||
|
vec4T<T> qpts() const { return vec4T<T>(q, p, t, s); }
|
||||||
|
|
||||||
|
vec4T<T> bgra() const { return vec4T<T>(b, g, r, a); }
|
||||||
|
|
||||||
|
vec2T<T> swizzle(int a, int b) const { return vec2T<T>(v[a], v[b]); }
|
||||||
|
vec3T<T> swizzle(int a, int b, int c) const { return vec3T<T>(v[a], v[b], v[c]); }
|
||||||
|
vec4T<T> swizzle(int a, int b, int c, int d) const { return vec4T<T>(v[a], v[b], v[c], v[d]); }
|
||||||
|
|
||||||
|
inline vec4T operator-() const { return vec4T(-x, -y, -z, -w); }
|
||||||
|
|
||||||
|
inline vec4T &operator+=(vec4T b) { x += b.x; y += b.y; z += b.z; w += b.w; return *this; }
|
||||||
|
inline vec4T &operator-=(vec4T b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; }
|
||||||
|
inline vec4T &operator*=(vec4T b) { x *= b.x; y *= b.y; z *= b.z; w *= b.w; return *this; }
|
||||||
|
inline vec4T &operator/=(vec4T b) { x /= b.x; y /= b.y; z /= b.z; w /= b.w; return *this; }
|
||||||
|
|
||||||
|
inline vec4T &operator+=(T b) { x += b; y += b; z += b; w += b; return *this; }
|
||||||
|
inline vec4T &operator-=(T b) { x -= b; y -= b; z -= b; w -= b; return *this; }
|
||||||
|
inline vec4T &operator*=(T b) { x *= b; y *= b; z *= b; w *= b; return *this; }
|
||||||
|
inline vec4T &operator/=(T b) { x /= b; y /= b; z /= b; w /= b; return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> vec2T<T> operator+(vec2T<T> a, vec2T<T> b) { return vec2T<T>(a.x + b.x, a.y + b.y); }
|
||||||
|
template<typename T> vec2T<T> operator-(vec2T<T> a, vec2T<T> b) { return vec2T<T>(a.x - b.x, a.y - b.y); }
|
||||||
|
template<typename T> vec2T<T> operator*(vec2T<T> a, vec2T<T> b) { return vec2T<T>(a.x * b.x, a.y * b.y); }
|
||||||
|
template<typename T> vec2T<T> operator/(vec2T<T> a, vec2T<T> b) { return vec2T<T>(a.x / b.x, a.y / b.y); }
|
||||||
|
|
||||||
|
template<typename T> vec2T<T> operator+(T a, vec2T<T> b) { return vec2T<T>(a + b.x, a + b.y); }
|
||||||
|
template<typename T> vec2T<T> operator-(T a, vec2T<T> b) { return vec2T<T>(a - b.x, a - b.y); }
|
||||||
|
template<typename T> vec2T<T> operator*(T a, vec2T<T> b) { return vec2T<T>(a * b.x, a * b.y); }
|
||||||
|
template<typename T> vec2T<T> operator/(T a, vec2T<T> b) { return vec2T<T>(a / b.x, a / b.y); }
|
||||||
|
|
||||||
|
template<typename T> vec2T<T> operator+(vec2T<T> a, T b) { return vec2T<T>(a.x + b, a.y + b); }
|
||||||
|
template<typename T> vec2T<T> operator-(vec2T<T> a, T b) { return vec2T<T>(a.x - b, a.y - b); }
|
||||||
|
template<typename T> vec2T<T> operator*(vec2T<T> a, T b) { return vec2T<T>(a.x * b, a.y * b); }
|
||||||
|
template<typename T> vec2T<T> operator/(vec2T<T> a, T b) { return vec2T<T>(a.x / b, a.y / b); }
|
||||||
|
|
||||||
|
template<typename T> vec3T<T> operator+(vec3T<T> a, vec3T<T> b) { return vec3T<T>(a.x + b.x, a.y + b.y, a.z + b.z); }
|
||||||
|
template<typename T> vec3T<T> operator-(vec3T<T> a, vec3T<T> b) { return vec3T<T>(a.x - b.x, a.y - b.y, a.z - b.z); }
|
||||||
|
template<typename T> vec3T<T> operator*(vec3T<T> a, vec3T<T> b) { return vec3T<T>(a.x * b.x, a.y * b.y, a.z * b.z); }
|
||||||
|
template<typename T> vec3T<T> operator/(vec3T<T> a, vec3T<T> b) { return vec3T<T>(a.x / b.x, a.y / b.y, a.z / b.z); }
|
||||||
|
|
||||||
|
template<typename T> vec3T<T> operator+(T a, vec3T<T> b) { return vec3T<T>(a + b.x, a + b.y, a + b.z); }
|
||||||
|
template<typename T> vec3T<T> operator-(T a, vec3T<T> b) { return vec3T<T>(a - b.x, a - b.y, a - b.z); }
|
||||||
|
template<typename T> vec3T<T> operator*(T a, vec3T<T> b) { return vec3T<T>(a * b.x, a * b.y, a * b.z); }
|
||||||
|
template<typename T> vec3T<T> operator/(T a, vec3T<T> b) { return vec3T<T>(a / b.x, a / b.y, a / b.z); }
|
||||||
|
|
||||||
|
template<typename T> vec3T<T> operator+(vec3T<T> a, T b) { return vec3T<T>(a.x + b, a.y + b, a.z + b); }
|
||||||
|
template<typename T> vec3T<T> operator-(vec3T<T> a, T b) { return vec3T<T>(a.x - b, a.y - b, a.z - b); }
|
||||||
|
template<typename T> vec3T<T> operator*(vec3T<T> a, T b) { return vec3T<T>(a.x * b, a.y * b, a.z * b); }
|
||||||
|
template<typename T> vec3T<T> operator/(vec3T<T> a, T b) { return vec3T<T>(a.x / b, a.y / b, a.z / b); }
|
||||||
|
|
||||||
|
template<typename T> vec4T<T> operator+(vec4T<T> a, vec4T<T> b) { return vec4T<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); }
|
||||||
|
template<typename T> vec4T<T> operator-(vec4T<T> a, vec4T<T> b) { return vec4T<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); }
|
||||||
|
template<typename T> vec4T<T> operator*(vec4T<T> a, vec4T<T> b) { return vec4T<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); }
|
||||||
|
template<typename T> vec4T<T> operator/(vec4T<T> a, vec4T<T> b) { return vec4T<T>(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); }
|
||||||
|
|
||||||
|
template<typename T> vec4T<T> operator+(T a, vec4T<T> b) { return vec4T<T>(a + b.x, a + b.y, a + b.z, a + b.w); }
|
||||||
|
template<typename T> vec4T<T> operator-(T a, vec4T<T> b) { return vec4T<T>(a - b.x, a - b.y, a - b.z, a - b.w); }
|
||||||
|
template<typename T> vec4T<T> operator*(T a, vec4T<T> b) { return vec4T<T>(a * b.x, a * b.y, a * b.z, a * b.w); }
|
||||||
|
template<typename T> vec4T<T> operator/(T a, vec4T<T> b) { return vec4T<T>(a / b.x, a / b.y, a / b.z, a / b.w); }
|
||||||
|
|
||||||
|
template<typename T> vec4T<T> operator+(vec4T<T> a, T b) { return vec4T<T>(a.x + b, a.y + b, a.z + b, a.w + b); }
|
||||||
|
template<typename T> vec4T<T> operator-(vec4T<T> a, T b) { return vec4T<T>(a.x - b, a.y - b, a.z - b, a.w - b); }
|
||||||
|
template<typename T> vec4T<T> operator*(vec4T<T> a, T b) { return vec4T<T>(a.x * b, a.y * b, a.z * b, a.w * b); }
|
||||||
|
template<typename T> vec4T<T> operator/(vec4T<T> a, T b) { return vec4T<T>(a.x / b, a.y / b, a.z / b, a.w / b); }
|
||||||
|
|
||||||
|
template<typename T> bool operator==(const vec2T<T> &a, const vec2T<T> &b) { return a.x == b.x && a.y == b.y; }
|
||||||
|
template<typename T> bool operator==(const vec3T<T> &a, const vec3T<T> &b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
|
||||||
|
template<typename T> bool operator==(const vec4T<T> &a, const vec4T<T> &b) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
|
||||||
|
|
||||||
|
template<typename T> bool operator!=(const vec2T<T> &a, const vec2T<T> &b) { return a.x != b.x || a.y != b.y; }
|
||||||
|
template<typename T> bool operator!=(const vec3T<T> &a, const vec3T<T> &b) { return a.x != b.x || a.y != b.y || a.z != b.z; }
|
||||||
|
template<typename T> bool operator!=(const vec4T<T> &a, const vec4T<T> &b) { return a.x != b.x || a.y != b.y || a.z != b.z || a.w == b.w; }
|
||||||
|
|
||||||
|
typedef vec2T<float> vec2;
|
||||||
|
typedef vec3T<float> vec3;
|
||||||
|
typedef vec4T<float> vec4;
|
||||||
|
typedef vec2T<double> dvec2;
|
||||||
|
typedef vec3T<double> dvec3;
|
||||||
|
typedef vec4T<double> dvec4;
|
||||||
|
typedef vec2T<int32_t> ivec2;
|
||||||
|
typedef vec3T<int32_t> ivec3;
|
||||||
|
typedef vec4T<int32_t> ivec4;
|
||||||
|
typedef vec2T<uint32_t> uvec2;
|
||||||
|
typedef vec3T<uint32_t> uvec3;
|
||||||
|
typedef vec4T<uint32_t> uvec4;
|
||||||
|
typedef vec2T<bool> bvec2;
|
||||||
|
typedef vec3T<bool> bvec3;
|
||||||
|
typedef vec4T<bool> bvec4;
|
||||||
|
typedef vec2T<int16_t> ivec2s;
|
||||||
|
typedef vec3T<int16_t> ivec3s;
|
||||||
|
typedef vec4T<int16_t> ivec4s;
|
||||||
|
typedef vec2T<uint16_t> uvec2s;
|
||||||
|
typedef vec3T<uint16_t> uvec3s;
|
||||||
|
typedef vec4T<uint16_t> uvec4s;
|
||||||
|
typedef vec2T<int8_t> ivec2b;
|
||||||
|
typedef vec3T<int8_t> ivec3b;
|
||||||
|
typedef vec4T<int8_t> ivec4b;
|
||||||
|
typedef vec2T<uint8_t> uvec2b;
|
||||||
|
typedef vec3T<uint8_t> uvec3b;
|
||||||
|
typedef vec4T<uint8_t> uvec4b;
|
||||||
|
|
||||||
|
inline float dot(vec2 a, vec2 b) { return a.x * b.x + a.y * b.y; }
|
||||||
|
inline float dot(vec3 a, vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||||
|
inline float dot(vec4 a, vec4 b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; }
|
||||||
|
|
||||||
|
inline double dot(dvec2 a, dvec2 b) { return a.x * b.x + a.y * b.y; }
|
||||||
|
inline double dot(dvec3 a, dvec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||||
|
inline double dot(dvec4 a, dvec4 b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; }
|
||||||
|
|
||||||
|
inline float radians(short deg) { return deg * (3.14159265359f / 180.0f); }
|
||||||
|
inline float degrees(short rad) { return rad * (180.0f / 3.14159265359f); }
|
||||||
|
|
||||||
|
inline float radians(int deg) { return deg * (3.14159265359f / 180.0f); }
|
||||||
|
inline float degrees(int rad) { return rad * (180.0f / 3.14159265359f); }
|
||||||
|
|
||||||
|
inline float radians(float deg) { return deg * (3.14159265359f / 180.0f); }
|
||||||
|
inline float degrees(float rad) { return rad * (180.0f / 3.14159265359f); }
|
||||||
|
|
||||||
|
inline double radians(double deg) { return deg * (3.14159265359 / 180.0); }
|
||||||
|
inline double degrees(double rad) { return rad * (180.0 / 3.14159265359); }
|
||||||
|
|
||||||
|
inline float length(vec2 v) { return std::sqrt(dot(v, v)); }
|
||||||
|
inline float length(vec3 v) { return std::sqrt(dot(v, v)); }
|
||||||
|
inline float length(vec4 v) { return std::sqrt(dot(v, v)); }
|
||||||
|
|
||||||
|
inline double length(dvec2 v) { return std::sqrt(dot(v, v)); }
|
||||||
|
inline double length(dvec3 v) { return std::sqrt(dot(v, v)); }
|
||||||
|
inline double length(dvec4 v) { return std::sqrt(dot(v, v)); }
|
||||||
|
|
||||||
|
inline vec2 normalize(vec2 v) { return v / length(v); }
|
||||||
|
inline vec3 normalize(vec3 v) { return v / length(v); }
|
||||||
|
inline vec4 normalize(vec4 v) { return v / length(v); }
|
||||||
|
|
||||||
|
inline dvec2 normalize(dvec2 v) { return v / length(v); }
|
||||||
|
inline dvec3 normalize(dvec3 v) { return v / length(v); }
|
||||||
|
inline dvec4 normalize(dvec4 v) { return v / length(v); }
|
||||||
|
|
||||||
|
inline vec3 cross(vec3 a, vec3 b) { return { a.y * b.z - b.y * a.z, a.z * b.x - b.z * a.x, a.x * b.y - b.x * a.y }; }
|
||||||
|
inline dvec3 cross(dvec3 a, dvec3 b) { return { a.y * b.z - b.y * a.z, a.z * b.x - b.z * a.x, a.x * b.y - b.x * a.y }; }
|
||||||
|
|
||||||
|
inline vec3 reflect(vec3 I, vec3 N) { return I - 2.0f * dot(N, I) * N; }
|
||||||
|
inline dvec3 reflect(dvec3 I, dvec3 N) { return I - 2.0 * dot(N, I) * N; }
|
||||||
|
|
||||||
|
inline vec3 refract(vec3 I, vec3 N, float eta) { float NdotI = dot(N, I); float k = 1.0f - eta * eta * (1.0f - NdotI * NdotI); return k < 0.0f ? vec3(0.0f) : I * eta - (eta * NdotI + std::sqrt(k)) * N; }
|
||||||
|
inline dvec3 refract(dvec3 I, dvec3 N, double eta) { double NdotI = dot(N, I); double k = 1.0 - eta * eta * (1.0 - NdotI * NdotI); return k < 0.0 ? dvec3(0.0) : I * eta - (eta * NdotI + std::sqrt(k)) * N; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T mix(T a, T b, float t) { return a * (1.0f - t) + b * t; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T mix(T a, T b, double t) { return a * (1.0 - t) + b * t; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T clamp(T val, T minval, T maxval) { return std::max<T>(std::min<T>(val, maxval), minval); }
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T smoothstep(const T edge0, const T edge1, const T x)
|
||||||
|
{
|
||||||
|
auto t = clamp<T>((x - edge0) / (edge1 - edge0), T(0.0), T(1.0));
|
||||||
|
return t * t * (T(3.0) - T(2.0) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float slerp(float t)
|
||||||
|
{
|
||||||
|
float s = t * t;
|
||||||
|
return s * s * (1.0f / 16.0f) - s * 0.5f + 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double slerp(double t)
|
||||||
|
{
|
||||||
|
double s = t * t;
|
||||||
|
return s * s * (1.0 / 16.0) - s * 0.5 + 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T spline(T a, T b, T c, T d, float t)
|
||||||
|
{
|
||||||
|
float w0 = slerp(t + 1.0f);
|
||||||
|
float w1 = slerp(t);
|
||||||
|
float w2 = slerp(t - 1.0f);
|
||||||
|
float w3 = slerp(t - 2.0f);
|
||||||
|
float invweight = 1.0f / (w0 + w1 + w2 + w3);
|
||||||
|
return (a * w0 + b * w1 + c * w2 + d * w3) * invweight;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T spline(T a, T b, T c, T d, double t)
|
||||||
|
{
|
||||||
|
double w0 = slerp(t + 1.0);
|
||||||
|
double w1 = slerp(t);
|
||||||
|
double w2 = slerp(t - 1.0);
|
||||||
|
double w3 = slerp(t - 2.0);
|
||||||
|
double invweight = 1.0 / (w0 + w1 + w2 + w3);
|
||||||
|
return (a * w0 + b * w1 + c * w2 + d * w3) * invweight;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline dvec2 to_dvec2(vec2 v) { return dvec2(v.x, v.y); }
|
||||||
|
inline dvec3 to_dvec3(vec3 v) { return dvec3(v.x, v.y, v.z); }
|
||||||
|
inline dvec4 to_dvec4(vec4 v) { return dvec4(v.x, v.y, v.z, v.w); }
|
||||||
|
|
||||||
|
inline vec2 to_vec2(dvec2 v) { return vec2((float)v.x, (float)v.y); }
|
||||||
|
inline vec3 to_vec3(dvec3 v) { return vec3((float)v.x, (float)v.y, (float)v.z); }
|
||||||
|
inline vec4 to_vec4(dvec4 v) { return vec4((float)v.x, (float)v.y, (float)v.z, (float)v.w); }
|
|
@ -1,38 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Note: this is a modified version of dlight. It is not the original software.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
|
||||||
// svkaiser@gmail.com
|
|
||||||
//
|
|
||||||
// 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 <math.h>
|
|
||||||
#include "mathlib.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
const Vec3 Vec3::vecRight(1, 0, 0);
|
|
||||||
const Vec3 Vec3::vecUp(0, 0, 1);
|
|
||||||
const Vec3 Vec3::vecForward(0, 1, 0);
|
|
||||||
|
|
||||||
const Vec2 Vec2::vecRight(1, 0);
|
|
||||||
const Vec2 Vec2::vecUp(0, 1);
|
|
||||||
Vec2 Vec2::vecZero(0, 0);
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "framework/tarray.h"
|
#include "framework/tarray.h"
|
||||||
#include "framework/templates.h"
|
#include "framework/templates.h"
|
||||||
#include "framework/zstring.h"
|
#include "framework/zstring.h"
|
||||||
|
#include "math/mathlib.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -73,9 +73,9 @@ private:
|
||||||
OBJSurface(FTextureID skin): numTris(0), numFaces(0), vbStart(0), faceStart(0), tris(nullptr), skin(skin) {}
|
OBJSurface(FTextureID skin): numTris(0), numFaces(0), vbStart(0), faceStart(0), tris(nullptr), skin(skin) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
TArray<Vec3> verts;
|
TArray<vec3> verts;
|
||||||
TArray<Vec3> norms;
|
TArray<vec3> norms;
|
||||||
TArray<Vec2> uvs;
|
TArray<vec2> uvs;
|
||||||
TArray<OBJFace> faces;
|
TArray<OBJFace> faces;
|
||||||
TArray<OBJSurface> surfaces;
|
TArray<OBJSurface> surfaces;
|
||||||
FScanner sc;
|
FScanner sc;
|
||||||
|
@ -87,11 +87,11 @@ private:
|
||||||
void ConstructSurfaceTris(OBJSurface &surf);
|
void ConstructSurfaceTris(OBJSurface &surf);
|
||||||
void AddVertFaces();
|
void AddVertFaces();
|
||||||
void TriangulateQuad(const OBJFace &quad, OBJFace *tris);
|
void TriangulateQuad(const OBJFace &quad, OBJFace *tris);
|
||||||
Vec3 RealignVector(Vec3 vecToRealign);
|
vec3 RealignVector(vec3 vecToRealign);
|
||||||
Vec2 FixUV(Vec2 vecToRealign);
|
vec2 FixUV(vec2 vecToRealign);
|
||||||
Vec3 CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx);
|
vec3 CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx);
|
||||||
Vec3 CalculateNormalFlat(OBJTriRef otr);
|
vec3 CalculateNormalFlat(OBJTriRef otr);
|
||||||
Vec3 CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup);
|
vec3 CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup);
|
||||||
public:
|
public:
|
||||||
FOBJModel(): hasMissingNormals(false), hasSmoothGroups(false), vertFaces(nullptr) {}
|
FOBJModel(): hasMissingNormals(false), hasSmoothGroups(false), vertFaces(nullptr) {}
|
||||||
~FOBJModel();
|
~FOBJModel();
|
||||||
|
|
|
@ -85,15 +85,15 @@ private:
|
||||||
// converted data structures
|
// converted data structures
|
||||||
struct UE1Vertex
|
struct UE1Vertex
|
||||||
{
|
{
|
||||||
Vec3 Pos, Normal;
|
vec3 Pos, Normal;
|
||||||
TArray<int> P; // polys that reference this vertex, used in normal computation to save time
|
TArray<int> P; // polys that reference this vertex, used in normal computation to save time
|
||||||
int nP; // count of those polys
|
int nP; // count of those polys
|
||||||
};
|
};
|
||||||
struct UE1Poly
|
struct UE1Poly
|
||||||
{
|
{
|
||||||
int V[3];
|
int V[3];
|
||||||
Vec2 C[3];
|
vec2 C[3];
|
||||||
TArray<Vec3> Normals;
|
TArray<vec3> Normals;
|
||||||
};
|
};
|
||||||
struct UE1Group
|
struct UE1Group
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,15 +111,15 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
|
||||||
{
|
{
|
||||||
if (sc.Compare("v")) // Vertex
|
if (sc.Compare("v")) // Vertex
|
||||||
{
|
{
|
||||||
ParseVector<Vec3, 3>(this->verts);
|
ParseVector<vec3, 3>(this->verts);
|
||||||
}
|
}
|
||||||
else if (sc.Compare("vn")) // Vertex normal
|
else if (sc.Compare("vn")) // Vertex normal
|
||||||
{
|
{
|
||||||
ParseVector<Vec3, 3>(this->norms);
|
ParseVector<vec3, 3>(this->norms);
|
||||||
}
|
}
|
||||||
else if (sc.Compare("vt")) // UV Coordinates
|
else if (sc.Compare("vt")) // UV Coordinates
|
||||||
{
|
{
|
||||||
ParseVector<Vec2, 2>(this->uvs);
|
ParseVector<vec2, 2>(this->uvs);
|
||||||
}
|
}
|
||||||
else if (sc.Compare("usemtl"))
|
else if (sc.Compare("usemtl"))
|
||||||
{
|
{
|
||||||
|
@ -223,7 +223,7 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
|
||||||
|
|
||||||
if (uvs.Size() == 0)
|
if (uvs.Size() == 0)
|
||||||
{ // Needed so that OBJs without UVs can work
|
{ // Needed so that OBJs without UVs can work
|
||||||
uvs.Push(Vec2(0.0, 0.0));
|
uvs.Push(vec2(0.0, 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -395,9 +395,9 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
|
||||||
int uvidx = (curSide.uvref >= 0 && (unsigned int)curSide.uvref < uvs.Size()) ? curSide.uvref : 0;
|
int uvidx = (curSide.uvref >= 0 && (unsigned int)curSide.uvref < uvs.Size()) ? curSide.uvref : 0;
|
||||||
int nidx = curSide.normref;
|
int nidx = curSide.normref;
|
||||||
|
|
||||||
Vec3 curVvec = RealignVector(verts[vidx]);
|
vec3 curVvec = RealignVector(verts[vidx]);
|
||||||
Vec2 curUvec = FixUV(uvs[uvidx]);
|
vec2 curUvec = FixUV(uvs[uvidx]);
|
||||||
Vec3 nvec;
|
vec3 nvec;
|
||||||
|
|
||||||
mdv->Set(curVvec.x, curVvec.y, curVvec.z, curUvec.x, curUvec.y);
|
mdv->Set(curVvec.x, curVvec.y, curVvec.z, curUvec.x, curUvec.y);
|
||||||
|
|
||||||
|
@ -526,7 +526,7 @@ void FOBJModel::AddVertFaces() {
|
||||||
* @param vecToRealign The vector to re-align
|
* @param vecToRealign The vector to re-align
|
||||||
* @return The re-aligned vector
|
* @return The re-aligned vector
|
||||||
*/
|
*/
|
||||||
inline Vec3 FOBJModel::RealignVector(Vec3 vecToRealign)
|
inline vec3 FOBJModel::RealignVector(vec3 vecToRealign)
|
||||||
{
|
{
|
||||||
vecToRealign.z *= -1;
|
vecToRealign.z *= -1;
|
||||||
return vecToRealign;
|
return vecToRealign;
|
||||||
|
@ -538,7 +538,7 @@ inline Vec3 FOBJModel::RealignVector(Vec3 vecToRealign)
|
||||||
* @param vecToRealign The vector to fix
|
* @param vecToRealign The vector to fix
|
||||||
* @return The fixed UV coordinate vector
|
* @return The fixed UV coordinate vector
|
||||||
*/
|
*/
|
||||||
inline Vec2 FOBJModel::FixUV(Vec2 vecToRealign)
|
inline vec2 FOBJModel::FixUV(vec2 vecToRealign)
|
||||||
{
|
{
|
||||||
vecToRealign.y *= -1;
|
vecToRealign.y *= -1;
|
||||||
return vecToRealign;
|
return vecToRealign;
|
||||||
|
@ -551,7 +551,7 @@ inline Vec2 FOBJModel::FixUV(Vec2 vecToRealign)
|
||||||
* @param triIdx The triangle Index
|
* @param triIdx The triangle Index
|
||||||
* @return The surface normal vector
|
* @return The surface normal vector
|
||||||
*/
|
*/
|
||||||
Vec3 FOBJModel::CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx)
|
vec3 FOBJModel::CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx)
|
||||||
{
|
{
|
||||||
// https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
|
// https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
|
||||||
int curVert = surfaces[surfIdx].tris[triIdx].sides[0].vertref;
|
int curVert = surfaces[surfIdx].tris[triIdx].sides[0].vertref;
|
||||||
|
@ -559,9 +559,9 @@ Vec3 FOBJModel::CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx)
|
||||||
int lastVert = surfaces[surfIdx].tris[triIdx].sides[1].vertref;
|
int lastVert = surfaces[surfIdx].tris[triIdx].sides[1].vertref;
|
||||||
|
|
||||||
// Cross-multiply the U-vector and V-vector
|
// Cross-multiply the U-vector and V-vector
|
||||||
Vec3 curVvec = RealignVector(verts[curVert]);
|
vec3 curVvec = RealignVector(verts[curVert]);
|
||||||
Vec3 uvec = RealignVector(verts[nextVert]) - curVvec;
|
vec3 uvec = RealignVector(verts[nextVert]) - curVvec;
|
||||||
Vec3 vvec = RealignVector(verts[lastVert]) - curVvec;
|
vec3 vvec = RealignVector(verts[lastVert]) - curVvec;
|
||||||
|
|
||||||
return uvec ^ vvec;
|
return uvec ^ vvec;
|
||||||
}
|
}
|
||||||
|
@ -572,7 +572,7 @@ Vec3 FOBJModel::CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx)
|
||||||
* @param otr A reference to the surface, and a triangle within that surface, as an OBJTriRef
|
* @param otr A reference to the surface, and a triangle within that surface, as an OBJTriRef
|
||||||
* @return The surface normal vector
|
* @return The surface normal vector
|
||||||
*/
|
*/
|
||||||
Vec3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
|
vec3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
|
||||||
{
|
{
|
||||||
return CalculateNormalFlat(otr.surf, otr.tri);
|
return CalculateNormalFlat(otr.surf, otr.tri);
|
||||||
}
|
}
|
||||||
|
@ -583,18 +583,18 @@ Vec3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
|
||||||
* @param vidx The index of the vertex in the array of vertices
|
* @param vidx The index of the vertex in the array of vertices
|
||||||
* @param smoothGroup The smooth group number
|
* @param smoothGroup The smooth group number
|
||||||
*/
|
*/
|
||||||
Vec3 FOBJModel::CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup)
|
vec3 FOBJModel::CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup)
|
||||||
{
|
{
|
||||||
unsigned int connectedFaces = 0;
|
unsigned int connectedFaces = 0;
|
||||||
TArray<OBJTriRef>& vTris = vertFaces[vidx];
|
TArray<OBJTriRef>& vTris = vertFaces[vidx];
|
||||||
|
|
||||||
Vec3 vNormal(0,0,0);
|
vec3 vNormal(0,0,0);
|
||||||
for (size_t face = 0; face < vTris.Size(); face++)
|
for (size_t face = 0; face < vTris.Size(); face++)
|
||||||
{
|
{
|
||||||
OBJFace& tri = surfaces[vTris[face].surf].tris[vTris[face].tri];
|
OBJFace& tri = surfaces[vTris[face].surf].tris[vTris[face].tri];
|
||||||
if (tri.smoothGroup == smoothGroup)
|
if (tri.smoothGroup == smoothGroup)
|
||||||
{
|
{
|
||||||
Vec3 fNormal = CalculateNormalFlat(vTris[face]);
|
vec3 fNormal = CalculateNormalFlat(vTris[face]);
|
||||||
connectedFaces += 1;
|
connectedFaces += 1;
|
||||||
vNormal += fNormal;
|
vNormal += fNormal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,14 +96,14 @@ void FUE1Model::LoadGeometry()
|
||||||
if ( dxverts != NULL )
|
if ( dxverts != NULL )
|
||||||
{
|
{
|
||||||
// convert padded XYZ16
|
// convert padded XYZ16
|
||||||
Vert.Pos = Vec3(dxverts[j+i*numVerts].x,
|
Vert.Pos = vec3(dxverts[j+i*numVerts].x,
|
||||||
dxverts[j+i*numVerts].z,
|
dxverts[j+i*numVerts].z,
|
||||||
(float)-dxverts[j+i*numVerts].y);
|
(float)-dxverts[j+i*numVerts].y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// convert packed XY11Z10
|
// convert packed XY11Z10
|
||||||
Vert.Pos = Vec3(unpackuvert(averts[j+i*numVerts],0),
|
Vert.Pos = vec3(unpackuvert(averts[j+i*numVerts],0),
|
||||||
unpackuvert(averts[j+i*numVerts],2),
|
unpackuvert(averts[j+i*numVerts],2),
|
||||||
-unpackuvert(averts[j+i*numVerts],1));
|
-unpackuvert(averts[j+i*numVerts],1));
|
||||||
}
|
}
|
||||||
|
@ -123,14 +123,14 @@ void FUE1Model::LoadGeometry()
|
||||||
Poly.V[j] = dpolys[i].vertices[j];
|
Poly.V[j] = dpolys[i].vertices[j];
|
||||||
// unpack coords
|
// unpack coords
|
||||||
for ( int j=0; j<3; j++ )
|
for ( int j=0; j<3; j++ )
|
||||||
Poly.C[j] = Vec2(dpolys[i].uv[j][0]/255.f,dpolys[i].uv[j][1]/255.f);
|
Poly.C[j] = vec2(dpolys[i].uv[j][0]/255.f,dpolys[i].uv[j][1]/255.f);
|
||||||
// compute facet normals
|
// compute facet normals
|
||||||
for ( int j=0; j<numFrames; j++ )
|
for ( int j=0; j<numFrames; j++ )
|
||||||
{
|
{
|
||||||
Vec3 dir[2];
|
vec3 dir[2];
|
||||||
dir[0] = verts[Poly.V[1]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
|
dir[0] = verts[Poly.V[1]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
|
||||||
dir[1] = verts[Poly.V[2]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
|
dir[1] = verts[Poly.V[2]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
|
||||||
Poly.Normals.Push((Vec3::Cross(dir[0],dir[1])).Unit());
|
Poly.Normals.Push(normalize(cross(dir[0],dir[1])));
|
||||||
// since we're iterating frames, also set references for later
|
// since we're iterating frames, also set references for later
|
||||||
for ( int k=0; k<3; k++ )
|
for ( int k=0; k<3; k++ )
|
||||||
{
|
{
|
||||||
|
@ -148,10 +148,10 @@ void FUE1Model::LoadGeometry()
|
||||||
{
|
{
|
||||||
for ( int j=0; j<numVerts; j++ )
|
for ( int j=0; j<numVerts; j++ )
|
||||||
{
|
{
|
||||||
Vec3 nsum = Vec3(0,0,0);
|
vec3 nsum = vec3(0,0,0);
|
||||||
for ( int k=0; k<verts[j+numVerts*i].nP; k++ )
|
for ( int k=0; k<verts[j+numVerts*i].nP; k++ )
|
||||||
nsum += polys[verts[j+numVerts*i].P[k]].Normals[i];
|
nsum += polys[verts[j+numVerts*i].P[k]].Normals[i];
|
||||||
verts[j+numVerts*i].Normal = Vec3(nsum.Unit());
|
verts[j+numVerts*i].Normal = normalize(nsum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// populate poly groups (subdivided by texture number and type)
|
// populate poly groups (subdivided by texture number and type)
|
||||||
|
@ -281,7 +281,7 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
|
||||||
for ( int l=0; l<3; l++ )
|
for ( int l=0; l<3; l++ )
|
||||||
{
|
{
|
||||||
UE1Vertex V = verts[polys[groups[j].P[k]].V[l]+i*numVerts];
|
UE1Vertex V = verts[polys[groups[j].P[k]].V[l]+i*numVerts];
|
||||||
Vec2 C = polys[groups[j].P[k]].C[l];
|
vec2 C = polys[groups[j].P[k]].C[l];
|
||||||
FModelVertex *vert = &vptr[vidx++];
|
FModelVertex *vert = &vptr[vidx++];
|
||||||
vert->Set(V.Pos.x,V.Pos.y,V.Pos.z,C.x,C.y);
|
vert->Set(V.Pos.x,V.Pos.y,V.Pos.z,C.x,C.y);
|
||||||
if ( groups[j].type&PT_Curvy ) // use facet normal
|
if ( groups[j].type&PT_Curvy ) // use facet normal
|
||||||
|
|
Loading…
Reference in a new issue