Replace the vector/matrix classes with something behaving a bit more like glsl

This commit is contained in:
Magnus Norddahl 2021-11-12 22:40:29 +01:00
parent 6b4fef6a2b
commit cb42f82bfc
32 changed files with 1618 additions and 2715 deletions

View file

@ -179,13 +179,11 @@ set( SOURCES
src/lightmap/glsl_rmiss_sun.h
src/lightmap/cpuraytracer.cpp
src/lightmap/cpuraytracer.h
src/math/mat.cpp
src/math/plane.cpp
src/math/angle.cpp
src/math/bounds.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.h
src/models/model_md2.h
@ -220,6 +218,9 @@ set( HEADERS
src/lightmap/surfaces.h
src/lightmap/worker.h
src/lightmap/collision.h
src/math/mat.h
src/math/quaternion.h
src/math/vec.h
src/math/mathlib.h
)

View file

@ -65,9 +65,9 @@ float BinFile::ReadFloat()
return fi.f;
}
Vec3 BinFile::ReadVector()
vec3 BinFile::ReadVector()
{
Vec3 vec;
vec3 vec;
vec.x = ReadFloat();
vec.y = ReadFloat();
@ -121,7 +121,7 @@ void BinFile::WriteFloat(const float val)
Write32(fi.i);
}
void BinFile::WriteVector(const Vec3 &val)
void BinFile::WriteVector(const vec3 &val)
{
WriteFloat(val.x);
WriteFloat(val.y);

View file

@ -37,14 +37,14 @@ public:
short Read16();
int Read32();
float ReadFloat();
Vec3 ReadVector();
vec3 ReadVector();
std::string ReadString();
void Write8(const uint8_t val);
void Write16(const short val);
void Write32(const int val);
void WriteFloat(const float val);
void WriteVector(const Vec3 &val);
void WriteVector(const vec3 &val);
void WriteString(const std::string &val);
int GetOffsetValue(int id);

View file

@ -165,29 +165,3 @@ const T MAX (const T a, const T 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;
}

View file

@ -250,8 +250,6 @@ struct IntVertex
};
class BBox;
class Vec3;
class Vec2;
struct vertex_t;
struct Surface;
struct ThingLight;
@ -265,8 +263,8 @@ struct FloatVertex
struct ThingLight
{
IntThing *mapThing;
Vec2 origin;
Vec3 rgb;
vec2 origin;
vec3 rgb;
float intensity;
float innerAngleCos;
float outerAngleCos;
@ -276,14 +274,14 @@ struct ThingLight
IntSector *sector;
MapSubsectorEx *ssect;
Vec3 LightOrigin() const
vec3 LightOrigin() const
{
float originZ;
if (!bCeiling)
originZ = sector->floorplane.zAt(origin.x, origin.y) + height;
else
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
@ -291,31 +289,31 @@ struct ThingLight
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;
if (outerAngleCos > -1.0f)
{
float negPitch = -radians(mapThing->pitch);
float xyLen = std::cos(negPitch);
Vec3 spotDir;
vec3 spotDir;
spotDir.x = -std::cos(radians(mapThing->angle)) * xyLen;
spotDir.y = -std::sin(radians(mapThing->angle)) * xyLen;
spotDir.z = -std::sin(negPitch);
float cosDir = Vec3::Dot(dir, spotDir);
float cosDir = dot(dir, spotDir);
spotAttenuation = smoothstep(outerAngleCos, innerAngleCos, cosDir);
spotAttenuation = std::max(spotAttenuation, 0.0f);
}
return spotAttenuation;
}
Vec3 SpotDir() const
vec3 SpotDir() const
{
if (outerAngleCos > -1.0f)
{
float negPitch = -radians(mapThing->pitch);
float xyLen = std::cos(negPitch);
Vec3 spotDir;
vec3 spotDir;
spotDir.x = -std::cos(radians(mapThing->angle)) * xyLen;
spotDir.y = -std::sin(radians(mapThing->angle)) * xyLen;
spotDir.z = -std::sin(negPitch);
@ -323,7 +321,7 @@ struct ThingLight
}
else
{
return Vec3(0.0f);
return vec3(0.0f);
}
}
@ -337,7 +335,7 @@ struct SurfaceLightDef
{
float distance;
float intensity;
Vec3 rgb;
vec3 rgb;
};
enum mapFlags_t
@ -387,8 +385,8 @@ struct FLevel
TArray<SurfaceLightDef> SurfaceLights;
TArray<int> ThingLightProbes;
Vec3 defaultSunColor;
Vec3 defaultSunDirection;
vec3 defaultSunColor;
vec3 defaultSunDirection;
int Samples;
int LightBounce;
float GridSize;
@ -404,15 +402,15 @@ struct FLevel
int NumSectors() const { return Sectors.Size(); }
int NumThings() const { return Things.Size(); }
const Vec3 &GetSunColor() const;
const Vec3 &GetSunDirection() const;
const vec3 &GetSunColor() const;
const vec3 &GetSunDirection() const;
IntSector *GetFrontSector(const IntSideDef *side);
IntSector *GetBackSector(const IntSideDef *side);
IntSector *GetSectorFromSubSector(const MapSubsectorEx *sub);
MapSubsectorEx *PointInSubSector(const int x, const int y);
FloatVertex GetSegVertex(int index);
Vec3 GetLightProbePosition(int index);
vec3 GetLightProbePosition(int index);
private:
void CheckSkySectors();

View file

@ -85,8 +85,8 @@ void FLevel::SetupLights()
}
// GG to whoever memset'ed FLevel
defaultSunColor = Vec3(1, 1, 1);
defaultSunDirection = Vec3(0.45f, 0.3f, 0.9f);
defaultSunColor = vec3(1, 1, 1);
defaultSunDirection = vec3(0.45f, 0.3f, 0.9f);
Samples = 8;
LightBounce = 1;
GridSize = 32.0f;
@ -101,8 +101,8 @@ void FLevel::SetupLights()
else if (thing->type == 9890) // ZDRayInfo
{
uint32_t lightcolor = 0xffffff;
Vec3 sundir(0.0f, 0.0f, 0.0f);
Vec3 suncolor(1.0f, 1.0f, 1.0f);
vec3 sundir(0.0f, 0.0f, 0.0f);
vec3 suncolor(1.0f, 1.0f, 1.0f);
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.y = ((lightcolor >> 8) & 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;
}
const Vec3 &FLevel::GetSunDirection() const
const vec3 &FLevel::GetSunDirection() const
{
return defaultSunDirection;
}
@ -235,8 +235,8 @@ MapSubsectorEx *FLevel::PointInSubSector(const int x, const int y)
MapNodeEx *node;
int side;
int nodenum;
Vec3 dp1;
Vec3 dp2;
vec3 dp1;
vec3 dp2;
float d;
// single subsector is a special case
@ -251,15 +251,15 @@ MapSubsectorEx *FLevel::PointInSubSector(const int x, const int y)
{
node = &GLNodes[nodenum];
Vec3 pt1(F(node->x), F(node->y), 0);
Vec3 pt2(F(node->dx), F(node->dy), 0);
//Vec3 pt1(F(node->x << 16), F(node->y << 16), 0);
//Vec3 pt2(F(node->dx << 16), F(node->dy << 16), 0);
Vec3 pos(F(x << 16), F(y << 16), 0);
vec3 pt1(F(node->x), F(node->y), 0);
vec3 pt2(F(node->dx), F(node->dy), 0);
//vec3 pt1(F(node->x << 16), F(node->y << 16), 0);
//vec3 pt2(F(node->dx << 16), F(node->dy << 16), 0);
vec3 pos(F(x << 16), F(y << 16), 0);
dp1 = pt1 - pos;
dp2 = (pt2 + pt1) - pos;
d = dp1.Cross(dp2).z;
d = cross(dp1, dp2).z;
side = FLOATSIGNBIT(d);
@ -338,7 +338,8 @@ void FLevel::CreateLights()
thingLight.bCeiling = false;
thingLight.ssect = PointInSubSector(x, y);
thingLight.sector = GetSectorFromSubSector(thingLight.ssect);
thingLight.origin.Set(x, y);
thingLight.origin.x = x;
thingLight.origin.y = y;
ThingLights.Push(thingLight);
}
@ -464,7 +465,7 @@ void FLevel::CreateLights()
printf("Surface lights: %i\n", (int)SurfaceLights.Size());
}
Vec3 FLevel::GetLightProbePosition(int index)
vec3 FLevel::GetLightProbePosition(int index)
{
int thingIndex = ThingLightProbes[index];
const IntThing& thing = Things[thingIndex];
@ -482,5 +483,5 @@ Vec3 FLevel::GetLightProbePosition(int index)
z = sector->floorplane.zAt(x, y) + thing.height;
}
}
return Vec3(x, y, z);
return vec3(x, y, z);
}

View file

@ -519,7 +519,7 @@ void FProcessor::ParseSector(IntSector *sec)
}
else
{
float scale = 1.0f / sec->ceilingplane.Normal().Length();
float scale = 1.0f / length(sec->ceilingplane.Normal());
sec->ceilingplane.a *= scale;
sec->ceilingplane.b *= scale;
sec->ceilingplane.c *= scale;
@ -536,7 +536,7 @@ void FProcessor::ParseSector(IntSector *sec)
}
else
{
float scale = 1.0f / sec->floorplane.Normal().Length();
float scale = 1.0f / length(sec->floorplane.Normal());
sec->floorplane.a *= scale;
sec->floorplane.b *= scale;
sec->floorplane.c *= scale;

View file

@ -28,7 +28,7 @@
#include <immintrin.h>
#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)
{
int num_triangles = num_elements / 3;
@ -36,7 +36,7 @@ TriangleMeshShape::TriangleMeshShape(const Vec3 *vertices, int num_vertices, con
return;
std::vector<int> triangles;
std::vector<Vec3> centroids;
std::vector<vec3> centroids;
triangles.reserve(num_triangles);
centroids.reserve(num_triangles);
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);
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);
}
@ -53,7 +53,7 @@ TriangleMeshShape::TriangleMeshShape(const Vec3 *vertices, int num_vertices, con
root = subdivide(&triangles[0], (int)triangles.size(), &centroids[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);
}
@ -68,19 +68,19 @@ bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape1, SphereShape *sha
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);
}
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;
// Perform segmented tracing to keep the ray AABB box smaller
Vec3 ray_dir = ray_end - ray_start;
float tracedist = ray_dir.Length();
vec3 ray_dir = ray_end - ray_start;
float tracedist = length(ray_dir);
float segmentlen = std::max(100.0f, tracedist / 20.0f);
for (float t = 0.0f; t < tracedist; t += segmentlen)
{
@ -98,7 +98,7 @@ TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const Vec3
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))
{
@ -239,7 +239,7 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
{
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 + 1]],
@ -248,15 +248,15 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
// MoellerTrumbore ray-triangle intersection algorithm:
Vec3 D = ray.end - ray.start;
vec3 D = ray.end - ray.start;
// Find vectors for two edges sharing p[0]
Vec3 e1 = p[1] - p[0];
Vec3 e2 = p[2] - p[0];
vec3 e1 = p[1] - p[0];
vec3 e2 = p[2] - p[0];
// Begin calculating determinant - also used to calculate u parameter
Vec3 P = Vec3::Cross(D, e2);
float det = Vec3::Dot(e1, P);
vec3 P = cross(D, e2);
float det = dot(e1, P);
// Backface check
//if (det < 0.0f)
@ -269,26 +269,26 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
float inv_det = 1.0f / det;
// 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
float u = Vec3::Dot(T, P) * inv_det;
float u = dot(T, P) * inv_det;
// Check if the intersection lies outside of the triangle
if (u < 0.f || u > 1.f)
return 1.0f;
// Prepare to test v parameter
Vec3 Q = Vec3::Cross(T, e1);
vec3 Q = cross(T, e1);
// 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
if (v < 0.f || u + v > 1.f)
return 1.0f;
float t = Vec3::Dot(e2, Q) * inv_det;
float t = dot(e2, Q) * inv_det;
if (t <= FLT_EPSILON)
return 1.0f;
@ -299,7 +299,7 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
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:
@ -309,30 +309,30 @@ bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, Spher
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;
Vec3 p[3] =
vec3 p[3] =
{
shape1->vertices[shape1->elements[start_element]],
shape1->vertices[shape1->elements[start_element + 1]],
shape1->vertices[shape1->elements[start_element + 2]]
};
Vec3 c = shape2->center;
Vec3 e = target;
vec3 c = shape2->center;
vec3 e = target;
float r = shape2->radius;
// 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]));
Vec4 plane(n, -Vec3::Dot(n, p[0]));
vec3 n = normalize(cross(p[1] - p[0], p[2] - p[0]));
vec4 plane(n, -dot(n, p[0]));
// Step 1: Plane intersect test
float sc = Vec4::Dot(plane, Vec4(c, 1.0f));
float se = Vec4::Dot(plane, Vec4(e, 1.0f));
float sc = dot(plane, vec4(c, 1.0f));
float se = dot(plane, vec4(e, 1.0f));
bool same_side = sc * se > 0.0f;
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);
Vec3 vt = c + (e - c) * t;
vec3 vt = c + (e - c) * t;
Vec3 u0 = p[1] - p[0];
Vec3 u1 = p[2] - p[0];
vec3 u0 = p[1] - p[0];
vec3 u1 = p[2] - p[0];
Vec2 v_2d[3] =
vec2 v_2d[3] =
{
Vec2(0.0f, 0.0f),
Vec2(Vec3::Dot(u0, u0), 0.0f),
Vec2(0.0f, Vec3::Dot(u1, u1))
vec2(0.0f, 0.0f),
vec2(dot(u0, u0), 0.0f),
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;
Vec2 e0 = v_2d[2];
vec2 e0 = v_2d[2];
bool y0 = e0.y >= point.y;
for (int i = 0; i < 3; i++)
{
Vec2 e1 = v_2d[i];
vec2 e1 = v_2d[i];
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)
@ -377,21 +377,21 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
// Step 2: Edge intersect test
Vec3 ke[3] =
vec3 ke[3] =
{
p[1] - p[0],
p[2] - p[1],
p[0] - p[2],
};
Vec3 kg[3] =
vec3 kg[3] =
{
p[0] - c,
p[1] - c,
p[2] - c,
};
Vec3 ks = e - c;
vec3 ks = e - c;
float kgg[3];
float kgs[3];
@ -399,12 +399,12 @@ float TriangleMeshShape::sweep_intersect_triangle_sphere(TriangleMeshShape *shap
for (int i = 0; i < 3; i++)
{
float kee = Vec3::Dot(ke[i], ke[i]);
float keg = Vec3::Dot(ke[i], kg[i]);
float kes = Vec3::Dot(ke[i], ks);
kgg[i] = Vec3::Dot(kg[i], kg[i]);
kgs[i] = Vec3::Dot(kg[i], ks);
kss[i] = Vec3::Dot(ks, ks);
float kee = dot(ke[i], ke[i]);
float keg = dot(ke[i], kg[i]);
float kes = dot(ke[i], ks);
kgg[i] = dot(kg[i], kg[i]);
kgs[i] = dot(kg[i], ks);
kss[i] = dot(ks, ks);
float aa = kee * kss[i] - kes * kes;
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)
{
Vec3 ct = c + ks * t;
float d = Vec3::Dot(ct - p[i], ke[i]);
vec3 ct = c + ks * t;
float d = dot(ct - p[i], ke[i]);
if (d >= 0.0f && d <= kee)
return t;
}
@ -486,49 +486,49 @@ bool TriangleMeshShape::overlap_triangle_sphere(TriangleMeshShape *shape1, Spher
int element_index = shape1->nodes[shape1_node_index].element_index;
Vec3 P = shape2->center;
Vec3 A = shape1->vertices[shape1->elements[element_index]] - P;
Vec3 B = shape1->vertices[shape1->elements[element_index + 1]] - P;
Vec3 C = shape1->vertices[shape1->elements[element_index + 2]] - P;
vec3 P = shape2->center;
vec3 A = shape1->vertices[shape1->elements[element_index]] - P;
vec3 B = shape1->vertices[shape1->elements[element_index + 1]] - P;
vec3 C = shape1->vertices[shape1->elements[element_index + 2]] - P;
float r = shape2->radius;
float rr = r * r;
// Testing if sphere lies outside the triangle plane
Vec3 V = Vec3::Cross(B - A, C - A);
float d = Vec3::Dot(A, V);
float e = Vec3::Dot(V, V);
vec3 V = cross(B - A, C - A);
float d = dot(A, V);
float e = dot(V, V);
bool sep1 = d * d > rr * e;
// Testing if sphere lies outside a triangle vertex
float aa = Vec3::Dot(A, A);
float ab = Vec3::Dot(A, B);
float ac = Vec3::Dot(A, C);
float bb = Vec3::Dot(B, B);
float bc = Vec3::Dot(B, C);
float cc = Vec3::Dot(C, C);
float aa = dot(A, A);
float ab = dot(A, B);
float ac = dot(A, C);
float bb = dot(B, B);
float bc = dot(B, C);
float cc = dot(C, C);
bool sep2 = (aa > rr) && (ab > aa) && (ac > aa);
bool sep3 = (bb > rr) && (ab > bb) && (bc > bb);
bool sep4 = (cc > rr) && (ac > cc) && (bc > cc);
// Testing if sphere lies outside a triangle edge
Vec3 AB = B - A;
Vec3 BC = C - B;
Vec3 CA = A - C;
vec3 AB = B - A;
vec3 BC = C - B;
vec3 CA = A - C;
float d1 = ab - aa;
float d2 = bc - bb;
float d3 = ac - cc;
float e1 = Vec3::Dot(AB, AB);
float e2 = Vec3::Dot(BC, BC);
float e3 = Vec3::Dot(CA, CA);
Vec3 Q1 = A * e1 - AB * d1;
Vec3 Q2 = B * e2 - BC * d2;
Vec3 Q3 = C * e3 - CA * d3;
Vec3 QC = C * e1 - Q1;
Vec3 QA = A * e2 - Q2;
Vec3 QB = B * e3 - Q3;
bool sep5 = (Vec3::Dot(Q1, Q1) > rr * e1 * e1) && (Vec3::Dot(Q1, QC) > 0.0f);
bool sep6 = (Vec3::Dot(Q2, Q2) > rr * e2 * e2) && (Vec3::Dot(Q2, QA) > 0.0f);
bool sep7 = (Vec3::Dot(Q3, Q3) > rr * e3 * e3) && (Vec3::Dot(Q3, QB) > 0.0f);
float e1 = dot(AB, AB);
float e2 = dot(BC, BC);
float e3 = dot(CA, CA);
vec3 Q1 = A * e1 - AB * d1;
vec3 Q2 = B * e2 - BC * d2;
vec3 Q3 = C * e3 - CA * d3;
vec3 QC = C * e1 - Q1;
vec3 QA = A * e2 - Q2;
vec3 QB = B * e3 - Q3;
bool sep5 = (dot(Q1, Q1) > rr * e1 * e1) && (dot(Q1, QC) > 0.0f);
bool sep6 = (dot(Q2, Q2) > rr * e2 * e2) && (dot(Q2, QA) > 0.0f);
bool sep7 = (dot(Q3, Q3) > rr * e3 * e3) && (dot(Q3, QB) > 0.0f);
bool separated = sep1 || sep2 || sep3 || sep4 || sep5 || sep6 || sep7;
return (!separated);
@ -541,7 +541,7 @@ bool TriangleMeshShape::is_leaf(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;
}
@ -591,14 +591,14 @@ float TriangleMeshShape::get_balanced_depth() const
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)
return -1;
// Find bounding box and median of the triangle centroids
Vec3 median;
Vec3 min, max;
vec3 median;
vec3 min, max;
min = vertices[elements[triangles[0] * 3]];
max = min;
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;
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.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
int left_count, right_count;
Vec3 axis;
vec3 axis;
for (int attempt = 0; attempt < 3; attempt++)
{
// Find the split plane for axis
switch (axis_order[attempt])
{
default:
case 0: axis = Vec3(1.0f, 0.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 0: axis = vec3(1.0f, 0.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;
}
Vec4 plane(axis, -Vec3::Dot(median, axis));
vec4 plane(axis, -dot(median, axis));
// Split triangles into two
left_count = 0;
@ -661,7 +661,7 @@ int TriangleMeshShape::subdivide(int *triangles, int num_triangles, const Vec3 *
int triangle = triangles[i];
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)
{
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 extents = aabb.Extents();
vec3 center = aabb.Center();
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 s = center.x * plane.x + center.y * plane.y + center.z * plane.z + plane.w;
if (s - e > 0)
@ -721,12 +721,12 @@ IntersectionTest::Result IntersectionTest::plane_aabb(const Vec4 &plane, const B
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 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 s = Vec3::Dot(obb.Center, n) + d;
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 = dot(obb.Center, n) + d;
if (s - e > 0)
return inside;
else if (s + e < 0)
@ -735,10 +735,10 @@ IntersectionTest::Result IntersectionTest::plane_obb(const Vec4 &plane, const Or
return intersecting;
}
IntersectionTest::OverlapResult IntersectionTest::sphere(const Vec3 &center1, float radius1, const Vec3 &center2, float radius2)
IntersectionTest::OverlapResult IntersectionTest::sphere(const vec3 &center1, float radius1, const vec3 &center2, float radius2)
{
Vec3 h = center1 - center2;
float square_distance = Vec3::Dot(h, h);
vec3 h = center1 - center2;
float square_distance = dot(h, h);
float radius_sum = radius1 + radius2;
if (square_distance > radius_sum * radius_sum)
return disjoint;
@ -746,18 +746,18 @@ IntersectionTest::OverlapResult IntersectionTest::sphere(const Vec3 &center1, fl
return overlap;
}
IntersectionTest::OverlapResult IntersectionTest::sphere_aabb(const Vec3 &center, float radius, const BBox &aabb)
IntersectionTest::OverlapResult IntersectionTest::sphere_aabb(const vec3 &center, float radius, const BBox &aabb)
{
Vec3 a = aabb.min - center;
Vec3 b = center - aabb.max;
vec3 a = aabb.min - center;
vec3 b = center - aabb.max;
a.x = std::max(a.x, 0.0f);
a.y = std::max(a.y, 0.0f);
a.z = std::max(a.z, 0.0f);
b.x = std::max(b.x, 0.0f);
b.y = std::max(b.y, 0.0f);
b.z = std::max(b.z, 0.0f);
Vec3 e = a + b;
float d = Vec3::Dot(e, e);
vec3 e = a + b;
float d = dot(e, e);
if (d > radius * radius)
return disjoint;
else
@ -847,9 +847,9 @@ IntersectionTest::OverlapResult IntersectionTest::ray_aabb(const RayBBox &ray, c
return (mask & 7) ? disjoint : overlap;
#else
const Vec3 &v = ray.v;
const Vec3 &w = ray.w;
const Vec3 &h = aabb.Extents;
const vec3 &v = ray.v;
const vec3 &w = ray.w;
const vec3 &h = aabb.Extents;
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)
@ -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[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);
}
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 + 1 * 4] + matrix[0 + 1 * 4],
matrix[3 + 2 * 4] + matrix[0 + 2 * 4],
matrix[3 + 3 * 4] + matrix[0 + 3 * 4]);
plane /= plane.ToVec3().Length();
plane /= length(plane.xyz());
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 + 1 * 4] - matrix[0 + 1 * 4],
matrix[3 + 2 * 4] - matrix[0 + 2 * 4],
matrix[3 + 3 * 4] - matrix[0 + 3 * 4]);
plane /= plane.ToVec3().Length();
plane /= length(plane.xyz());
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 + 1 * 4] - matrix[1 + 1 * 4],
matrix[3 + 2 * 4] - matrix[1 + 2 * 4],
matrix[3 + 3 * 4] - matrix[1 + 3 * 4]);
plane /= plane.ToVec3().Length();
plane /= length(plane.xyz());
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 + 1 * 4] + matrix[1 + 1 * 4],
matrix[3 + 2 * 4] + matrix[1 + 2 * 4],
matrix[3 + 3 * 4] + matrix[1 + 3 * 4]);
plane /= plane.ToVec3().Length();
plane /= length(plane.xyz());
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 + 1 * 4] + matrix[2 + 1 * 4],
matrix[3 + 2 * 4] + matrix[2 + 2 * 4],
matrix[3 + 3 * 4] + matrix[2 + 3 * 4]);
plane /= plane.ToVec3().Length();
plane /= length(plane.xyz());
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 + 1 * 4] - matrix[2 + 1 * 4],
matrix[3 + 2 * 4] - matrix[2 + 2 * 4],
matrix[3 + 3 * 4] - matrix[2 + 3 * 4]);
plane /= plane.ToVec3().Length();
plane /= length(plane.xyz());
return plane;
}

View file

@ -30,9 +30,9 @@ class SphereShape
{
public:
SphereShape() { }
SphereShape(const Vec3 &center, float radius) : center(center), radius(radius) { }
SphereShape(const vec3 &center, float radius) : center(center), radius(radius) { }
Vec3 center;
vec3 center;
float radius = 0.0f;
};
@ -49,7 +49,7 @@ class CollisionBBox : public BBox
public:
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 halfmax = aabb_max * 0.5f;
@ -57,15 +57,15 @@ public:
Extents = halfmax - halfmin;
}
Vec3 Center;
Vec3 Extents;
vec3 Center;
vec3 Extents;
float ssePadding = 0.0f; // Needed to safely load Extents directly into a sse register
};
class RayBBox
{
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;
w = ray_end - c;
@ -74,15 +74,15 @@ public:
v.z = std::abs(w.z);
}
Vec3 start, end;
Vec3 c, w, v;
vec3 start, end;
vec3 c, w, v;
float ssePadding = 0.0f; // Needed to safely load v directly into a sse register
};
class TriangleMeshShape
{
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_max_depth() const;
@ -91,20 +91,20 @@ public:
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, 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:
struct Node
{
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 left, int right) : aabb(aabb_min, aabb_max), left(left), right(right) { }
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) { }
CollisionBBox aabb;
int left = -1;
@ -112,7 +112,7 @@ private:
int element_index = -1;
};
const Vec3 *vertices = nullptr;
const vec3 *vertices = nullptr;
const int num_vertices = 0;
const unsigned int *elements = nullptr;
int num_elements = 0;
@ -120,7 +120,7 @@ private:
std::vector<Node> nodes;
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, SphereShape *shape2, int a);
@ -131,8 +131,8 @@ private:
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 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 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 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);
@ -143,34 +143,34 @@ private:
inline bool is_leaf(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
{
public:
Vec3 Center;
Vec3 Extents;
Vec3 axis_x;
Vec3 axis_y;
Vec3 axis_z;
vec3 Center;
vec3 Extents;
vec3 axis_x;
vec3 axis_y;
vec3 axis_z;
};
class FrustumPlanes
{
public:
FrustumPlanes();
explicit FrustumPlanes(const Mat4 &world_to_projection);
explicit FrustumPlanes(const mat4 &world_to_projection);
Vec4 planes[6];
vec4 planes[6];
private:
static Vec4 left_frustum_plane(const Mat4 &matrix);
static Vec4 right_frustum_plane(const Mat4 &matrix);
static Vec4 top_frustum_plane(const Mat4 &matrix);
static Vec4 bottom_frustum_plane(const Mat4 &matrix);
static Vec4 near_frustum_plane(const Mat4 &matrix);
static Vec4 far_frustum_plane(const Mat4 &matrix);
static vec4 left_frustum_plane(const mat4 &matrix);
static vec4 right_frustum_plane(const mat4 &matrix);
static vec4 top_frustum_plane(const mat4 &matrix);
static vec4 bottom_frustum_plane(const mat4 &matrix);
static vec4 near_frustum_plane(const mat4 &matrix);
static vec4 far_frustum_plane(const mat4 &matrix);
};
class IntersectionTest
@ -189,10 +189,10 @@ public:
overlap
};
static Result plane_aabb(const Vec4 &plane, const BBox &aabb);
static Result plane_obb(const Vec4 &plane, const OrientedBBox &obb);
static OverlapResult sphere(const Vec3 &center1, float radius1, const Vec3 &center2, float radius2);
static OverlapResult sphere_aabb(const Vec3 &center, float radius, const BBox &aabb);
static Result plane_aabb(const vec4 &plane, const BBox &aabb);
static Result plane_obb(const vec4 &plane, const OrientedBBox &obb);
static OverlapResult sphere(const vec3 &center1, float radius1, const vec3 &center2, float radius2);
static OverlapResult sphere_aabb(const vec3 &center, float radius, const BBox &aabb);
static OverlapResult aabb(const BBox &a, const BBox &b);
static Result frustum_aabb(const FrustumPlanes &frustum, const BBox &box);
static Result frustum_obb(const FrustumPlanes &frustum, const OrientedBBox &box);

View file

@ -73,7 +73,7 @@ void CPURaytracer::RaytraceTask(const CPUTraceTask& task)
if (task.id >= 0)
{
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.StartSurface = surface;
}
@ -134,7 +134,7 @@ void CPURaytracer::RaytraceTask(const CPUTraceTask& task)
void CPURaytracer::RunBounceTrace(CPUTraceState& state)
{
Vec3 origin;
vec3 origin;
Surface* surface;
if (state.PassType == 2)
{
@ -147,7 +147,7 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
surface = state.StartSurface;
}
Vec3 incoming(0.0f, 0.0f, 0.0f);
vec3 incoming(0.0f, 0.0f, 0.0f);
float incomingAttenuation = 1.0f;
if (state.PassType == 0)
@ -166,7 +166,7 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
if (state.PassType == 1)
incomingAttenuation = 1.0f / float(state.SampleCount);
Vec3 normal;
vec3 normal;
if (surface)
{
normal = surface->plane.Normal();
@ -175,19 +175,19 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
{
switch (state.SampleIndex % 6)
{
case 0: 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 3: normal = Vec3( 0.0f, -1.0f, 0.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 0: 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 3: normal = vec3( 0.0f, -1.0f, 0.0f); break;
case 4: 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 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
vec3 H = ImportanceSample(state.HemisphereVec, 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));
incomingAttenuation *= NdotL / p;
@ -195,19 +195,19 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
state.EndTrace = true;
if (NdotL > 0.0f)
{
Vec3 start = origin + normal * 0.1f;
Vec3 end = start + L * 32768.0f;
vec3 start = origin + normal * 0.1f;
vec3 end = start + L * 32768.0f;
LevelTraceHit hit = Trace(start, end);
if (hit.fraction < 1.0f)
{
state.EndTrace = false;
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);
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);
incoming += emissive.Color * (emissive.Intensity * attenuation * incomingAttenuation);
}
@ -227,15 +227,15 @@ void CPURaytracer::RunBounceTrace(CPUTraceState& state)
void CPURaytracer::RunLightTrace(CPUTraceState& state)
{
Vec3 incoming = state.Output;
vec3 incoming = state.Output;
float incomingAttenuation = state.OutputAttenuation;
if (incomingAttenuation <= 0.0f)
return;
Surface* surface = state.Surf;
Vec3 origin = state.Position;
Vec3 normal;
vec3 origin = state.Position;
vec3 normal;
if (surface)
{
normal = surface->plane.Normal();
@ -251,17 +251,17 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
float attenuation = 0.0f;
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 e1 = Vec3::Cross(normal, e0);
e0 = Vec3::Cross(normal, e1);
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 = cross(normal, e0);
e0 = cross(normal, e1);
for (uint32_t i = 0; i < state.SampleCount; i++)
{
Vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
Vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
Vec3 start = origin2;
Vec3 end = start + state.SunDir * dist;
vec3 start = origin2;
vec3 end = start + state.SunDir * dist;
LevelTraceHit hit = Trace(start, end);
if (hit.fraction < 1.0f && hit.hitSurface->bSky)
attenuation += 1.0f;
@ -270,8 +270,8 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
}
else
{
Vec3 start = origin;
Vec3 end = start + state.SunDir * dist;
vec3 start = origin;
vec3 end = start + state.SunDir * dist;
LevelTraceHit hit = Trace(start, end);
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
float dist = (light.Origin - origin).Length();
float dist = length(light.Origin - origin);
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 angleAttenuation = 1.0f;
if (surface)
{
angleAttenuation = std::max(Vec3::Dot(normal, dir), 0.0f);
angleAttenuation = std::max(dot(normal, dir), 0.0f);
}
float spotAttenuation = 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 = std::max(spotAttenuation, 0.0f);
}
@ -308,13 +308,13 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
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 e1 = Vec3::Cross(normal, e0);
e0 = Vec3::Cross(normal, e1);
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 = cross(normal, e0);
e0 = cross(normal, e1);
for (uint32_t i = 0; i < state.SampleCount; i++)
{
Vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
Vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
vec2 offset = (Hammersley(i, state.SampleCount) - 0.5f) * state.SampleDistance;
vec3 origin2 = origin + e0 * offset.x + e1 * offset.y;
LevelTraceHit hit = Trace(origin2, light.Origin);
if (hit.fraction == 1.0f)
@ -338,20 +338,20 @@ void CPURaytracer::RunLightTrace(CPUTraceState& state)
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
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 bitangent = Vec3::Cross(N, tangent);
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 = normalize(cross(up, N));
vec3 bitangent = cross(N, tangent);
Vec3 sampleVec = tangent * HemisphereVec.x + bitangent * HemisphereVec.y + N * HemisphereVec.z;
return Vec3::Normalize(sampleVec);
vec3 sampleVec = tangent * HemisphereVec.x + bitangent * HemisphereVec.y + N * HemisphereVec.z;
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)
@ -371,12 +371,12 @@ void CPURaytracer::CreateHemisphereVectors()
HemisphereVectors.reserve(bounceSampleCount);
for (int i = 0; i < bounceSampleCount; i++)
{
Vec2 Xi = Hammersley(i, bounceSampleCount);
Vec3 H;
vec2 Xi = Hammersley(i, bounceSampleCount);
vec3 H;
H.x = Xi.x * 2.0f - 1.0f;
H.y = Xi.y * 2.0f - 1.0f;
H.z = RadicalInverse_VdC(i) + 0.01f;
H.Normalize();
H = normalize(H);
HemisphereVectors.push_back(H);
}
}
@ -440,13 +440,13 @@ CPUEmissiveSurface CPURaytracer::GetEmissive(Surface* surface)
{
info.Distance = 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;
}
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);
@ -476,7 +476,7 @@ LevelTraceHit CPURaytracer::Trace(const Vec3& startVec, const Vec3& endVec)
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);
}

View file

@ -10,13 +10,13 @@ struct CPUTraceTask
struct CPULightInfo
{
Vec3 Origin;
vec3 Origin;
float Radius;
float Intensity;
float InnerAngleCos;
float OuterAngleCos;
Vec3 SpotDir;
Vec3 Color;
vec3 SpotDir;
vec3 Color;
};
struct CPUTraceState
@ -25,19 +25,19 @@ struct CPUTraceState
uint32_t SampleCount;
uint32_t PassType;
uint32_t LightCount;
Vec3 SunDir;
vec3 SunDir;
float SampleDistance;
Vec3 SunColor;
vec3 SunColor;
float SunIntensity;
Vec3 HemisphereVec;
vec3 HemisphereVec;
Vec3 StartPosition;
vec3 StartPosition;
Surface* StartSurface;
Vec3 Position;
vec3 Position;
Surface* Surf;
Vec3 Output;
vec3 Output;
float OutputAttenuation;
bool EndTrace;
@ -47,13 +47,13 @@ struct CPUEmissiveSurface
{
float Distance;
float Intensity;
Vec3 Color;
vec3 Color;
};
struct LevelTraceHit
{
Vec3 start;
Vec3 end;
vec3 start;
vec3 end;
float fraction;
Surface* hitSurface;
@ -79,19 +79,19 @@ private:
void CreateHemisphereVectors();
void CreateLights();
LevelTraceHit Trace(const Vec3& startVec, const Vec3& endVec);
bool TraceAnyHit(const Vec3& startVec, const Vec3& endVec);
LevelTraceHit Trace(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 Vec2 Hammersley(uint32_t i, uint32_t N);
static vec2 Hammersley(uint32_t i, uint32_t N);
const int coverageSampleCount = 256;
const int bounceSampleCount = 2048;
LevelMesh* mesh = nullptr;
std::vector<Vec3> HemisphereVectors;
std::vector<vec3> HemisphereVectors;
std::vector<CPULightInfo> Lights;
std::unique_ptr<TriangleMeshShape> CollisionMesh;

View file

@ -73,16 +73,16 @@ void GPURaytracer::Raytrace(LevelMesh* level)
}
}
std::vector<Vec3> HemisphereVectors;
std::vector<vec3> HemisphereVectors;
HemisphereVectors.reserve(bounceSampleCount);
for (int i = 0; i < bounceSampleCount; i++)
{
Vec2 Xi = Hammersley(i, bounceSampleCount);
Vec3 H;
vec2 Xi = Hammersley(i, bounceSampleCount);
vec3 H;
H.x = Xi.x * 2.0f - 1.0f;
H.y = Xi.y * 2.0f - 1.0f;
H.z = RadicalInverse_VdC(i) + 0.01f;
H.Normalize();
H = normalize(H);
HemisphereVectors.push_back(H);
}
@ -172,9 +172,9 @@ void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size)
if (size > maxTasks)
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);
Vec4* startPositions = (Vec4*)imageData;
vec4* startPositions = (vec4*)imageData;
for (size_t i = 0; i < size; i++)
{
const TraceTask& task = tasks[i];
@ -182,19 +182,19 @@ void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size)
if (task.id >= 0)
{
Surface* surface = mesh->surfaces[task.id].get();
Vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
startPositions[i] = Vec4(pos, (float)task.id);
vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
startPositions[i] = vec4(pos, (float)task.id);
}
else
{
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++)
{
startPositions[i] = Vec4(0.0f, 0.0f, 0.0f, -1.0f);
startPositions[i] = vec4(0.0f, 0.0f, 0.0f, -1.0f);
}
imageTransferBuffer->Unmap();
@ -303,9 +303,9 @@ void GPURaytracer::DownloadTasks(const TraceTask* tasks, size_t size)
SubmitCommands();
size_t imageSize = sizeof(Vec4) * rayTraceImageSize * rayTraceImageSize;
size_t imageSize = sizeof(vec4) * rayTraceImageSize * rayTraceImageSize;
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++)
{
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();
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
{
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();
@ -370,7 +370,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
{
info.EmissiveDistance = 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);
}
@ -392,7 +392,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
if (lights.empty()) // vulkan doesn't support zero byte buffers
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 surfaceindexbuffersize = (size_t)mesh->MeshSurfaces.Size() * sizeof(uint32_t);
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 };
triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
triangles.vertexData.deviceAddress = vertexAddress;
triangles.vertexStride = sizeof(Vec3);
triangles.vertexStride = sizeof(vec3);
triangles.indexType = VK_INDEX_TYPE_UINT32;
triangles.indexData.deviceAddress = indexAddress;
triangles.maxVertex = mesh->MeshVertices.Size();
@ -823,7 +823,7 @@ void GPURaytracer::CreateDescriptorSet()
BufferBuilder itbuilder;
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->SetDebugName("imageTransferBuffer");
@ -910,9 +910,9 @@ void GPURaytracer::PrintVulkanInfo()
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)

View file

@ -12,19 +12,19 @@ struct Uniforms
uint32_t SampleCount;
uint32_t PassType;
uint32_t LightCount;
Vec3 SunDir;
vec3 SunDir;
float SampleDistance;
Vec3 SunColor;
vec3 SunColor;
float SunIntensity;
Vec3 HemisphereVec;
vec3 HemisphereVec;
float Padding1;
};
struct SurfaceInfo
{
Vec3 Normal;
vec3 Normal;
float EmissiveDistance;
Vec3 EmissiveColor;
vec3 EmissiveColor;
float EmissiveIntensity;
float Sky;
float Padding0, Padding1, Padding2;
@ -32,15 +32,15 @@ struct SurfaceInfo
struct LightInfo
{
Vec3 Origin;
vec3 Origin;
float Padding0;
float Radius;
float Intensity;
float InnerAngleCos;
float OuterAngleCos;
Vec3 SpotDir;
vec3 SpotDir;
float Padding1;
Vec3 Color;
vec3 Color;
float Padding2;
};
@ -79,7 +79,7 @@ private:
void PrintVulkanInfo();
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 bounceSampleCount = 2048;

View file

@ -120,11 +120,11 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
{
Plane* plane;
BBox bounds;
Vec3 roundedSize;
vec3 roundedSize;
int i;
Plane::PlaneAxis axis;
Vec3 tCoords[2];
Vec3 tOrigin;
vec3 tCoords[2];
vec3 tOrigin;
int width;
int height;
float d;
@ -141,8 +141,8 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
roundedSize[i] = (bounds.max[i] - bounds.min[i]) / samples + 1;
}
tCoords[0].Clear();
tCoords[1].Clear();
tCoords[0] = vec3(0.0f);
tCoords[1] = vec3(0.0f);
axis = plane->BestAxis();
@ -197,7 +197,7 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
for (i = 0; i < 2; i++)
{
tCoords[i].Normalize();
tCoords[i] = normalize(tCoords[i]);
d = plane->Distance(tCoords[i]) / plane->Normal()[axis];
tCoords[i][axis] -= d;
}
@ -217,8 +217,8 @@ void LevelMesh::BuildSurfaceParams(Surface* surface)
BBox LevelMesh::GetBoundsFromSurface(const Surface* surface)
{
Vec3 low(M_INFINITY, M_INFINITY, M_INFINITY);
Vec3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
vec3 low(M_INFINITY, M_INFINITY, M_INFINITY);
vec3 hi(-M_INFINITY, -M_INFINITY, -M_INFINITY);
BBox bounds;
bounds.Clear();
@ -256,11 +256,11 @@ void LevelMesh::FinishSurface(Surface* surface)
{
int sampleWidth = surface->lightmapDims[0];
int sampleHeight = surface->lightmapDims[1];
Vec3* colorSamples = surface->samples.data();
vec3* colorSamples = surface->samples.data();
if (!surface->indirect.empty())
{
Vec3* indirect = surface->indirect.data();
vec3* indirect = surface->indirect.data();
for (int i = 0; i < sampleHeight; i++)
{
for (int j = 0; j < sampleWidth; j++)
@ -298,9 +298,9 @@ void LevelMesh::FinishSurface(Surface* surface)
// calculate texture coordinates
for (int i = 0; i < surface->numVerts; i++)
{
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 + 1] = (tDelta.Dot(surface->textureCoords[1]) + y + 0.5f) / (float)textureHeight;
vec3 tDelta = surface->verts[i] - surface->bounds.min;
surface->lightmapCoords[i * 2 + 0] = (dot(tDelta, surface->textureCoords[0]) + x + 0.5f) / (float)textureWidth;
surface->lightmapCoords[i * 2 + 1] = (dot(tDelta, surface->textureCoords[1]) + y + 0.5f) / (float)textureHeight;
}
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 };
for (int y = 0; y < sampleHeight; y++)
{
Vec3* src = &colorSamples[y * sampleWidth];
vec3* src = &colorSamples[y * sampleWidth];
for (int x = 0; x < sampleWidth; x++)
{
// gaussian blur with a 3x3 kernel
Vec3 color = { 0.0f };
vec3 color = { 0.0f };
for (int yy = -1; yy <= 1; yy++)
{
int yyy = clamp(y + yy, 0, sampleHeight - 1) - y;
@ -407,9 +407,9 @@ void LevelMesh::CreateLightProbes(FLevel& map)
if (delta > doubleGridSize)
{
LightProbeSample p[3];
p[0].Position = Vec3(x, y, z0 + halfGridSize);
p[1].Position = Vec3(x, y, z0 + (z1 - z0) * 0.5f);
p[2].Position = Vec3(x, y, z1 - halfGridSize);
p[0].Position = vec3(x, y, z0 + halfGridSize);
p[1].Position = vec3(x, y, z0 + (z1 - z0) * 0.5f);
p[2].Position = vec3(x, y, z1 - halfGridSize);
for (int i = 0; i < 3; i++)
{
@ -462,8 +462,8 @@ void LevelMesh::CreateSideSurfaces(FLevel &doomMap, IntSideDef *side)
int typeIndex = side - &doomMap.Sides[0];
Vec2 dx(v2.x - v1.x, v2.y - v1.y);
float distance = std::sqrt(dx.Dot(dx));
vec2 dx(v2.x - v1.x, v2.y - v1.y);
float distance = length(dx);
if (back)
{
@ -785,7 +785,7 @@ void LevelMesh::CreateSubsectorSurfaces(FLevel &doomMap)
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.
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();
mtlfilename += "mtl";
TArray<Vec3> outvertices;
TArray<Vec2> outuv;
TArray<Vec3> outnormal;
TArray<vec3> outvertices;
TArray<vec2> outuv;
TArray<vec3> outnormal;
TArray<int> outface;
outvertices.Resize(MeshVertices.Size());
@ -947,7 +947,7 @@ void LevelMesh::Export(std::string filename)
int uvindex = MeshUVIndex[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();
outface.Push(vertexidx);

View file

@ -57,20 +57,20 @@ struct Surface
int lightmapNum;
int lightmapOffs[2];
int lightmapDims[2];
Vec3 lightmapOrigin;
Vec3 lightmapSteps[2];
Vec3 textureCoords[2];
vec3 lightmapOrigin;
vec3 lightmapSteps[2];
vec3 textureCoords[2];
BBox bounds;
int numVerts;
std::vector<Vec3> verts;
std::vector<vec3> verts;
std::vector<float> lightmapCoords;
std::vector<Vec3> samples;
std::vector<Vec3> indirect;
std::vector<vec3> samples;
std::vector<vec3> indirect;
SurfaceType type;
int typeIndex;
IntSector *controlSector;
bool bSky;
std::vector<Vec2> uvs;
std::vector<vec2> uvs;
std::string material;
};
@ -142,8 +142,8 @@ private:
class LightProbeSample
{
public:
Vec3 Position = Vec3(0.0f, 0.0f, 0.0f);
Vec3 Color = 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);
};
class LevelMesh
@ -166,7 +166,7 @@ public:
int textureWidth = 128;
int textureHeight = 128;
TArray<Vec3> MeshVertices;
TArray<vec3> MeshVertices;
TArray<int> MeshUVIndex;
TArray<unsigned int> MeshElements;
TArray<int> MeshSurfaces;
@ -183,5 +183,5 @@ private:
void FinishSurface(Surface* surface);
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);
};

View file

@ -45,7 +45,7 @@ Angle::Angle(const float yaw, const float pitch, const float roll)
this->roll = roll;
}
Angle::Angle(const Vec3 &vector)
Angle::Angle(const vec3 &vector)
{
this->yaw = vector.x;
this->pitch = vector.y;
@ -158,7 +158,7 @@ Angle Angle::Diff(Angle &angle)
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 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);
return vec;
}
Vec3 Angle::ToUpAxis()
vec3 Angle::ToUpAxis()
{
Vec3 vec;
vec3 vec;
ToAxis(nullptr, &vec, nullptr);
return vec;
}
Vec3 Angle::ToRightAxis()
vec3 Angle::ToRightAxis()
{
Vec3 vec;
vec3 vec;
ToAxis(nullptr, nullptr, &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);
}
Quat Angle::ToQuat()
{
return
(Quat(pitch, Vec3::vecRight) *
(Quat(yaw, Vec3::vecUp) *
Quat(roll, Vec3::vecForward)));
return *reinterpret_cast<vec3*>(&yaw);
}
Angle Angle::operator+(const Angle &angle)
@ -268,7 +260,7 @@ Angle &Angle::operator=(const Angle &angle)
return *this;
}
Angle &Angle::operator=(const Vec3 &vector)
Angle &Angle::operator=(const vec3 &vector)
{
yaw = vector.x;
pitch = vector.y;

View file

@ -34,7 +34,7 @@ BBox::BBox()
Clear();
}
BBox::BBox(const Vec3 &vMin, const Vec3 &vMax)
BBox::BBox(const vec3 &vMin, const vec3 &vMax)
{
this->min = vMin;
this->max = vMax;
@ -42,11 +42,11 @@ BBox::BBox(const Vec3 &vMin, const Vec3 &vMax)
void BBox::Clear()
{
min.Set(M_INFINITY, M_INFINITY, M_INFINITY);
max.Set(-M_INFINITY, -M_INFINITY, -M_INFINITY);
min = vec3(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 lowy = min.y;
@ -62,8 +62,8 @@ void BBox::AddPoint(const Vec3 &vec)
if (vec.y > hiy) { hiy = vec.y; }
if (vec.z > hiz) { hiz = vec.z; }
min.Set(lowx, lowy, lowz);
max.Set(hix, hiy, hiz);
min = vec3(lowx, lowy, lowz);
max = vec3(hix, hiy, hiz);
}
float BBox::Radius() const
@ -91,7 +91,7 @@ float BBox::Radius() const
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] ||
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)
{
Vec3 c;
vec3 c;
float distStart;
float distEnd;
float dist = 0;
@ -144,8 +144,8 @@ float BBox::DistanceToPlane(Plane &plane)
BBox BBox::operator+(const float radius) const
{
Vec3 vmin = min;
Vec3 vmax = max;
vec3 vmin = min;
vec3 vmax = max;
vmin.x -= radius;
vmin.y -= radius;
@ -169,10 +169,10 @@ BBox &BBox::operator+=(const float radius)
return *this;
}
BBox BBox::operator+(const Vec3 &vec) const
BBox BBox::operator+(const vec3 &vec) const
{
Vec3 vmin = min;
Vec3 vmax = max;
vec3 vmin = min;
vec3 vmax = max;
vmin.x += vec.x;
vmin.y += vec.y;
@ -187,8 +187,8 @@ BBox BBox::operator+(const Vec3 &vec) const
BBox BBox::operator-(const float radius) const
{
Vec3 vmin = min;
Vec3 vmax = max;
vec3 vmin = min;
vec3 vmax = max;
vmin.x += radius;
vmin.y += radius;
@ -201,10 +201,10 @@ BBox BBox::operator-(const float radius) const
return BBox(vmin, vmax);
}
BBox BBox::operator-(const Vec3 &vec) const
BBox BBox::operator-(const vec3 &vec) const
{
Vec3 vmin = min;
Vec3 vmax = max;
vec3 vmin = min;
vec3 vmax = max;
vmin.x -= vec.x;
vmin.y -= vec.y;
@ -228,51 +228,7 @@ BBox &BBox::operator-=(const float radius)
return *this;
}
BBox BBox::operator*(const Mat4 &matrix) 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 BBox::operator*(const vec3 &vec) const
{
BBox box = *this;
@ -286,7 +242,7 @@ BBox BBox::operator*(const Vec3 &vec) const
return box;
}
BBox &BBox::operator*=(const Vec3 &vec)
BBox &BBox::operator*=(const vec3 &vec)
{
if (vec.x < 0) { min.x += (vec.x - 1); }
else { max.x += (vec.x + 1); }
@ -306,26 +262,26 @@ BBox &BBox::operator=(const BBox &bbox)
return *this;
}
Vec3 BBox::operator[](int index) const
vec3 BBox::operator[](int index) const
{
assert(index >= 0 && index < 2);
return index == 0 ? min : max;
}
Vec3 &BBox::operator[](int index)
vec3 &BBox::operator[](int index)
{
assert(index >= 0 && index < 2);
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];
Vec3 center = Center();
Vec3 extents = max - center;
Vec3 lineDir = (end - start) * 0.5f;
Vec3 lineCenter = lineDir + start;
Vec3 dir = lineCenter - center;
vec3 center = Center();
vec3 extents = max - center;
vec3 lineDir = (end - start) * 0.5f;
vec3 lineCenter = lineDir + start;
vec3 dir = lineCenter - center;
ld[0] = Math::Fabs(lineDir.x);
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);
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(cross.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.x) > extents.y * ld[2] + extents.z * ld[1]) { return false; }
if (Math::Fabs(crossprod.y) > extents.x * ld[2] + extents.z * ld[0]) { return false; }
if (Math::Fabs(crossprod.z) > extents.x * ld[1] + extents.y * ld[0]) { return false; }
return true;
}
@ -373,7 +329,7 @@ void BBox::ToPoints(float *points) const
}
// 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][1] = min[1];

336
src/math/mat.cpp Normal file
View 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
View 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];
};

View file

@ -44,7 +44,7 @@ int Math::RoundPowerOfTwo(int 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;
float xyz[3];
@ -60,7 +60,7 @@ void Math::CubicCurve(const Vec3 &start, const Vec3 &end, const float time, cons
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;
float xyz[3];

File diff suppressed because it is too large Load diff

View file

@ -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;
}

View file

@ -44,18 +44,18 @@ Plane::Plane(const float a, const float b, const float c, const float 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);
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->b = normal.y;
this->c = normal.z;
this->d = point.Dot(normal);
this->d = dot(point, normal);
}
Plane::Plane(const Plane &plane)
@ -66,36 +66,36 @@ Plane::Plane(const Plane &plane)
this->d = plane.d;
}
Plane &Plane::SetNormal(const Vec3 &normal)
Plane &Plane::SetNormal(const vec3 &normal)
{
Normal() = normal;
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;
}
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;
}
@ -106,7 +106,7 @@ bool Plane::IsFacing(const float yaw)
float Plane::ToYaw()
{
float d = Normal().Unit();
float d = length(Normal());
if (d != 0)
{
@ -125,23 +125,17 @@ float Plane::ToYaw()
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 Quat(Math::ACos(Vec3::vecUp.Dot(Normal())), cross);
return *reinterpret_cast<const vec4*>(&a);
}
Vec4 const &Plane::ToVec4() const
vec4 &Plane::ToVec4()
{
return *reinterpret_cast<const Vec4*>(&a);
}
Vec4 &Plane::ToVec4()
{
return *reinterpret_cast<Vec4*>(&a);
return *reinterpret_cast<vec4*>(&a);
}
const Plane::PlaneAxis Plane::BestAxis() const
@ -163,8 +157,8 @@ const Plane::PlaneAxis Plane::BestAxis() const
return AXIS_XY;
}
Vec3 Plane::GetInclination()
vec3 Plane::GetInclination()
{
Vec3 dir = Normal() * Vec3::vecUp.Dot(Normal());
return (Vec3::vecUp - dir).Normalize();
vec3 dir = Normal() * dot(vec3(0.0f, 0.0f, 1.0f), Normal());
return normalize(vec3(0.0f, 0.0f, 1.0f) - dir);
}

View file

@ -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
View 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
View 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); }

View file

@ -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);

View file

@ -3,6 +3,7 @@
#include "framework/tarray.h"
#include "framework/templates.h"
#include "framework/zstring.h"
#include "math/mathlib.h"
#include <stdint.h>
#include <string>
#include <memory>

View file

@ -73,9 +73,9 @@ private:
OBJSurface(FTextureID skin): numTris(0), numFaces(0), vbStart(0), faceStart(0), tris(nullptr), skin(skin) {}
};
TArray<Vec3> verts;
TArray<Vec3> norms;
TArray<Vec2> uvs;
TArray<vec3> verts;
TArray<vec3> norms;
TArray<vec2> uvs;
TArray<OBJFace> faces;
TArray<OBJSurface> surfaces;
FScanner sc;
@ -87,11 +87,11 @@ private:
void ConstructSurfaceTris(OBJSurface &surf);
void AddVertFaces();
void TriangulateQuad(const OBJFace &quad, OBJFace *tris);
Vec3 RealignVector(Vec3 vecToRealign);
Vec2 FixUV(Vec2 vecToRealign);
Vec3 CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx);
Vec3 CalculateNormalFlat(OBJTriRef otr);
Vec3 CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup);
vec3 RealignVector(vec3 vecToRealign);
vec2 FixUV(vec2 vecToRealign);
vec3 CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx);
vec3 CalculateNormalFlat(OBJTriRef otr);
vec3 CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup);
public:
FOBJModel(): hasMissingNormals(false), hasSmoothGroups(false), vertFaces(nullptr) {}
~FOBJModel();

View file

@ -85,15 +85,15 @@ private:
// converted data structures
struct UE1Vertex
{
Vec3 Pos, Normal;
vec3 Pos, Normal;
TArray<int> P; // polys that reference this vertex, used in normal computation to save time
int nP; // count of those polys
};
struct UE1Poly
{
int V[3];
Vec2 C[3];
TArray<Vec3> Normals;
vec2 C[3];
TArray<vec3> Normals;
};
struct UE1Group
{

View file

@ -111,15 +111,15 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
{
if (sc.Compare("v")) // Vertex
{
ParseVector<Vec3, 3>(this->verts);
ParseVector<vec3, 3>(this->verts);
}
else if (sc.Compare("vn")) // Vertex normal
{
ParseVector<Vec3, 3>(this->norms);
ParseVector<vec3, 3>(this->norms);
}
else if (sc.Compare("vt")) // UV Coordinates
{
ParseVector<Vec2, 2>(this->uvs);
ParseVector<vec2, 2>(this->uvs);
}
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)
{ // Needed so that OBJs without UVs can work
uvs.Push(Vec2(0.0, 0.0));
uvs.Push(vec2(0.0, 0.0));
}
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 nidx = curSide.normref;
Vec3 curVvec = RealignVector(verts[vidx]);
Vec2 curUvec = FixUV(uvs[uvidx]);
Vec3 nvec;
vec3 curVvec = RealignVector(verts[vidx]);
vec2 curUvec = FixUV(uvs[uvidx]);
vec3 nvec;
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
* @return The re-aligned vector
*/
inline Vec3 FOBJModel::RealignVector(Vec3 vecToRealign)
inline vec3 FOBJModel::RealignVector(vec3 vecToRealign)
{
vecToRealign.z *= -1;
return vecToRealign;
@ -538,7 +538,7 @@ inline Vec3 FOBJModel::RealignVector(Vec3 vecToRealign)
* @param vecToRealign The vector to fix
* @return The fixed UV coordinate vector
*/
inline Vec2 FOBJModel::FixUV(Vec2 vecToRealign)
inline vec2 FOBJModel::FixUV(vec2 vecToRealign)
{
vecToRealign.y *= -1;
return vecToRealign;
@ -551,7 +551,7 @@ inline Vec2 FOBJModel::FixUV(Vec2 vecToRealign)
* @param triIdx The triangle Index
* @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
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;
// Cross-multiply the U-vector and V-vector
Vec3 curVvec = RealignVector(verts[curVert]);
Vec3 uvec = RealignVector(verts[nextVert]) - curVvec;
Vec3 vvec = RealignVector(verts[lastVert]) - curVvec;
vec3 curVvec = RealignVector(verts[curVert]);
vec3 uvec = RealignVector(verts[nextVert]) - curVvec;
vec3 vvec = RealignVector(verts[lastVert]) - curVvec;
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
* @return The surface normal vector
*/
Vec3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
vec3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
{
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 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;
TArray<OBJTriRef>& vTris = vertFaces[vidx];
Vec3 vNormal(0,0,0);
vec3 vNormal(0,0,0);
for (size_t face = 0; face < vTris.Size(); face++)
{
OBJFace& tri = surfaces[vTris[face].surf].tris[vTris[face].tri];
if (tri.smoothGroup == smoothGroup)
{
Vec3 fNormal = CalculateNormalFlat(vTris[face]);
vec3 fNormal = CalculateNormalFlat(vTris[face]);
connectedFaces += 1;
vNormal += fNormal;
}

View file

@ -96,14 +96,14 @@ void FUE1Model::LoadGeometry()
if ( dxverts != NULL )
{
// convert padded XYZ16
Vert.Pos = Vec3(dxverts[j+i*numVerts].x,
Vert.Pos = vec3(dxverts[j+i*numVerts].x,
dxverts[j+i*numVerts].z,
(float)-dxverts[j+i*numVerts].y);
}
else
{
// 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],1));
}
@ -123,14 +123,14 @@ void FUE1Model::LoadGeometry()
Poly.V[j] = dpolys[i].vertices[j];
// unpack coords
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
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[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
for ( int k=0; k<3; k++ )
{
@ -148,10 +148,10 @@ void FUE1Model::LoadGeometry()
{
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++ )
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)
@ -281,7 +281,7 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
for ( int l=0; l<3; l++ )
{
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++];
vert->Set(V.Pos.x,V.Pos.y,V.Pos.z,C.x,C.y);
if ( groups[j].type&PT_Curvy ) // use facet normal