Initial commit of current work on Prime World Editor
|
@ -0,0 +1,34 @@
|
|||
# C++ objects and libs
|
||||
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.a
|
||||
*.la
|
||||
*.lai
|
||||
*.so
|
||||
*.dll
|
||||
*.dylib
|
||||
|
||||
# Qt-es
|
||||
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
*.pro.user
|
||||
*.pro.user.*
|
||||
*.qbs.user
|
||||
*.qbs.user.*
|
||||
*.moc
|
||||
moc_*.cpp
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
Makefile*
|
||||
*-build-*
|
||||
|
||||
# QtCreator
|
||||
|
||||
*.autosave
|
||||
|
||||
#QtCtreator Qml
|
||||
*.qmlproject.user
|
||||
*.qmlproject.user.*
|
|
@ -0,0 +1,10 @@
|
|||
#include "CTimer.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace AnimUtil
|
||||
{
|
||||
float SecondsMod900()
|
||||
{
|
||||
return fmod((float) CTimer::GlobalTime(), 900.f);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef ANIMUTIL_H
|
||||
#define ANIMUTIL_H
|
||||
|
||||
namespace AnimUtil
|
||||
{
|
||||
float SecondsMod900();
|
||||
}
|
||||
|
||||
#endif // ANIMUTIL_H
|
|
@ -0,0 +1,158 @@
|
|||
#include "CAABox.h"
|
||||
#include <Common/CTransform4f.h>
|
||||
#include <Common/Math.h>
|
||||
#include "CRay.h"
|
||||
#include "SRayIntersection.h"
|
||||
#include <float.h>
|
||||
|
||||
CAABox::CAABox()
|
||||
{
|
||||
mMin = CVector3f::skInfinite;
|
||||
mMax = -CVector3f::skInfinite;
|
||||
}
|
||||
|
||||
CAABox::CAABox(const CVector3f& Min, const CVector3f& Max)
|
||||
{
|
||||
mMin = Min;
|
||||
mMax = Max;
|
||||
}
|
||||
|
||||
CAABox::CAABox(CInputStream& input)
|
||||
{
|
||||
mMin = CVector3f(input);
|
||||
mMax = CVector3f(input);
|
||||
}
|
||||
|
||||
void CAABox::Write(COutputStream& Output)
|
||||
{
|
||||
mMin.Write(Output);
|
||||
mMax.Write(Output);
|
||||
}
|
||||
|
||||
CVector3f CAABox::Center() const
|
||||
{
|
||||
return (mMax - ((mMax - mMin) * 0.5f));
|
||||
}
|
||||
|
||||
CVector3f CAABox::GetSize() const
|
||||
{
|
||||
return (mMax - mMin);
|
||||
}
|
||||
|
||||
CVector3f CAABox::Min() const
|
||||
{
|
||||
return mMin;
|
||||
}
|
||||
|
||||
CVector3f CAABox::Max() const
|
||||
{
|
||||
return mMax;
|
||||
}
|
||||
|
||||
bool CAABox::IsNull() const
|
||||
{
|
||||
return (GetSize() == CVector3f::skZero);
|
||||
}
|
||||
|
||||
bool CAABox::IsInfinite() const
|
||||
{
|
||||
return (GetSize() == CVector3f::skInfinite);
|
||||
}
|
||||
|
||||
void CAABox::ExpandBounds(const CVector3f& vtx)
|
||||
{
|
||||
// take an input vertex coordinate and expand the bounding box to fit it, if necessary
|
||||
if (vtx.x < mMin.x) mMin.x = vtx.x;
|
||||
if (vtx.x > mMax.x) mMax.x = vtx.x;
|
||||
if (vtx.y < mMin.y) mMin.y = vtx.y;
|
||||
if (vtx.y > mMax.y) mMax.y = vtx.y;
|
||||
if (vtx.z < mMin.z) mMin.z = vtx.z;
|
||||
if (vtx.z > mMax.z) mMax.z = vtx.z;
|
||||
}
|
||||
|
||||
void CAABox::ExpandBounds(const CAABox& AABox)
|
||||
{
|
||||
ExpandBounds(AABox.mMin);
|
||||
ExpandBounds(AABox.mMax);
|
||||
}
|
||||
|
||||
CAABox CAABox::Transformed(const CTransform4f& transform) const
|
||||
{
|
||||
CAABox AABox;
|
||||
|
||||
AABox.ExpandBounds(transform * CVector3f(mMin.x, mMin.y, mMin.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMin.x, mMin.y, mMax.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMin.x, mMax.y, mMax.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMin.x, mMax.y, mMin.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMax.x, mMin.y, mMin.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMax.x, mMin.y, mMax.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMax.x, mMax.y, mMax.z));
|
||||
AABox.ExpandBounds(transform * CVector3f(mMax.x, mMax.y, mMin.z));
|
||||
|
||||
return AABox;
|
||||
}
|
||||
|
||||
bool CAABox::IsPointInBox(const CVector3f& Point) const
|
||||
{
|
||||
return ( ((Point.x >= mMin.x) && (Point.x <= mMax.x)) &&
|
||||
((Point.y >= mMin.y) && (Point.y <= mMax.y)) &&
|
||||
((Point.z >= mMin.z) && (Point.z <= mMax.z)) );
|
||||
}
|
||||
|
||||
CVector3f CAABox::ClosestPointAlongVector(const CVector3f& dir) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = (dir.x >= 0.f) ? mMin.x : mMax.x;
|
||||
out.y = (dir.y >= 0.f) ? mMin.y : mMax.y;
|
||||
out.z = (dir.z >= 0.f) ? mMin.z : mMax.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CAABox::FurthestPointAlongVector(const CVector3f& dir) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = (dir.x >= 0.f) ? mMax.x : mMin.x;
|
||||
out.y = (dir.y >= 0.f) ? mMax.y : mMin.y;
|
||||
out.z = (dir.z >= 0.f) ? mMax.z : mMin.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
// ************ INTERSECTION TESTS ************
|
||||
// These tests are kinda bad and probably inaccurate, they need rewrites
|
||||
bool CAABox::IntersectsAABox(const CAABox& AABox)
|
||||
{
|
||||
return ((mMax > AABox.mMin) && (mMin < AABox.mMax));
|
||||
}
|
||||
|
||||
bool CAABox::IntersectsSphere(const CVector3f& SphereCenter, const float SphereRadius)
|
||||
{
|
||||
// Placeholder for proper sphere intersection test
|
||||
// Generate an AABox for the sphere and do an AABox/AABox intersection test instead
|
||||
return IntersectsAABox(CAABox(SphereCenter - SphereRadius, SphereCenter + SphereRadius));
|
||||
}
|
||||
|
||||
std::pair<bool,float> CAABox::IntersectsRay(const CRay &Ray) const
|
||||
{
|
||||
return Math::RayBoxIntersection(Ray, *this);
|
||||
}
|
||||
|
||||
bool CAABox::operator==(const CAABox& Other)
|
||||
{
|
||||
return ((mMin == Other.mMin) && (mMax == Other.mMax));
|
||||
}
|
||||
|
||||
bool CAABox::operator!=(const CAABox& Other)
|
||||
{
|
||||
return (!(*this == Other));
|
||||
}
|
||||
|
||||
// ************ CONSTANTS ************
|
||||
|
||||
// min set to float maximum, max set to float minimum; ideal for creating an AABox from scratch
|
||||
const CAABox CAABox::skInfinite = CAABox(CVector3f(FLT_MAX), CVector3f(-FLT_MAX));
|
||||
|
||||
// a 1x1x1 bounding box
|
||||
const CAABox CAABox::skOne = CAABox( CVector3f(-0.5f, -0.5f, -0.5f), CVector3f(0.5f, 0.5f, 0.5f) );
|
||||
|
||||
// a 0x0x0 bounding box
|
||||
const CAABox CAABox::skZero = CAABox(CVector3f(0), CVector3f(0));
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef CAABOX_H
|
||||
#define CAABOX_H
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
#include "CVector3f.h"
|
||||
#include <utility>
|
||||
|
||||
class CRay;
|
||||
class CRayIntersection;
|
||||
|
||||
class CAABox
|
||||
{
|
||||
CVector3f mMin, mMax;
|
||||
|
||||
public:
|
||||
CAABox();
|
||||
CAABox(const CVector3f& Min, const CVector3f& Max);
|
||||
CAABox(CInputStream& input);
|
||||
void Write(COutputStream& Output);
|
||||
CVector3f Center() const;
|
||||
CVector3f GetSize() const;
|
||||
CVector3f Min() const;
|
||||
CVector3f Max() const;
|
||||
bool IsNull() const;
|
||||
bool IsInfinite() const;
|
||||
|
||||
void ExpandBounds(const CVector3f& vtx);
|
||||
void ExpandBounds(const CAABox& AABox);
|
||||
CAABox Transformed(const CTransform4f& transform) const;
|
||||
|
||||
bool IsPointInBox(const CVector3f& Point) const;
|
||||
CVector3f ClosestPointAlongVector(const CVector3f& dir) const;
|
||||
CVector3f FurthestPointAlongVector(const CVector3f& dir) const;
|
||||
|
||||
// Intersection Tests
|
||||
bool IntersectsAABox(const CAABox& AABox);
|
||||
bool IntersectsSphere(const CVector3f& SphereCenter, const float SphereRadius);
|
||||
std::pair<bool,float> IntersectsRay(const CRay& Ray) const;
|
||||
|
||||
// Operators
|
||||
bool operator==(const CAABox& Other);
|
||||
bool operator!=(const CAABox& Other);
|
||||
|
||||
// Constants
|
||||
static const CAABox skInfinite;
|
||||
static const CAABox skOne;
|
||||
static const CAABox skZero;
|
||||
};
|
||||
|
||||
#endif // CAABOX_H
|
|
@ -0,0 +1,183 @@
|
|||
#include "CColor.h"
|
||||
|
||||
CColor::CColor()
|
||||
{
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
CColor::CColor(CInputStream& src)
|
||||
{
|
||||
src.ReadBytes(&r, 4);
|
||||
}
|
||||
|
||||
CColor::CColor(u32 rgba)
|
||||
{
|
||||
r = (rgba >> 24) & 0xFF;
|
||||
g = (rgba >> 16) & 0xFF;
|
||||
b = (rgba >> 8) & 0xFF;
|
||||
a = rgba & 0xFF;
|
||||
}
|
||||
|
||||
CColor::CColor(u8 rgba)
|
||||
{
|
||||
r = g = b = a = rgba;
|
||||
}
|
||||
|
||||
CColor::CColor(u8 _r, u8 _g, u8 _b, u8 _a)
|
||||
{
|
||||
r = _r;
|
||||
g = _g;
|
||||
b = _b;
|
||||
a = _a;
|
||||
}
|
||||
|
||||
CColor::CColor(float rgba)
|
||||
{
|
||||
r = g = b = a = u8(rgba * 255.f);
|
||||
}
|
||||
|
||||
CColor::CColor(float _r, float _g, float _b, float _a)
|
||||
{
|
||||
r = u8(_r * 255.f);
|
||||
g = u8(_g * 255.f);
|
||||
b = u8(_b * 255.f);
|
||||
a = u8(_a * 255.f);
|
||||
}
|
||||
|
||||
void CColor::Write(COutputStream &Output)
|
||||
{
|
||||
Output.WriteBytes(&r, 4);
|
||||
}
|
||||
|
||||
long CColor::AsLongRGBA() const
|
||||
{
|
||||
return (r << 24) | (g << 16) | (b << 8) | a;
|
||||
}
|
||||
|
||||
long CColor::ToLongARGB() const
|
||||
{
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
CVector4f CColor::ToVector4f() const
|
||||
{
|
||||
return CVector4f(float(r) / 255.f,
|
||||
float(g) / 255.f,
|
||||
float(b) / 255.f,
|
||||
float(a) / 255.f);
|
||||
}
|
||||
|
||||
bool CColor::operator==(const CColor& other) const
|
||||
{
|
||||
return ((r == other.r) &&
|
||||
(g == other.g) &&
|
||||
(b == other.b) &&
|
||||
(a == other.a));
|
||||
}
|
||||
|
||||
bool CColor::operator!=(const CColor& other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
CColor CColor::operator+(const CColor& other) const
|
||||
{
|
||||
u16 NewR = r + other.r;
|
||||
if (NewR > 255) NewR = 255;
|
||||
u16 NewG = g + other.g;
|
||||
if (NewG > 255) NewG = 255;
|
||||
u16 NewB = b + other.b;
|
||||
if (NewB > 255) NewB = 255;
|
||||
u16 NewA = a + other.a;
|
||||
if (NewA > 255) NewA = 255;
|
||||
return CColor((u8) NewR, (u8) NewG, (u8) NewB, (u8) NewA);
|
||||
}
|
||||
|
||||
void CColor::operator+=(const CColor& other)
|
||||
{
|
||||
*this = (*this + other);
|
||||
}
|
||||
|
||||
CColor CColor::operator-(const CColor& other) const
|
||||
{
|
||||
s16 NewR = r - other.r;
|
||||
if (NewR < 0) NewR = 0;
|
||||
s16 NewG = g - other.g;
|
||||
if (NewG < 0) NewG = 0;
|
||||
s16 NewB = b - other.b;
|
||||
if (NewB < 0) NewB = 0;
|
||||
s16 NewA = a - other.a;
|
||||
if (NewA < 0) NewA = 0;
|
||||
return CColor((u8) NewR, (u8) NewG, (u8) NewB, (u8) NewA);
|
||||
}
|
||||
|
||||
void CColor::operator-=(const CColor& other)
|
||||
{
|
||||
*this = (*this - other);
|
||||
}
|
||||
|
||||
CColor CColor::operator*(const CColor& other) const
|
||||
{
|
||||
u16 NewR = r * other.r;
|
||||
if (NewR > 255) NewR = 255;
|
||||
u16 NewG = g * other.g;
|
||||
if (NewG > 255) NewG = 255;
|
||||
u16 NewB = b * other.b;
|
||||
if (NewB > 255) NewB = 255;
|
||||
u16 NewA = a * other.a;
|
||||
if (NewA > 255) NewA = 255;
|
||||
return CColor((u8) NewR, (u8) NewG, (u8) NewB, (u8) NewA);
|
||||
}
|
||||
|
||||
void CColor::operator*=(const CColor& other)
|
||||
{
|
||||
*this = (*this - other);
|
||||
}
|
||||
|
||||
CColor CColor::operator*(const float other) const
|
||||
{
|
||||
u8 NewR = (u8) (r * other);
|
||||
u8 NewG = (u8) (g * other);
|
||||
u8 NewB = (u8) (b * other);
|
||||
u8 NewA = (u8) (a * other);
|
||||
return CColor(NewR, NewG, NewB, NewA);
|
||||
}
|
||||
|
||||
void CColor::operator*=(const float other)
|
||||
{
|
||||
*this = (*this * other);
|
||||
}
|
||||
|
||||
CColor CColor::operator/(const CColor& other) const
|
||||
{
|
||||
u16 NewR = (other.r == 0) ? 0 : r / other.r;
|
||||
u16 NewG = (other.g == 0) ? 0 : g / other.g;
|
||||
u16 NewB = (other.b == 0) ? 0 : b / other.b;
|
||||
u16 NewA = (other.a == 0) ? 0 : a / other.a;
|
||||
return CColor((u8) NewR, (u8) NewG, (u8) NewB, (u8) NewA);
|
||||
}
|
||||
|
||||
void CColor::operator/=(const CColor& other)
|
||||
{
|
||||
*this = (*this / other);
|
||||
}
|
||||
|
||||
// defining predefined colors
|
||||
const CColor CColor::skRed (u32(0xFF0000FF));
|
||||
const CColor CColor::skGreen (u32(0x00FF00FF));
|
||||
const CColor CColor::skBlue (u32(0x0000FFFF));
|
||||
const CColor CColor::skYellow(u32(0xFFFF00FF));
|
||||
const CColor CColor::skPurple(u32(0xFF00FFFF));
|
||||
const CColor CColor::skCyan (u32(0x00FFFFFF));
|
||||
const CColor CColor::skWhite (u32(0xFFFFFFFF));
|
||||
const CColor CColor::skBlack (u32(0x000000FF));
|
||||
const CColor CColor::skGray (u32(0x808080FF));
|
||||
const CColor CColor::skTransparentRed (u32(0xFF000000));
|
||||
const CColor CColor::skTransparentGreen (u32(0x00FF0000));
|
||||
const CColor CColor::skTransparentBlue (u32(0x0000FF00));
|
||||
const CColor CColor::skTransparentYellow(u32(0xFFFF0000));
|
||||
const CColor CColor::skTransparentPurple(u32(0xFF00FF00));
|
||||
const CColor CColor::skTransparentCyan (u32(0x00FFFF00));
|
||||
const CColor CColor::skTransparentWhite (u32(0xFFFFFF00));
|
||||
const CColor CColor::skTransparentBlack (u32(0x00000000));
|
||||
const CColor CColor::skTransparentGray (u32(0x80808000));
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef CCOLOR_H
|
||||
#define CCOLOR_H
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
#include "CVector4f.h"
|
||||
#include "types.h"
|
||||
|
||||
class CColor
|
||||
{
|
||||
public:
|
||||
u8 r, g, b, a;
|
||||
|
||||
CColor();
|
||||
CColor(CInputStream& src);
|
||||
CColor(u32 rgba);
|
||||
CColor(u8 rgba);
|
||||
CColor(u8 _r, u8 _g, u8 _b, u8 _a);
|
||||
CColor(float rgba);
|
||||
CColor(float _r, float _g, float _b, float _a);
|
||||
void Write(COutputStream& Output);
|
||||
|
||||
long AsLongRGBA() const;
|
||||
long ToLongARGB() const;
|
||||
CVector4f ToVector4f() const;
|
||||
bool operator==(const CColor& other) const;
|
||||
bool operator!=(const CColor& other) const;
|
||||
CColor operator+(const CColor& other) const;
|
||||
void operator+=(const CColor& other);
|
||||
CColor operator-(const CColor& other) const;
|
||||
void operator-=(const CColor& other);
|
||||
CColor operator*(const CColor& other) const;
|
||||
void operator*=(const CColor& other);
|
||||
CColor operator*(const float other) const;
|
||||
void operator*=(const float other);
|
||||
CColor operator/(const CColor& other) const;
|
||||
void operator/=(const CColor& other);
|
||||
|
||||
// some predefined colors below for ease of use
|
||||
static const CColor skRed;
|
||||
static const CColor skGreen;
|
||||
static const CColor skBlue;
|
||||
static const CColor skYellow;
|
||||
static const CColor skPurple;
|
||||
static const CColor skCyan;
|
||||
static const CColor skWhite;
|
||||
static const CColor skBlack;
|
||||
static const CColor skGray;
|
||||
static const CColor skTransparentRed;
|
||||
static const CColor skTransparentGreen;
|
||||
static const CColor skTransparentBlue;
|
||||
static const CColor skTransparentYellow;
|
||||
static const CColor skTransparentPurple;
|
||||
static const CColor skTransparentCyan;
|
||||
static const CColor skTransparentWhite;
|
||||
static const CColor skTransparentBlack;
|
||||
static const CColor skTransparentGray;
|
||||
};
|
||||
|
||||
#endif // CCOLOR_H
|
|
@ -0,0 +1,111 @@
|
|||
#include "CFourCC.h"
|
||||
|
||||
CFourCC::CFourCC()
|
||||
{
|
||||
FourCC[0] = 0;
|
||||
FourCC[1] = 0;
|
||||
FourCC[2] = 0;
|
||||
FourCC[3] = 0;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(const char *src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(const std::string& src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(long src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(CInputStream& src)
|
||||
{
|
||||
src.ReadBytes(&FourCC[0], 4);
|
||||
}
|
||||
|
||||
void CFourCC::Write(COutputStream &Output)
|
||||
{
|
||||
Output.WriteBytes(FourCC, 4);
|
||||
}
|
||||
|
||||
CFourCC& CFourCC::operator=(const char *src)
|
||||
{
|
||||
|
||||
memcpy(&FourCC[0], src, 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFourCC& CFourCC::operator=(const std::string& src)
|
||||
{
|
||||
memcpy(&FourCC[0], src.c_str(), 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFourCC& CFourCC::operator=(long src)
|
||||
{
|
||||
FourCC[0] = (src >> 24) & 0xFF;
|
||||
FourCC[1] = (src >> 16) & 0xFF;
|
||||
FourCC[2] = (src >> 8) & 0xFF;
|
||||
FourCC[3] = (src >> 0) & 0xFF;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CFourCC::operator==(const CFourCC& other) const
|
||||
{
|
||||
return ((FourCC[0] == other.FourCC[0]) && (FourCC[1] == other.FourCC[1]) && (FourCC[2] == other.FourCC[2]) && (FourCC[3] == other.FourCC[3]));
|
||||
}
|
||||
|
||||
bool CFourCC::operator!=(const CFourCC& other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
bool CFourCC::operator==(const char *other) const
|
||||
{
|
||||
return (*this == CFourCC(other));
|
||||
}
|
||||
|
||||
bool CFourCC::operator!=(const char *other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
bool CFourCC::operator==(const long other) const
|
||||
{
|
||||
return (*this == CFourCC(other));
|
||||
}
|
||||
|
||||
bool CFourCC::operator!=(const long other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
long CFourCC::ToLong() const
|
||||
{
|
||||
return FourCC[0] << 24 | FourCC[1] << 16 | FourCC[2] << 8 | FourCC[3];
|
||||
}
|
||||
|
||||
std::string CFourCC::ToString() const
|
||||
{
|
||||
return std::string(FourCC, 4);
|
||||
}
|
||||
|
||||
CFourCC CFourCC::ToUpper() const
|
||||
{
|
||||
CFourCC Out;
|
||||
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
if ((FourCC[c] >= 0x61) && (FourCC[c] <= 0x7A))
|
||||
Out.FourCC[c] = FourCC[c] - 0x20;
|
||||
else
|
||||
Out.FourCC[c] = FourCC[c];
|
||||
}
|
||||
|
||||
return Out;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef CFOURCC_H
|
||||
#define CFOURCC_H
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
#include <string>
|
||||
|
||||
class CFourCC
|
||||
{
|
||||
char FourCC[4];
|
||||
public:
|
||||
CFourCC();
|
||||
CFourCC(const char *src);
|
||||
CFourCC(const std::string& src);
|
||||
CFourCC(long src);
|
||||
CFourCC(CInputStream& src);
|
||||
void Write(COutputStream& Output);
|
||||
|
||||
CFourCC& operator=(const char *src);
|
||||
CFourCC& operator=(const std::string& src);
|
||||
CFourCC& operator=(long src);
|
||||
bool operator==(const CFourCC& other) const;
|
||||
bool operator!=(const CFourCC& other) const;
|
||||
bool operator==(const char *other) const;
|
||||
bool operator!=(const char *other) const;
|
||||
bool operator==(const long other) const;
|
||||
bool operator!=(const long other) const;
|
||||
|
||||
long ToLong() const;
|
||||
std::string ToString() const;
|
||||
CFourCC ToUpper() const;
|
||||
};
|
||||
|
||||
#endif // CFOURCC_H
|
|
@ -0,0 +1,72 @@
|
|||
#include "CHashFNV1A.h"
|
||||
|
||||
const u64 CHashFNV1A::skFNVOffsetBasis32 = 0x811C9DC5;
|
||||
const u64 CHashFNV1A::skFNVOffsetBasis64 = 0xCBF29CE484222325;
|
||||
const u64 CHashFNV1A::skFNVPrime32 = 0x1000193;
|
||||
const u64 CHashFNV1A::skFNVPrime64 = 0x100000001B3;
|
||||
|
||||
CHashFNV1A::CHashFNV1A()
|
||||
{
|
||||
Init32();
|
||||
}
|
||||
|
||||
void CHashFNV1A::Init32()
|
||||
{
|
||||
mHashLength = e32Bit;
|
||||
mHash = skFNVOffsetBasis32;
|
||||
}
|
||||
|
||||
void CHashFNV1A::Init64()
|
||||
{
|
||||
mHashLength = e64Bit;
|
||||
mHash = skFNVOffsetBasis64;
|
||||
}
|
||||
|
||||
void CHashFNV1A::HashData(const void *pData, u32 Size)
|
||||
{
|
||||
const char *pCharData = (const char*) pData;
|
||||
u64 FNVPrime = (mHashLength == e32Bit) ? skFNVPrime32 : skFNVPrime64;
|
||||
|
||||
for (u32 i = 0; i < Size; i++)
|
||||
{
|
||||
mHash ^= *pCharData;
|
||||
mHash *= FNVPrime;
|
||||
pCharData++;
|
||||
}
|
||||
}
|
||||
|
||||
u32 CHashFNV1A::GetHash32()
|
||||
{
|
||||
return (u32) mHash;
|
||||
}
|
||||
|
||||
u64 CHashFNV1A::GetHash64()
|
||||
{
|
||||
return mHash;
|
||||
}
|
||||
|
||||
// ************ CONVENIENCE FUNCTIONS ************
|
||||
void CHashFNV1A::HashByte(const u8& v)
|
||||
{
|
||||
HashData(&v, 1);
|
||||
}
|
||||
|
||||
void CHashFNV1A::HashShort(const u16& v)
|
||||
{
|
||||
HashData(&v, 2);
|
||||
}
|
||||
|
||||
void CHashFNV1A::HashLong(const u32& v)
|
||||
{
|
||||
HashData(&v, 4);
|
||||
}
|
||||
|
||||
void CHashFNV1A::HashFloat(const float& v)
|
||||
{
|
||||
HashData(&v, 4);
|
||||
}
|
||||
|
||||
void CHashFNV1A::HashString(const std::string& v)
|
||||
{
|
||||
HashData(v.data(), v.size());
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef CHASHFNV1A_H
|
||||
#define CHASHFNV1A_H
|
||||
|
||||
#include "types.h"
|
||||
#include <string>
|
||||
|
||||
class CHashFNV1A
|
||||
{
|
||||
u64 mHash;
|
||||
|
||||
enum EHashLength {
|
||||
e32Bit, e64Bit
|
||||
} mHashLength;
|
||||
|
||||
static const u64 skFNVOffsetBasis32;
|
||||
static const u64 skFNVOffsetBasis64;
|
||||
static const u64 skFNVPrime32;
|
||||
static const u64 skFNVPrime64;
|
||||
|
||||
public:
|
||||
CHashFNV1A();
|
||||
void Init32();
|
||||
void Init64();
|
||||
void HashData(const void *pData, u32 Size);
|
||||
u32 GetHash32();
|
||||
u64 GetHash64();
|
||||
|
||||
// Convenience functions
|
||||
void HashByte(const u8& v);
|
||||
void HashShort(const u16& v);
|
||||
void HashLong(const u32& v);
|
||||
void HashFloat(const float& v);
|
||||
void HashString(const std::string& v);
|
||||
};
|
||||
|
||||
#endif // CHASHFNV1A_H
|
|
@ -0,0 +1,241 @@
|
|||
#include "CMatrix4f.h"
|
||||
#include "CVector3f.h"
|
||||
#include "CVector4f.h"
|
||||
#include "CTransform4f.h"
|
||||
|
||||
CMatrix4f::CMatrix4f()
|
||||
{
|
||||
}
|
||||
|
||||
CMatrix4f::CMatrix4f(float v)
|
||||
{
|
||||
*this = skZero;
|
||||
m[0][0] = v;
|
||||
m[1][1] = v;
|
||||
m[2][2] = v;
|
||||
m[3][3] = v;
|
||||
}
|
||||
|
||||
CMatrix4f::CMatrix4f(float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33)
|
||||
{
|
||||
m[0][0] = m00;
|
||||
m[0][1] = m01;
|
||||
m[0][2] = m02;
|
||||
m[0][3] = m03;
|
||||
m[1][0] = m10;
|
||||
m[1][1] = m11;
|
||||
m[1][2] = m12;
|
||||
m[1][3] = m13;
|
||||
m[2][0] = m20;
|
||||
m[2][1] = m21;
|
||||
m[2][2] = m22;
|
||||
m[2][3] = m23;
|
||||
m[3][0] = m30;
|
||||
m[3][1] = m31;
|
||||
m[3][2] = m32;
|
||||
m[3][3] = m33;
|
||||
}
|
||||
|
||||
// ************ MATH ************
|
||||
CMatrix4f CMatrix4f::Transpose() const
|
||||
{
|
||||
return CMatrix4f(m[0][0], m[1][0], m[2][0], m[3][0],
|
||||
m[0][1], m[1][1], m[2][1], m[3][1],
|
||||
m[0][2], m[1][2], m[2][2], m[3][2],
|
||||
m[0][3], m[1][3], m[2][3], m[3][3]);
|
||||
}
|
||||
|
||||
CMatrix4f CMatrix4f::Inverse() const
|
||||
{
|
||||
// Copied from Ogre.
|
||||
// todo after developing a better understanding of the math - rewrite
|
||||
float m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];
|
||||
float m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], m13 = m[1][3];
|
||||
float m20 = m[2][0], m21 = m[2][1], m22 = m[2][2], m23 = m[2][3];
|
||||
float m30 = m[3][0], m31 = m[3][1], m32 = m[3][2], m33 = m[3][3];
|
||||
|
||||
float v0 = m20 * m31 - m21 * m30;
|
||||
float v1 = m20 * m32 - m22 * m30;
|
||||
float v2 = m20 * m33 - m23 * m30;
|
||||
float v3 = m21 * m32 - m22 * m31;
|
||||
float v4 = m21 * m33 - m23 * m31;
|
||||
float v5 = m22 * m33 - m23 * m32;
|
||||
|
||||
float t00 = + (v5 * m11 - v4 * m12 + v3 * m13);
|
||||
float t10 = - (v5 * m10 - v2 * m12 + v1 * m13);
|
||||
float t20 = + (v4 * m10 - v2 * m11 + v0 * m13);
|
||||
float t30 = - (v3 * m10 - v1 * m11 + v0 * m12);
|
||||
|
||||
float invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
|
||||
|
||||
float d00 = t00 * invDet;
|
||||
float d10 = t10 * invDet;
|
||||
float d20 = t20 * invDet;
|
||||
float d30 = t30 * invDet;
|
||||
|
||||
float d01 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
|
||||
float d11 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
|
||||
float d21 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
|
||||
float d31 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
|
||||
|
||||
v0 = m10 * m31 - m11 * m30;
|
||||
v1 = m10 * m32 - m12 * m30;
|
||||
v2 = m10 * m33 - m13 * m30;
|
||||
v3 = m11 * m32 - m12 * m31;
|
||||
v4 = m11 * m33 - m13 * m31;
|
||||
v5 = m12 * m33 - m13 * m32;
|
||||
|
||||
float d02 = + (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
|
||||
float d12 = - (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
|
||||
float d22 = + (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
|
||||
float d32 = - (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
|
||||
|
||||
v0 = m21 * m10 - m20 * m11;
|
||||
v1 = m22 * m10 - m20 * m12;
|
||||
v2 = m23 * m10 - m20 * m13;
|
||||
v3 = m22 * m11 - m21 * m12;
|
||||
v4 = m23 * m11 - m21 * m13;
|
||||
v5 = m23 * m12 - m22 * m13;
|
||||
|
||||
float d03 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
|
||||
float d13 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
|
||||
float d23 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
|
||||
float d33 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
|
||||
|
||||
return CMatrix4f(
|
||||
d00, d01, d02, d03,
|
||||
d10, d11, d12, d13,
|
||||
d20, d21, d22, d23,
|
||||
d30, d31, d32, d33);
|
||||
}
|
||||
|
||||
float CMatrix4f::Determinant() const
|
||||
{
|
||||
float AA = m[1][1] * ((m[2][2] * m[3][3]) - (m[2][3] * m[3][2]));
|
||||
float AB = m[1][2] * ((m[2][1] * m[3][3]) - (m[2][3] * m[3][1]));
|
||||
float AC = m[1][3] * ((m[2][1] * m[3][2]) - (m[2][2] * m[3][1]));
|
||||
float A = m[0][0] * (AA - AB + AC);
|
||||
|
||||
float BA = m[1][0] * ((m[2][2] * m[3][3]) - (m[2][3] * m[3][2]));
|
||||
float BB = m[1][2] * ((m[2][0] * m[3][3]) - (m[2][3] * m[3][0]));
|
||||
float BC = m[1][3] * ((m[2][0] * m[3][2]) - (m[2][2] * m[3][0]));
|
||||
float B = m[0][1] * (BA - BB + BC);
|
||||
|
||||
float CA = m[1][0] * ((m[2][1] * m[3][3]) - (m[2][3] * m[3][1]));
|
||||
float CB = m[1][1] * ((m[2][0] * m[3][3]) - (m[2][3] * m[3][0]));
|
||||
float CC = m[1][3] * ((m[2][0] * m[3][1]) - (m[2][1] * m[3][0]));
|
||||
float C = m[0][2] * (CA - CB + CC);
|
||||
|
||||
float DA = m[1][0] * ((m[2][1] * m[3][2]) - (m[2][2] * m[3][1]));
|
||||
float DB = m[1][1] * ((m[2][0] * m[3][2]) - (m[2][2] * m[3][0]));
|
||||
float DC = m[1][2] * ((m[2][0] * m[3][1]) - (m[2][1] * m[3][0]));
|
||||
float D = m[0][3] * (DA - DB + DC);
|
||||
|
||||
return (A - B + C - D);
|
||||
}
|
||||
|
||||
glm::mat4 CMatrix4f::ToGlmMat4() const
|
||||
{
|
||||
glm::mat4 out = glm::mat4(1);
|
||||
memcpy(&out[0][0], &m[0][0], sizeof(glm::mat4));
|
||||
return out;
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CMatrix4f CMatrix4f::FromGlmMat4(glm::mat4 src)
|
||||
{
|
||||
CMatrix4f out;
|
||||
memcpy(&out[0][0], &src[0][0], sizeof(CMatrix4f));
|
||||
return out;
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
inline float* CMatrix4f::operator[](long index)
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
inline const float* CMatrix4f::operator[](long index) const
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
CVector3f CMatrix4f::operator*(const CVector3f& vec) const
|
||||
{
|
||||
// For vec3 multiplication, the vector w component is considered to be 1.0
|
||||
CVector3f out;
|
||||
float w = (m[3][0] * vec.x) + (m[3][1] * vec.y) + (m[3][2] * vec.z) + m[3][3];
|
||||
out.x = ((m[0][0] * vec.x) + (m[0][1] * vec.y) + (m[0][2] * vec.z) + m[0][3]) / w;
|
||||
out.y = ((m[1][0] * vec.x) + (m[1][1] * vec.y) + (m[1][2] * vec.z) + m[1][3]) / w;
|
||||
out.z = ((m[2][0] * vec.x) + (m[2][1] * vec.y) + (m[2][2] * vec.z) + m[1][3]) / w;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CMatrix4f::operator*(const CVector4f& vec) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = (m[0][0] * vec.x) + (m[0][1] * vec.y) + (m[0][2] * vec.z) + (m[0][3] * vec.w);
|
||||
out.y = (m[1][0] * vec.x) + (m[1][1] * vec.y) + (m[1][2] * vec.z) + (m[1][3] * vec.w);
|
||||
out.z = (m[2][0] * vec.x) + (m[2][1] * vec.y) + (m[2][2] * vec.z) + (m[2][3] * vec.w);
|
||||
out.w = (m[3][0] * vec.x) + (m[3][1] * vec.y) + (m[3][2] * vec.z) + (m[3][3] * vec.w);
|
||||
return out;
|
||||
}
|
||||
|
||||
CMatrix4f CMatrix4f::operator*(const CTransform4f& mtx) const
|
||||
{
|
||||
// CTransform4f is a 3x4 matrix with an implicit fourth row of {0, 0, 0, 1}
|
||||
CMatrix4f out;
|
||||
out[0][0] = (m[0][0] * mtx[0][0]) + (m[0][1] * mtx[1][0]) + (m[0][2] * mtx[2][0]);
|
||||
out[0][1] = (m[0][0] * mtx[0][1]) + (m[0][1] * mtx[1][1]) + (m[0][2] * mtx[2][1]);
|
||||
out[0][2] = (m[0][0] * mtx[0][2]) + (m[0][1] * mtx[1][2]) + (m[0][2] * mtx[2][2]);
|
||||
out[0][3] = (m[0][0] * mtx[0][3]) + (m[0][1] * mtx[1][3]) + (m[0][2] * mtx[2][3]) + m[0][3];
|
||||
out[1][0] = (m[1][0] * mtx[0][0]) + (m[1][1] * mtx[1][0]) + (m[1][2] * mtx[2][0]);
|
||||
out[1][1] = (m[1][0] * mtx[0][1]) + (m[1][1] * mtx[1][1]) + (m[1][2] * mtx[2][1]);
|
||||
out[1][2] = (m[1][0] * mtx[0][2]) + (m[1][1] * mtx[1][2]) + (m[1][2] * mtx[2][2]);
|
||||
out[1][3] = (m[1][0] * mtx[0][3]) + (m[1][1] * mtx[1][3]) + (m[1][2] * mtx[2][3]) + m[1][3];
|
||||
out[2][0] = (m[2][0] * mtx[0][0]) + (m[2][1] * mtx[1][0]) + (m[2][2] * mtx[2][0]);
|
||||
out[2][1] = (m[2][0] * mtx[0][1]) + (m[2][1] * mtx[1][1]) + (m[2][2] * mtx[2][1]);
|
||||
out[2][2] = (m[2][0] * mtx[0][2]) + (m[2][1] * mtx[1][2]) + (m[2][2] * mtx[2][2]);
|
||||
out[2][3] = (m[2][0] * mtx[0][3]) + (m[2][1] * mtx[1][3]) + (m[2][2] * mtx[2][3]) + m[2][3];
|
||||
out[3][0] = (m[3][0] * mtx[0][0]) + (m[3][1] * mtx[1][0]) + (m[3][2] * mtx[2][0]);
|
||||
out[3][1] = (m[3][0] * mtx[0][1]) + (m[3][1] * mtx[1][1]) + (m[3][2] * mtx[2][1]);
|
||||
out[3][2] = (m[3][0] * mtx[0][2]) + (m[3][1] * mtx[1][2]) + (m[3][2] * mtx[2][2]);
|
||||
out[3][3] = (m[3][0] * mtx[0][3]) + (m[3][1] * mtx[1][3]) + (m[3][2] * mtx[2][3]) + m[3][3];
|
||||
return out;
|
||||
}
|
||||
|
||||
CMatrix4f CMatrix4f::operator*(const CMatrix4f& mtx) const
|
||||
{
|
||||
CMatrix4f out;
|
||||
out[0][0] = (m[0][0] * mtx[0][0]) + (m[0][1] * mtx[1][0]) + (m[0][2] * mtx[2][0]) + (m[0][3] * mtx[3][0]);
|
||||
out[0][1] = (m[0][0] * mtx[0][1]) + (m[0][1] * mtx[1][1]) + (m[0][2] * mtx[2][1]) + (m[0][3] * mtx[3][1]);
|
||||
out[0][2] = (m[0][0] * mtx[0][2]) + (m[0][1] * mtx[1][2]) + (m[0][2] * mtx[2][2]) + (m[0][3] * mtx[3][2]);
|
||||
out[0][3] = (m[0][0] * mtx[0][3]) + (m[0][1] * mtx[1][3]) + (m[0][2] * mtx[2][3]) + (m[0][3] * mtx[3][3]);
|
||||
out[1][0] = (m[1][0] * mtx[0][0]) + (m[1][1] * mtx[1][0]) + (m[1][2] * mtx[2][0]) + (m[1][3] * mtx[3][0]);
|
||||
out[1][1] = (m[1][0] * mtx[0][1]) + (m[1][1] * mtx[1][1]) + (m[1][2] * mtx[2][1]) + (m[1][3] * mtx[3][1]);
|
||||
out[1][2] = (m[1][0] * mtx[0][2]) + (m[1][1] * mtx[1][2]) + (m[1][2] * mtx[2][2]) + (m[1][3] * mtx[3][2]);
|
||||
out[1][3] = (m[1][0] * mtx[0][3]) + (m[1][1] * mtx[1][3]) + (m[1][2] * mtx[2][3]) + (m[1][3] * mtx[3][3]);
|
||||
out[2][0] = (m[2][0] * mtx[0][0]) + (m[2][1] * mtx[1][0]) + (m[2][2] * mtx[2][0]) + (m[2][3] * mtx[3][0]);
|
||||
out[2][1] = (m[2][0] * mtx[0][1]) + (m[2][1] * mtx[1][1]) + (m[2][2] * mtx[2][1]) + (m[2][3] * mtx[3][1]);
|
||||
out[2][2] = (m[2][0] * mtx[0][2]) + (m[2][1] * mtx[1][2]) + (m[2][2] * mtx[2][2]) + (m[2][3] * mtx[3][2]);
|
||||
out[2][3] = (m[2][0] * mtx[0][3]) + (m[2][1] * mtx[1][3]) + (m[2][2] * mtx[2][3]) + (m[2][3] * mtx[3][3]);
|
||||
out[3][0] = (m[3][0] * mtx[0][0]) + (m[3][1] * mtx[1][0]) + (m[3][2] * mtx[2][0]) + (m[3][3] * mtx[3][0]);
|
||||
out[3][1] = (m[3][0] * mtx[0][1]) + (m[3][1] * mtx[1][1]) + (m[3][2] * mtx[2][1]) + (m[3][3] * mtx[3][1]);
|
||||
out[3][2] = (m[3][0] * mtx[0][2]) + (m[3][1] * mtx[1][2]) + (m[3][2] * mtx[2][2]) + (m[3][3] * mtx[3][2]);
|
||||
out[3][3] = (m[3][0] * mtx[0][3]) + (m[3][1] * mtx[1][3]) + (m[3][2] * mtx[2][3]) + (m[3][3] * mtx[3][3]);
|
||||
return out;
|
||||
}
|
||||
|
||||
// ************ CONSTANT ************
|
||||
const CMatrix4f CMatrix4f::skZero(0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
const CMatrix4f CMatrix4f::skIdentity(1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef CMATRIX4_H
|
||||
#define CMATRIX4_H
|
||||
|
||||
#include <glm.hpp>
|
||||
|
||||
class CVector3f;
|
||||
class CVector4f;
|
||||
class CTransform4f;
|
||||
|
||||
class CMatrix4f
|
||||
{
|
||||
union
|
||||
{
|
||||
float m[4][4];
|
||||
float _m[16];
|
||||
};
|
||||
|
||||
public:
|
||||
CMatrix4f();
|
||||
CMatrix4f(float v);
|
||||
CMatrix4f(float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33);
|
||||
|
||||
// Math
|
||||
CMatrix4f Transpose() const;
|
||||
CMatrix4f Inverse() const;
|
||||
float Determinant() const;
|
||||
|
||||
// Conversion
|
||||
glm::mat4 ToGlmMat4() const;
|
||||
|
||||
// Static
|
||||
static CMatrix4f FromGlmMat4(glm::mat4 src);
|
||||
|
||||
// Operators
|
||||
inline float* operator[](long index);
|
||||
inline const float* operator[](long index) const;
|
||||
CVector3f operator*(const CVector3f& vec) const;
|
||||
CVector4f operator*(const CVector4f& vec) const;
|
||||
CMatrix4f operator*(const CTransform4f& mtx) const;
|
||||
CMatrix4f operator*(const CMatrix4f& mtx) const;
|
||||
|
||||
// Constants
|
||||
static const CMatrix4f skZero;
|
||||
static const CMatrix4f skIdentity;
|
||||
};
|
||||
|
||||
#endif // CMATRIX4_H
|
|
@ -0,0 +1,86 @@
|
|||
#include "CQuaternion.h"
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
|
||||
CQuaternion::CQuaternion()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 0;
|
||||
}
|
||||
|
||||
CQuaternion::CQuaternion(float _x, float _y, float _z, float _w)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::operator*(const CQuaternion& other) const
|
||||
{
|
||||
CQuaternion out;
|
||||
out.x = ( x * other.w) + (y * other.z) - (z * other.y) + (w * other.x);
|
||||
out.y = (-x * other.z) + (y * other.w) + (z * other.x) + (w * other.y);
|
||||
out.z = ( x * other.y) - (y * other.x) + (z * other.w) + (w * other.z);
|
||||
out.w = (-x * other.x) - (y * other.y) - (z * other.z) + (w * other.w);
|
||||
return out;
|
||||
}
|
||||
|
||||
void CQuaternion::operator *= (const CQuaternion& other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CQuaternion CQuaternion::FromEuler(CVector3f euler)
|
||||
{
|
||||
/**
|
||||
* The commented-out code below might be faster but the conversion isn't completely correct
|
||||
* So in lieu of fixing it I'm using axis angles to convert from Eulers instead
|
||||
* I'm not sure what the difference is performance-wise but the result is 100% accurate
|
||||
*/
|
||||
/*CQuaternion quat;
|
||||
|
||||
// Convert from degrees to radians
|
||||
float pi = 3.14159265358979323846f;
|
||||
euler = euler * pi / 180;
|
||||
|
||||
// Convert to quaternion
|
||||
float c1 = cos(euler.x / 2);
|
||||
float c2 = cos(euler.y / 2);
|
||||
float c3 = cos(euler.z / 2);
|
||||
float s1 = sin(euler.x / 2);
|
||||
float s2 = sin(euler.y / 2);
|
||||
float s3 = sin(euler.z / 2);
|
||||
|
||||
quat.w = (c1 * c2 * c3) - (s1 * s2 * s3);
|
||||
quat.x = -((s1 * c2 * c3) + (c1 * s2 * s3));
|
||||
quat.y = ((c1 * s2 * c3) - (s1 * c2 * s3));
|
||||
quat.z = ((s1 * s2 * c3) + (c1 * c2 * s3));*/
|
||||
|
||||
CQuaternion x = CQuaternion::FromAxisAngle(euler.x, CVector3f(1,0,0));
|
||||
CQuaternion y = CQuaternion::FromAxisAngle(euler.y, CVector3f(0,1,0));
|
||||
CQuaternion z = CQuaternion::FromAxisAngle(euler.z, CVector3f(0,0,1));
|
||||
CQuaternion quat = z * y * x;
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::FromAxisAngle(float angle, CVector3f axis)
|
||||
{
|
||||
CQuaternion quat;
|
||||
axis = axis.Normalized();
|
||||
angle = angle * 3.14159265358979323846f / 180;
|
||||
|
||||
float sa = sin(angle / 2);
|
||||
quat.x = axis.x * sa;
|
||||
quat.y = axis.y * sa;
|
||||
quat.z = axis.z * sa;
|
||||
quat.w = cos(angle / 2);
|
||||
return quat;
|
||||
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::skIdentity = CQuaternion(0.f, 0.f, 0.f, 1.f);
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef CQUATERNION_H
|
||||
#define CQUATERNION_H
|
||||
|
||||
#include "CVector3f.h"
|
||||
|
||||
class CQuaternion
|
||||
{
|
||||
public:
|
||||
float x, y, z, w;
|
||||
|
||||
CQuaternion();
|
||||
CQuaternion(float _x, float _y, float _z, float _w);
|
||||
|
||||
// Operators
|
||||
CQuaternion operator*(const CQuaternion& other) const;
|
||||
void operator *= (const CQuaternion& other);
|
||||
|
||||
// Static
|
||||
static CQuaternion FromEuler(CVector3f euler);
|
||||
static CQuaternion FromAxisAngle(float angle, CVector3f axis);
|
||||
|
||||
static CQuaternion skIdentity;
|
||||
};
|
||||
|
||||
#endif // CQUATERNION_H
|
|
@ -0,0 +1,43 @@
|
|||
#include "CRay.h"
|
||||
#include <Common/CVector4f.h>
|
||||
#include <Common/CTransform4f.h>
|
||||
#include <iostream>
|
||||
|
||||
CRay::CRay()
|
||||
{
|
||||
}
|
||||
|
||||
CRay::CRay(const CVector3f& Origin, const CVector3f& Direction)
|
||||
: mOrigin(Origin), mDirection(Direction)
|
||||
{
|
||||
}
|
||||
|
||||
CRay::~CRay()
|
||||
{
|
||||
}
|
||||
|
||||
void CRay::SetOrigin(const CVector3f& Origin)
|
||||
{
|
||||
mOrigin = Origin;
|
||||
}
|
||||
|
||||
void CRay::SetDirection(const CVector3f& Direction)
|
||||
{
|
||||
mDirection = Direction;
|
||||
}
|
||||
|
||||
CRay CRay::Transformed(const CTransform4f &Matrix) const
|
||||
{
|
||||
CRay out;
|
||||
out.mOrigin = Matrix * mOrigin;
|
||||
|
||||
CVector3f Point = Matrix * (mOrigin + mDirection);
|
||||
out.mDirection = (Point - out.mOrigin).Normalized();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CRay::PointOnRay(float Distance) const
|
||||
{
|
||||
return mOrigin + (mDirection * Distance);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef CRAY_H
|
||||
#define CRAY_H
|
||||
|
||||
#include "CVector3f.h"
|
||||
|
||||
class CRay
|
||||
{
|
||||
CVector3f mOrigin;
|
||||
CVector3f mDirection;
|
||||
|
||||
public:
|
||||
CRay();
|
||||
CRay(const CVector3f& Origin, const CVector3f& Direction);
|
||||
~CRay();
|
||||
const CVector3f& Origin() const;
|
||||
const CVector3f& Direction() const;
|
||||
void SetOrigin(const CVector3f& Origin);
|
||||
void SetDirection(const CVector3f& Direction);
|
||||
|
||||
CRay Transformed(const CTransform4f& Matrix) const;
|
||||
CVector3f PointOnRay(float Distance) const;
|
||||
};
|
||||
|
||||
// ************ INLINE FUNCTIONS ************
|
||||
inline const CVector3f& CRay::Origin() const
|
||||
{
|
||||
return mOrigin;
|
||||
}
|
||||
|
||||
inline const CVector3f& CRay::Direction() const
|
||||
{
|
||||
return mDirection;
|
||||
}
|
||||
|
||||
#endif // CRAY_H
|
|
@ -0,0 +1,56 @@
|
|||
#include "CRayCollisionTester.h"
|
||||
#include <Scene/CSceneNode.h>
|
||||
|
||||
CRayCollisionTester::CRayCollisionTester(const CRay& Ray)
|
||||
: mRay(Ray)
|
||||
{
|
||||
}
|
||||
|
||||
CRayCollisionTester::~CRayCollisionTester()
|
||||
{
|
||||
}
|
||||
|
||||
void CRayCollisionTester::AddNode(CSceneNode *pNode, u32 AssetIndex, float Distance)
|
||||
{
|
||||
mBoxIntersectList.emplace_back(SRayIntersection());
|
||||
SRayIntersection& Intersection = mBoxIntersectList.back();
|
||||
Intersection.pNode = pNode;
|
||||
Intersection.AssetIndex = AssetIndex;
|
||||
Intersection.Distance = Distance;
|
||||
}
|
||||
|
||||
SRayIntersection CRayCollisionTester::TestNodes()
|
||||
{
|
||||
// Sort nodes by distance from ray
|
||||
mBoxIntersectList.sort(
|
||||
[](const SRayIntersection& A, SRayIntersection& B) -> bool
|
||||
{
|
||||
return (A.Distance < B.Distance);
|
||||
});
|
||||
|
||||
// Now do more precise intersection tests on geometry
|
||||
SRayIntersection Result;
|
||||
Result.Hit = false;
|
||||
|
||||
for (auto iNode = mBoxIntersectList.begin(); iNode != mBoxIntersectList.end(); iNode++)
|
||||
{
|
||||
SRayIntersection& Intersection = *iNode;
|
||||
|
||||
// If we have a result, and the distance for the bounding box hit is further than the current result distance
|
||||
// then we know that every remaining node is further away and there is no chance of finding a closer hit.
|
||||
if ((Result.Hit) && (Result.Distance < Intersection.Distance))
|
||||
break;
|
||||
|
||||
// Otherwise, more intersection tests...
|
||||
CSceneNode *pNode = Intersection.pNode;
|
||||
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex);
|
||||
|
||||
if (MidResult.Hit)
|
||||
{
|
||||
if ((!Result.Hit) || (MidResult.Distance < Result.Distance))
|
||||
Result = MidResult;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef CRAYCOLLISIONHELPER_H
|
||||
#define CRAYCOLLISIONHELPER_H
|
||||
|
||||
#include "CAABox.h"
|
||||
#include "CRay.h"
|
||||
#include "CVector3f.h"
|
||||
#include "SRayIntersection.h"
|
||||
#include "types.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
class CSceneNode;
|
||||
|
||||
class CRayCollisionTester
|
||||
{
|
||||
CRay mRay;
|
||||
std::list<SRayIntersection> mBoxIntersectList;
|
||||
|
||||
public:
|
||||
CRayCollisionTester(const CRay& Ray);
|
||||
~CRayCollisionTester();
|
||||
const CRay& Ray() const;
|
||||
void AddNode(CSceneNode *pNode, u32 AssetIndex, float Distance);
|
||||
SRayIntersection TestNodes();
|
||||
};
|
||||
|
||||
inline const CRay& CRayCollisionTester::Ray() const
|
||||
{
|
||||
return mRay;
|
||||
}
|
||||
|
||||
#endif // CRAYCOLLISIONHELPER_H
|
|
@ -0,0 +1,89 @@
|
|||
#include "CTimer.h"
|
||||
#include <ctime>
|
||||
|
||||
CTimer::CTimer()
|
||||
{
|
||||
mStartTime = 0;
|
||||
mStopTime = 0;
|
||||
mStarted = false;
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
void CTimer::Start()
|
||||
{
|
||||
if (!mStarted)
|
||||
{
|
||||
mStartTime = GlobalTime();
|
||||
mStarted = true;
|
||||
mPaused = false;
|
||||
mPauseStartTime = 0;
|
||||
mTotalPauseTime = 0;
|
||||
mStopTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CTimer::Start(double StartTime)
|
||||
{
|
||||
if (!mStarted)
|
||||
{
|
||||
mStartTime = GlobalTime() - StartTime;
|
||||
mStarted = true;
|
||||
mPaused = false;
|
||||
mPauseStartTime = 0;
|
||||
mTotalPauseTime = 0;
|
||||
mStopTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CTimer::Restart()
|
||||
{
|
||||
mStarted = false;
|
||||
Start();
|
||||
}
|
||||
|
||||
double CTimer::Stop()
|
||||
{
|
||||
mStopTime = Time();
|
||||
mStarted = false;
|
||||
mPaused = false;
|
||||
return mStopTime;
|
||||
}
|
||||
|
||||
double CTimer::Pause()
|
||||
{
|
||||
mPauseStartTime = GlobalTime();
|
||||
mPaused = true;
|
||||
return Time();
|
||||
}
|
||||
|
||||
bool CTimer::IsPaused()
|
||||
{
|
||||
return mPaused;
|
||||
}
|
||||
|
||||
void CTimer::Resume()
|
||||
{
|
||||
if (mPaused)
|
||||
{
|
||||
mTotalPauseTime += GlobalTime() - mPauseStartTime;
|
||||
mPaused = false;
|
||||
}
|
||||
}
|
||||
|
||||
double CTimer::Time()
|
||||
{
|
||||
if (mStarted)
|
||||
{
|
||||
double CurrentPauseTime = 0;
|
||||
if (mPaused) CurrentPauseTime = GlobalTime() - mPauseStartTime;
|
||||
return GlobalTime() - mStartTime - mTotalPauseTime - CurrentPauseTime;
|
||||
}
|
||||
|
||||
else
|
||||
return mStopTime;
|
||||
}
|
||||
|
||||
double CTimer::GlobalTime()
|
||||
{
|
||||
return (double) clock() / CLOCKS_PER_SEC;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef CTIMER_H
|
||||
#define CTIMER_H
|
||||
|
||||
class CTimer
|
||||
{
|
||||
double mStartTime;
|
||||
double mPauseStartTime;
|
||||
double mTotalPauseTime;
|
||||
double mStopTime;
|
||||
bool mStarted;
|
||||
bool mPaused;
|
||||
|
||||
public:
|
||||
CTimer();
|
||||
void Start();
|
||||
void Start(double StartTime);
|
||||
void Restart();
|
||||
double Stop();
|
||||
double Pause();
|
||||
bool IsPaused();
|
||||
void Resume();
|
||||
double Time();
|
||||
|
||||
// Static
|
||||
static double GlobalTime();
|
||||
};
|
||||
|
||||
#endif // CTIMER_H
|
|
@ -0,0 +1,309 @@
|
|||
#include "CTransform4f.h"
|
||||
#include "CVector3f.h"
|
||||
#include "CVector4f.h"
|
||||
#include "CQuaternion.h"
|
||||
#include "CMatrix4f.h"
|
||||
|
||||
// ************ CONSTRUCTRS ************
|
||||
CTransform4f::CTransform4f()
|
||||
{
|
||||
*this = skIdentity;
|
||||
}
|
||||
|
||||
CTransform4f::CTransform4f(CInputStream& input)
|
||||
{
|
||||
for (int v = 0; v < 12; v++)
|
||||
_m[v] = input.ReadFloat();
|
||||
}
|
||||
|
||||
CTransform4f::CTransform4f(float v)
|
||||
{
|
||||
*this = skZero;
|
||||
m[0][0] = v;
|
||||
m[1][1] = v;
|
||||
m[2][2] = v;
|
||||
}
|
||||
|
||||
CTransform4f::CTransform4f(float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23)
|
||||
{
|
||||
m[0][0] = m00;
|
||||
m[0][1] = m01;
|
||||
m[0][2] = m02;
|
||||
m[0][3] = m03;
|
||||
m[1][0] = m10;
|
||||
m[1][1] = m11;
|
||||
m[1][2] = m12;
|
||||
m[1][3] = m13;
|
||||
m[2][0] = m20;
|
||||
m[2][1] = m21;
|
||||
m[2][2] = m22;
|
||||
m[2][3] = m23;
|
||||
}
|
||||
|
||||
CTransform4f::CTransform4f(CVector3f Position, CQuaternion Rotation, CVector3f Scale)
|
||||
{
|
||||
*this = skIdentity;
|
||||
Translate(Position);
|
||||
Rotate(Rotation);
|
||||
this->Scale(Scale);
|
||||
}
|
||||
|
||||
CTransform4f::CTransform4f(CVector3f, CVector3f, CVector3f)
|
||||
{
|
||||
}
|
||||
|
||||
// ************ MATH ************
|
||||
void CTransform4f::Translate(CVector3f Translation)
|
||||
{
|
||||
CTransform4f TranslateMtx = CTransform4f::TranslationMatrix(Translation);
|
||||
*this = TranslateMtx * *this;
|
||||
}
|
||||
|
||||
void CTransform4f::Translate(float XTrans, float YTrans, float ZTrans)
|
||||
{
|
||||
Translate(CVector3f(XTrans, YTrans, ZTrans));
|
||||
}
|
||||
|
||||
void CTransform4f::Rotate(CQuaternion Rotation)
|
||||
{
|
||||
CTransform4f RotateMtx = CTransform4f::RotationMatrix(Rotation);
|
||||
*this = RotateMtx * *this;
|
||||
}
|
||||
|
||||
void CTransform4f::Rotate(CVector3f Rotation)
|
||||
{
|
||||
CQuaternion quat = CQuaternion::FromEuler(Rotation);
|
||||
Rotate(quat);
|
||||
}
|
||||
|
||||
void CTransform4f::Rotate(float XRot, float YRot, float ZRot)
|
||||
{
|
||||
Rotate(CVector3f(XRot, YRot, ZRot));
|
||||
}
|
||||
|
||||
void CTransform4f::Scale(CVector3f Scale)
|
||||
{
|
||||
CTransform4f ScaleMtx = CTransform4f::ScaleMatrix(Scale);
|
||||
*this = ScaleMtx * *this;
|
||||
}
|
||||
|
||||
void CTransform4f::Scale(float XScale, float YScale, float ZScale)
|
||||
{
|
||||
Scale(CVector3f(XScale, YScale, ZScale));
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::MultiplyIgnoreTranslation(const CTransform4f& mtx) const
|
||||
{
|
||||
CTransform4f out;
|
||||
out[0][0] = (m[0][0] * mtx[0][0]) + (m[0][1] * mtx[1][0]) + (m[0][2] * mtx[2][0]);
|
||||
out[0][1] = (m[0][0] * mtx[0][1]) + (m[0][1] * mtx[1][1]) + (m[0][2] * mtx[2][1]);
|
||||
out[0][2] = (m[0][0] * mtx[0][2]) + (m[0][1] * mtx[1][2]) + (m[0][2] * mtx[2][2]);
|
||||
out[1][0] = (m[1][0] * mtx[0][0]) + (m[1][1] * mtx[1][0]) + (m[1][2] * mtx[2][0]);
|
||||
out[1][1] = (m[1][0] * mtx[0][1]) + (m[1][1] * mtx[1][1]) + (m[1][2] * mtx[2][1]);
|
||||
out[1][2] = (m[1][0] * mtx[0][2]) + (m[1][1] * mtx[1][2]) + (m[1][2] * mtx[2][2]);
|
||||
out[2][0] = (m[2][0] * mtx[0][0]) + (m[2][1] * mtx[1][0]) + (m[2][2] * mtx[2][0]);
|
||||
out[2][1] = (m[2][0] * mtx[0][1]) + (m[2][1] * mtx[1][1]) + (m[2][2] * mtx[2][1]);
|
||||
out[2][2] = (m[2][0] * mtx[0][2]) + (m[2][1] * mtx[1][2]) + (m[2][2] * mtx[2][2]);
|
||||
out[0][3] = 0.f;
|
||||
out[1][3] = 0.f;
|
||||
out[2][3] = 0.f;
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::Inverse() const
|
||||
{
|
||||
// This uses CMatrix4f because I suck at math
|
||||
// todo - rewrite this without using CMatrix4f
|
||||
CMatrix4f Mat4 = ToMatrix4f().Inverse();
|
||||
CTransform4f Out;
|
||||
memcpy(&Out[0][0], &Mat4[0][0], sizeof(CTransform4f));
|
||||
return Out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::QuickInverse() const
|
||||
{
|
||||
CTransform4f out;
|
||||
out[0][0] = m[0][0];
|
||||
out[0][1] = m[1][0];
|
||||
out[0][2] = m[2][0];
|
||||
out[0][3] = -((m[0][0] * m[0][3]) + (m[1][0] * m[1][3]) + (m[2][0] * m[2][3]));
|
||||
out[1][0] = m[0][1];
|
||||
out[1][1] = m[1][1];
|
||||
out[1][2] = m[2][1];
|
||||
out[1][3] = -((m[0][1] * m[0][3]) + (m[1][1] * m[1][3]) + (m[2][1] * m[2][3]));
|
||||
out[2][0] = m[0][2];
|
||||
out[2][1] = m[1][2];
|
||||
out[2][2] = m[2][2];
|
||||
out[2][3] = -((m[0][2] * m[0][3]) + (m[1][2] * m[1][3]) + (m[2][2] * m[2][3]));
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::NoTranslation() const
|
||||
{
|
||||
return CTransform4f(m[0][0], m[0][1], m[0][2], 0.f,
|
||||
m[1][0], m[1][1], m[1][2], 0.f,
|
||||
m[2][0], m[2][1], m[2][2], 0.f);
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::RotationOnly() const
|
||||
{
|
||||
return CTransform4f::FromMatrix4f(Inverse().ToMatrix4f().Transpose());
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
float* CTransform4f::operator[](long index)
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
const float* CTransform4f::operator[](long index) const
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
CVector3f CTransform4f::operator*(const CVector3f& vec) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = (m[0][0] * vec.x) + (m[0][1] * vec.y) + (m[0][2] * vec.z) + (m[0][3]);
|
||||
out.y = (m[1][0] * vec.x) + (m[1][1] * vec.y) + (m[1][2] * vec.z) + (m[1][3]);
|
||||
out.z = (m[2][0] * vec.x) + (m[2][1] * vec.y) + (m[2][2] * vec.z) + (m[2][3]);
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CTransform4f::operator*(const CVector4f& vec) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = (m[0][0] * vec.x) + (m[0][1] * vec.y) + (m[0][2] * vec.z) + (m[0][3] * vec.w);
|
||||
out.y = (m[1][0] * vec.x) + (m[1][1] * vec.y) + (m[1][2] * vec.z) + (m[1][3] * vec.w);
|
||||
out.z = (m[2][0] * vec.x) + (m[2][1] * vec.y) + (m[2][2] * vec.z) + (m[2][3] * vec.w);
|
||||
out.w = vec.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::operator*(const CTransform4f& mtx) const
|
||||
{
|
||||
CTransform4f out;
|
||||
out[0][0] = (m[0][0] * mtx[0][0]) + (m[0][1] * mtx[1][0]) + (m[0][2] * mtx[2][0]);
|
||||
out[0][1] = (m[0][0] * mtx[0][1]) + (m[0][1] * mtx[1][1]) + (m[0][2] * mtx[2][1]);
|
||||
out[0][2] = (m[0][0] * mtx[0][2]) + (m[0][1] * mtx[1][2]) + (m[0][2] * mtx[2][2]);
|
||||
out[0][3] = (m[0][0] * mtx[0][3]) + (m[0][1] * mtx[1][3]) + (m[0][2] * mtx[2][3]) + m[0][3];
|
||||
out[1][0] = (m[1][0] * mtx[0][0]) + (m[1][1] * mtx[1][0]) + (m[1][2] * mtx[2][0]);
|
||||
out[1][1] = (m[1][0] * mtx[0][1]) + (m[1][1] * mtx[1][1]) + (m[1][2] * mtx[2][1]);
|
||||
out[1][2] = (m[1][0] * mtx[0][2]) + (m[1][1] * mtx[1][2]) + (m[1][2] * mtx[2][2]);
|
||||
out[1][3] = (m[1][0] * mtx[0][3]) + (m[1][1] * mtx[1][3]) + (m[1][2] * mtx[2][3]) + m[1][3];
|
||||
out[2][0] = (m[2][0] * mtx[0][0]) + (m[2][1] * mtx[1][0]) + (m[2][2] * mtx[2][0]);
|
||||
out[2][1] = (m[2][0] * mtx[0][1]) + (m[2][1] * mtx[1][1]) + (m[2][2] * mtx[2][1]);
|
||||
out[2][2] = (m[2][0] * mtx[0][2]) + (m[2][1] * mtx[1][2]) + (m[2][2] * mtx[2][2]);
|
||||
out[2][3] = (m[2][0] * mtx[0][3]) + (m[2][1] * mtx[1][3]) + (m[2][2] * mtx[2][3]) + m[2][3];
|
||||
return out;
|
||||
}
|
||||
|
||||
void CTransform4f::operator*=(const CTransform4f& mtx)
|
||||
{
|
||||
*this = *this * mtx;
|
||||
}
|
||||
|
||||
bool CTransform4f::operator==(const CTransform4f& mtx) const
|
||||
{
|
||||
return ((m[0][0] == mtx[0][0]) &&
|
||||
(m[0][1] == mtx[0][1]) &&
|
||||
(m[0][2] == mtx[0][2]) &&
|
||||
(m[0][3] == mtx[0][3]) &&
|
||||
(m[1][0] == mtx[1][0]) &&
|
||||
(m[1][1] == mtx[1][1]) &&
|
||||
(m[1][2] == mtx[1][2]) &&
|
||||
(m[1][3] == mtx[1][3]) &&
|
||||
(m[2][0] == mtx[2][0]) &&
|
||||
(m[2][1] == mtx[2][1]) &&
|
||||
(m[2][2] == mtx[2][2]) &&
|
||||
(m[2][3] == mtx[2][3]));
|
||||
}
|
||||
|
||||
bool CTransform4f::operator!=(const CTransform4f& mtx) const
|
||||
{
|
||||
return (!(*this == mtx));
|
||||
}
|
||||
|
||||
// ************ CONVERSION ************
|
||||
CMatrix4f CTransform4f::ToMatrix4f() const
|
||||
{
|
||||
return CMatrix4f(m[0][0], m[0][1], m[0][2], m[0][3],
|
||||
m[1][0], m[1][1], m[1][2], m[1][3],
|
||||
m[2][0], m[2][1], m[2][2], m[2][3],
|
||||
0.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CTransform4f CTransform4f::TranslationMatrix(CVector3f Translation)
|
||||
{
|
||||
CTransform4f out = skIdentity;
|
||||
out[0][3] = Translation.x;
|
||||
out[1][3] = Translation.y;
|
||||
out[2][3] = Translation.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::RotationMatrix(CQuaternion Rotation)
|
||||
{
|
||||
CTransform4f out = skIdentity;
|
||||
float x = Rotation.x;
|
||||
float y = Rotation.y;
|
||||
float z = Rotation.z;
|
||||
float w = Rotation.w;
|
||||
float x2 = x * x;
|
||||
float y2 = y * y;
|
||||
float z2 = z * z;
|
||||
|
||||
out[0][0] = 1.0f - (2 * y2) - (2 * z2);
|
||||
out[0][1] = (2 * x * y) - (2 * z * w);
|
||||
out[0][2] = (2 * x * z) + (2 * y * w);
|
||||
out[1][0] = (2 * x * y) + (2 * z * w);
|
||||
out[1][1] = 1.0f - (2 * x2) - (2 * z2);
|
||||
out[1][2] = (2 * y * z) - (2 * x * w);
|
||||
out[2][0] = (2 * x * z) - (2 * y * w);
|
||||
out[2][1] = (2 * y * z) + (2 * x * w);
|
||||
out[2][2] = 1.0f - (2 * x2) - (2 * y2);
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::ScaleMatrix(CVector3f Scale)
|
||||
{
|
||||
CTransform4f out = skIdentity;
|
||||
out[0][0] = Scale.x;
|
||||
out[1][1] = Scale.y;
|
||||
out[2][2] = Scale.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::FromMatrix4f(const CMatrix4f& mtx)
|
||||
{
|
||||
CTransform4f out;
|
||||
for (int r = 0; r < 3; r++)
|
||||
for (int c = 0; c < 4; c++)
|
||||
out[r][c] = mtx[r][c];
|
||||
return out;
|
||||
}
|
||||
|
||||
CTransform4f CTransform4f::FromGlmMat4(const glm::mat4& mtx)
|
||||
{
|
||||
CTransform4f out;
|
||||
for (int r = 0; r < 3; r++)
|
||||
for (int c = 0; c < 4; c++)
|
||||
out[r][c] = mtx[r][c];
|
||||
return out;
|
||||
}
|
||||
|
||||
static CTransform4f FromGlmMat4(const glm::mat4&)
|
||||
{
|
||||
}
|
||||
|
||||
// ************ CONSTANTS ************
|
||||
const CTransform4f CTransform4f::skIdentity(1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
const CTransform4f CTransform4f::skZero(0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f);
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef CTRANSFORM4F_H
|
||||
#define CTRANSFORM4F_H
|
||||
|
||||
#include <FileIO/FileIO.h>
|
||||
#include "CMatrix4f.h"
|
||||
#include <glm.hpp>
|
||||
|
||||
class CVector3f;
|
||||
class CVector4f;
|
||||
class CQuaternion;
|
||||
class CMatrix4f;
|
||||
|
||||
class CTransform4f
|
||||
{
|
||||
union
|
||||
{
|
||||
float m[3][4];
|
||||
float _m[12];
|
||||
};
|
||||
|
||||
public:
|
||||
CTransform4f();
|
||||
CTransform4f(CInputStream& input);
|
||||
CTransform4f(float v);
|
||||
CTransform4f(float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23);
|
||||
CTransform4f(CVector3f Position, CQuaternion Rotation, CVector3f Scale);
|
||||
CTransform4f(CVector3f Position, CVector3f Rotation, CVector3f Scale);
|
||||
|
||||
// Math
|
||||
void Translate(CVector3f Translation);
|
||||
void Translate(float XTrans, float YTrans, float ZTrans);
|
||||
void Rotate(CQuaternion Rotation);
|
||||
void Rotate(CVector3f Rotation);
|
||||
void Rotate(float XRot, float YRot, float ZRot);
|
||||
void Scale(CVector3f Scale);
|
||||
void Scale(float XScale, float YScale, float ZScale);
|
||||
CTransform4f MultiplyIgnoreTranslation(const CTransform4f& mtx) const;
|
||||
CTransform4f Inverse() const;
|
||||
CTransform4f QuickInverse() const;
|
||||
CTransform4f NoTranslation() const;
|
||||
CTransform4f RotationOnly() const;
|
||||
|
||||
// Conversion
|
||||
CMatrix4f ToMatrix4f() const;
|
||||
|
||||
// Static
|
||||
static CTransform4f TranslationMatrix(CVector3f Translation);
|
||||
static CTransform4f RotationMatrix(CQuaternion Rotation);
|
||||
static CTransform4f ScaleMatrix(CVector3f Scale);
|
||||
static CTransform4f FromMatrix4f(const CMatrix4f& mtx);
|
||||
static CTransform4f FromGlmMat4(const glm::mat4& mtx);
|
||||
|
||||
// Operators
|
||||
float* operator[](long index);
|
||||
const float* operator[](long index) const;
|
||||
CVector3f operator*(const CVector3f& vec) const;
|
||||
CVector4f operator*(const CVector4f& vec) const;
|
||||
CTransform4f operator*(const CTransform4f& mtx) const;
|
||||
void operator*=(const CTransform4f& mtx);
|
||||
bool operator==(const CTransform4f& mtx) const;
|
||||
bool operator!=(const CTransform4f& mtx) const;
|
||||
|
||||
// Constant
|
||||
static const CTransform4f skIdentity;
|
||||
static const CTransform4f skZero;
|
||||
};
|
||||
|
||||
#endif // CTRANSFORM4F_H
|
|
@ -0,0 +1,299 @@
|
|||
#include "CUniqueID.h"
|
||||
#include <Common/StringUtil.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
|
||||
// this class probably isn't optimized! this may not be the best way to do things
|
||||
using IOUtil::SystemEndianness;
|
||||
using IOUtil::LittleEndian;
|
||||
using IOUtil::BigEndian;
|
||||
|
||||
CUniqueID::CUniqueID()
|
||||
{
|
||||
memset(mID, 0xFF, 16);
|
||||
mLength = eInvalidUIDLength;
|
||||
}
|
||||
|
||||
CUniqueID::CUniqueID(u64 ID)
|
||||
{
|
||||
// This constructor is intended to be used with both 32-bit and 64-bit input values
|
||||
memset(mID, 0xFF, 16);
|
||||
|
||||
// 64-bit - check for valid content in upper 32 bits (at least one bit set + one bit unset)
|
||||
if ((ID & 0xFFFFFFFF00000000) && (~ID & 0xFFFFFFFF00000000))
|
||||
{
|
||||
memcpy(&mID, &ID, 8);
|
||||
mLength = e64Bit;
|
||||
}
|
||||
|
||||
// 32-bit
|
||||
else
|
||||
{
|
||||
memcpy(mID, &ID, 4);
|
||||
mLength = e32Bit;
|
||||
}
|
||||
|
||||
// Reverse for Big Endian
|
||||
if (SystemEndianness == BigEndian)
|
||||
Reverse();
|
||||
}
|
||||
|
||||
CUniqueID::CUniqueID(u64 Part1, u64 Part2)
|
||||
{
|
||||
// Constructor for 128-bit IDs
|
||||
memcpy(&mID[0], &Part1, 8);
|
||||
memcpy(&mID[8], &Part2, 8);
|
||||
mLength = e128Bit;
|
||||
}
|
||||
|
||||
CUniqueID::CUniqueID(const char* ID)
|
||||
{
|
||||
*this = CUniqueID::FromString(ID);
|
||||
}
|
||||
|
||||
CUniqueID::CUniqueID(CInputStream& Input, EUIDLength Length)
|
||||
{
|
||||
memset(mID, 0, 16);
|
||||
Input.ReadBytes(&mID[16 - Length], Length);
|
||||
|
||||
if (Length != e128Bit)
|
||||
if (SystemEndianness == LittleEndian)
|
||||
Reverse();
|
||||
|
||||
mLength = Length;
|
||||
}
|
||||
|
||||
u32 CUniqueID::ToLong() const
|
||||
{
|
||||
if (SystemEndianness == LittleEndian)
|
||||
return *((u32*) mID);
|
||||
else
|
||||
return *((u32*) &mID[12]);
|
||||
}
|
||||
|
||||
u64 CUniqueID::ToLongLong() const
|
||||
{
|
||||
if (SystemEndianness == LittleEndian)
|
||||
return *((u64*) mID);
|
||||
else
|
||||
return *((u64*) &mID[8]);
|
||||
}
|
||||
|
||||
std::string CUniqueID::ToString() const
|
||||
{
|
||||
std::stringstream Ret;
|
||||
Ret << std::hex << std::setfill('0');
|
||||
|
||||
switch (mLength)
|
||||
{
|
||||
case e32Bit:
|
||||
Ret << std::setw(8) << ToLong();
|
||||
break;
|
||||
case e64Bit:
|
||||
Ret << std::setw(16) << ToLongLong();
|
||||
break;
|
||||
case e128Bit:
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
Ret << std::setw(2) << (u32) mID[i];
|
||||
break;
|
||||
}
|
||||
|
||||
return Ret.str();
|
||||
}
|
||||
|
||||
void CUniqueID::Reverse()
|
||||
{
|
||||
std::reverse(mID, &mID[16]);
|
||||
}
|
||||
|
||||
EUIDLength CUniqueID::Length() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
void CUniqueID::SetLength(EUIDLength Length)
|
||||
{
|
||||
mLength = Length;
|
||||
}
|
||||
|
||||
bool CUniqueID::IsValid() const
|
||||
{
|
||||
if (mLength == e32Bit)
|
||||
return (*this != skInvalidID32);
|
||||
|
||||
else if (mLength == e64Bit)
|
||||
return (*this != skInvalidID64);
|
||||
|
||||
else if (mLength == e128Bit)
|
||||
return (*this != skInvalidID128);
|
||||
|
||||
else return false;
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
void CUniqueID::operator=(const u64& Input)
|
||||
{
|
||||
*this = CUniqueID(Input);
|
||||
}
|
||||
|
||||
void CUniqueID::operator=(const char* Input)
|
||||
{
|
||||
*this = CUniqueID(Input);
|
||||
}
|
||||
|
||||
bool CUniqueID::operator==(const CUniqueID& Other) const
|
||||
{
|
||||
return ((mLength == Other.mLength) &&
|
||||
(memcmp(mID, Other.mID, 16) == 0));
|
||||
}
|
||||
|
||||
bool CUniqueID::operator!=(const CUniqueID& Other) const
|
||||
{
|
||||
return (!(*this == Other));
|
||||
}
|
||||
|
||||
bool CUniqueID::operator>(const CUniqueID& Other) const
|
||||
{
|
||||
if (mLength != Other.mLength)
|
||||
return mLength > Other.mLength;
|
||||
|
||||
switch (mLength)
|
||||
{
|
||||
case e32Bit:
|
||||
return (ToLong() > Other.ToLong());
|
||||
|
||||
case e64Bit:
|
||||
return (ToLongLong() > Other.ToLongLong());
|
||||
|
||||
case e128Bit:
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
if (mID[i] != Other.mID[i])
|
||||
return (mID[i] > Other.mID[i]);
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CUniqueID::operator>=(const CUniqueID& Other) const
|
||||
{
|
||||
return ((*this == Other) || (*this > Other));
|
||||
}
|
||||
|
||||
bool CUniqueID::operator<(const CUniqueID& Other) const
|
||||
{
|
||||
if (mLength != Other.mLength)
|
||||
return mLength < Other.mLength;
|
||||
|
||||
switch (mLength)
|
||||
{
|
||||
case e32Bit:
|
||||
return (ToLong() < Other.ToLong());
|
||||
|
||||
case e64Bit:
|
||||
return (ToLongLong() < Other.ToLongLong());
|
||||
|
||||
case e128Bit:
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
if (mID[i] != Other.mID[i])
|
||||
return (mID[i] < Other.mID[i]);
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CUniqueID::operator<=(const CUniqueID& Other) const
|
||||
{
|
||||
return ((*this == Other) || (*this < Other));
|
||||
}
|
||||
|
||||
bool CUniqueID::operator==(u64 Other) const
|
||||
{
|
||||
return (*this == CUniqueID(Other));
|
||||
}
|
||||
|
||||
bool CUniqueID::operator!=(u64 Other) const
|
||||
{
|
||||
return (!(*this == Other));
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CUniqueID CUniqueID::FromString(std::string String)
|
||||
{
|
||||
// If the input is a hex ID in string form, then preserve it... otherwise, generate an ID by hashing the string
|
||||
std::string Name = StringUtil::GetFileName(String);
|
||||
if (Name.back() == '\0') Name.pop_back();
|
||||
u32 NameLength = Name.length();
|
||||
|
||||
if (StringUtil::IsHexString(Name))
|
||||
{
|
||||
if (NameLength == 8)
|
||||
{
|
||||
CUniqueID ID;
|
||||
ID.mLength = e32Bit;
|
||||
|
||||
u32 LongID = StringUtil::StrToRes32(Name);
|
||||
|
||||
if (SystemEndianness == LittleEndian)
|
||||
memcpy(ID.mID, &LongID, 4);
|
||||
else
|
||||
memcpy(&ID.mID[12], &LongID, 4);
|
||||
|
||||
return ID;
|
||||
}
|
||||
|
||||
else if (NameLength == 16)
|
||||
{
|
||||
CUniqueID ID;
|
||||
ID.mLength = e64Bit;
|
||||
|
||||
u64 LongID = StringUtil::StrToRes64(Name);
|
||||
|
||||
if (SystemEndianness == LittleEndian)
|
||||
memcpy(ID.mID, &LongID, 8);
|
||||
else
|
||||
memcpy(&ID.mID[8], &LongID, 8);
|
||||
|
||||
return ID;
|
||||
}
|
||||
|
||||
else if (NameLength == 32)
|
||||
{
|
||||
CUniqueID ID;
|
||||
ID.mLength = e128Bit;
|
||||
StringUtil::StrToRes128(Name, (char*) ID.mID);
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
return CUniqueID( (u64) StringUtil::Hash64(String) );
|
||||
}
|
||||
|
||||
CUniqueID CUniqueID::FromData(void *pData, EUIDLength Length)
|
||||
{
|
||||
CUniqueID ID;
|
||||
ID.mLength = Length;
|
||||
memcpy(ID.mID, pData, Length);
|
||||
return ID;
|
||||
}
|
||||
|
||||
CUniqueID CUniqueID::RandomID()
|
||||
{
|
||||
CUniqueID ID;
|
||||
ID.mLength = e128Bit;
|
||||
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
ID.mID[i] = rand() & 0xFF;
|
||||
|
||||
return ID;
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
CUniqueID CUniqueID::skInvalidID32 = CUniqueID((u32) -1);
|
||||
CUniqueID CUniqueID::skInvalidID64 = CUniqueID((u64) -1);
|
||||
CUniqueID CUniqueID::skInvalidID128 = CUniqueID((u64) -1, (u64) -1);
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef CUNIQUEID_H
|
||||
#define CUNIQUEID_H
|
||||
|
||||
#include "types.h"
|
||||
#include <FileIO/FileIO.h>
|
||||
|
||||
enum EUIDLength
|
||||
{
|
||||
e32Bit = 4,
|
||||
e64Bit = 8,
|
||||
e128Bit = 16,
|
||||
eInvalidUIDLength = 0
|
||||
};
|
||||
|
||||
class CUniqueID
|
||||
{
|
||||
EUIDLength mLength;
|
||||
u8 mID[16];
|
||||
|
||||
public:
|
||||
CUniqueID();
|
||||
CUniqueID(u64 ID);
|
||||
CUniqueID(u64 Part1, u64 Part2);
|
||||
CUniqueID(const char* ID);
|
||||
CUniqueID(CInputStream& Input, EUIDLength Length);
|
||||
u32 ToLong() const;
|
||||
u64 ToLongLong() const;
|
||||
std::string ToString() const;
|
||||
void Reverse();
|
||||
EUIDLength Length() const;
|
||||
void SetLength(EUIDLength Length);
|
||||
bool IsValid() const;
|
||||
|
||||
// Operators
|
||||
void operator=(const u64& Input);
|
||||
void operator=(const char *Input);
|
||||
bool operator==(const CUniqueID& Other) const;
|
||||
bool operator!=(const CUniqueID& Other) const;
|
||||
bool operator>(const CUniqueID& Other) const;
|
||||
bool operator>=(const CUniqueID& Other) const;
|
||||
bool operator<(const CUniqueID& Other) const;
|
||||
bool operator<=(const CUniqueID& Other) const;
|
||||
bool operator==(u64 Other) const;
|
||||
bool operator!=(u64 Other) const;
|
||||
|
||||
// Static
|
||||
static CUniqueID FromString(std::string String);
|
||||
static CUniqueID FromData(void *pData, EUIDLength Length);
|
||||
static CUniqueID RandomID();
|
||||
|
||||
static CUniqueID skInvalidID32;
|
||||
static CUniqueID skInvalidID64;
|
||||
static CUniqueID skInvalidID128;
|
||||
};
|
||||
|
||||
#endif // CUNIQUEID_H
|
|
@ -0,0 +1,156 @@
|
|||
#include "CVector2f.h"
|
||||
|
||||
CVector2f::CVector2f()
|
||||
{
|
||||
x = y = 0.f;
|
||||
}
|
||||
|
||||
CVector2f::CVector2f(float xy)
|
||||
{
|
||||
x = y = xy;
|
||||
}
|
||||
|
||||
CVector2f::CVector2f(float _x, float _y)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
}
|
||||
|
||||
CVector2f::CVector2f(CInputStream& Input)
|
||||
{
|
||||
x = Input.ReadFloat();
|
||||
y = Input.ReadFloat();
|
||||
}
|
||||
|
||||
void CVector2f::Write(COutputStream &Output)
|
||||
{
|
||||
Output.WriteFloat(x);
|
||||
Output.WriteFloat(y);
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator+(const CVector2f& src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x + src.x;
|
||||
out.y = this->y + src.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator-(const CVector2f& src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x - src.x;
|
||||
out.y = this->y - src.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator*(const CVector2f& src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x * src.x;
|
||||
out.y = this->y * src.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator/(const CVector2f& src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x / src.x;
|
||||
out.y = this->y / src.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector2f::operator+=(const CVector2f& other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector2f::operator-=(const CVector2f& other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector2f::operator*=(const CVector2f& other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector2f::operator/=(const CVector2f& other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator+(const float src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x + src;
|
||||
out.y = this->y + src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator-(const float src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x - src;
|
||||
out.y = this->y - src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator*(const float src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x * src;
|
||||
out.y = this->y * src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator/(const float src) const
|
||||
{
|
||||
CVector2f out;
|
||||
out.x = this->x / src;
|
||||
out.y = this->y / src;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector2f::operator+=(const float other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector2f::operator-=(const float other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector2f::operator*=(const float other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector2f::operator/=(const float other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
bool CVector2f::operator==(const CVector2f& other) const
|
||||
{
|
||||
return ((x == other.x) && (y == other.y));
|
||||
}
|
||||
|
||||
bool CVector2f::operator!=(const CVector2f& other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
float& CVector2f::operator[](long index)
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
const CVector2f CVector2f::skZero = CVector2f(0, 0);
|
||||
const CVector2f CVector2f::skOne = CVector2f(1, 1);
|
||||
const CVector2f CVector2f::skUp = CVector2f(0, 1);
|
||||
const CVector2f CVector2f::skRight = CVector2f(1, 0);
|
||||
const CVector2f CVector2f::skDown = CVector2f(0,-1);
|
||||
const CVector2f CVector2f::skLeft = CVector2f(-1,0);
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef CVECTOR2F
|
||||
#define CVECTOR2F
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
|
||||
class CVector2f
|
||||
{
|
||||
public:
|
||||
float x, y;
|
||||
CVector2f();
|
||||
CVector2f(float xy);
|
||||
CVector2f(float _x, float _y);
|
||||
CVector2f(CInputStream& Input);
|
||||
void Write(COutputStream& Output);
|
||||
|
||||
CVector2f operator+(const CVector2f& other) const;
|
||||
CVector2f operator-(const CVector2f& other) const;
|
||||
CVector2f operator*(const CVector2f& other) const;
|
||||
CVector2f operator/(const CVector2f& other) const;
|
||||
void operator+=(const CVector2f& other);
|
||||
void operator-=(const CVector2f& other);
|
||||
void operator*=(const CVector2f& other);
|
||||
void operator/=(const CVector2f& other);
|
||||
CVector2f operator+(const float other) const;
|
||||
CVector2f operator-(const float other) const;
|
||||
CVector2f operator*(const float other) const;
|
||||
CVector2f operator/(const float other) const;
|
||||
void operator+=(const float other);
|
||||
void operator-=(const float other);
|
||||
void operator*=(const float other);
|
||||
void operator/=(const float other);
|
||||
bool operator==(const CVector2f& other) const;
|
||||
bool operator!=(const CVector2f& other) const;
|
||||
float& operator[](long index);
|
||||
|
||||
// Static Members
|
||||
static const CVector2f skZero;
|
||||
static const CVector2f skOne;
|
||||
static const CVector2f skUp;
|
||||
static const CVector2f skRight;
|
||||
static const CVector2f skDown;
|
||||
static const CVector2f skLeft;
|
||||
};
|
||||
|
||||
#endif // CVECTOR2F
|
|
@ -0,0 +1,139 @@
|
|||
#include "CVector2i.h"
|
||||
|
||||
CVector2i::CVector2i()
|
||||
{
|
||||
x = y = 0;
|
||||
}
|
||||
|
||||
CVector2i::CVector2i(int xy)
|
||||
{
|
||||
x = y = xy;
|
||||
}
|
||||
|
||||
CVector2i::CVector2i(int _x, int _y)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator+(const CVector2i& other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x + other.x;
|
||||
out.y = this->y + other.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator-(const CVector2i& other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x - other.x;
|
||||
out.y = this->y - other.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator*(const CVector2i& other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x * other.x;
|
||||
out.y = this->y * other.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator/(const CVector2i& other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x / other.x;
|
||||
out.y = this->y / other.y;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector2i::operator+=(const CVector2i& other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector2i::operator-=(const CVector2i& other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector2i::operator*=(const CVector2i& other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector2i::operator/=(const CVector2i& other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator+(const int other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x + other;
|
||||
out.y = this->y + other;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator-(const int other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x - other;
|
||||
out.y = this->y - other;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator*(const int other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x * other;
|
||||
out.y = this->y * other;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector2i CVector2i::operator/(const int other) const
|
||||
{
|
||||
CVector2i out;
|
||||
out.x = this->x / other;
|
||||
out.y = this->y / other;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector2i::operator+=(const int other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector2i::operator-=(const int other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector2i::operator*=(const int other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector2i::operator/=(const int other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
bool CVector2i::operator==(const CVector2i& other) const
|
||||
{
|
||||
return ((this->x == other.x) && (this->y == other.y));
|
||||
}
|
||||
|
||||
bool CVector2i::operator!=(const CVector2i& other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
int& CVector2i::operator[](int index)
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INTIALIZATION ************
|
||||
const CVector2i CVector2i::skZero = CVector2i(0,0);
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef CVECTOR2I_H
|
||||
#define CVECTOR2I_H
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
|
||||
class CVector2i
|
||||
{
|
||||
public:
|
||||
int x, y;
|
||||
CVector2i();
|
||||
CVector2i(int xy);
|
||||
CVector2i(int _x, int _y);
|
||||
|
||||
CVector2i operator+(const CVector2i& other) const;
|
||||
CVector2i operator-(const CVector2i& other) const;
|
||||
CVector2i operator*(const CVector2i& other) const;
|
||||
CVector2i operator/(const CVector2i& other) const;
|
||||
void operator+=(const CVector2i& other);
|
||||
void operator-=(const CVector2i& other);
|
||||
void operator*=(const CVector2i& other);
|
||||
void operator/=(const CVector2i& other);
|
||||
CVector2i operator+(const int other) const;
|
||||
CVector2i operator-(const int other) const;
|
||||
CVector2i operator*(const int other) const;
|
||||
CVector2i operator/(const int other) const;
|
||||
void operator+=(const int other);
|
||||
void operator-=(const int other);
|
||||
void operator*=(const int other);
|
||||
void operator/=(const int other);
|
||||
bool operator==(const CVector2i& other) const;
|
||||
bool operator!=(const CVector2i& other) const;
|
||||
int& operator[](int index);
|
||||
|
||||
// Static Members
|
||||
static const CVector2i skZero;
|
||||
};
|
||||
|
||||
#endif // CVECTOR2I_H
|
|
@ -0,0 +1,300 @@
|
|||
#include "CVector3f.h"
|
||||
#include "CVector2f.h"
|
||||
#include "CVector4f.h"
|
||||
#include "CTransform4f.h"
|
||||
#include <iomanip>
|
||||
#include <float.h>
|
||||
|
||||
CVector3f::CVector3f()
|
||||
{
|
||||
x = y = z = 0.f;
|
||||
}
|
||||
|
||||
CVector3f::CVector3f(float xyz)
|
||||
{
|
||||
x = y = z = xyz;
|
||||
}
|
||||
|
||||
CVector3f::CVector3f(float _x, float _y, float _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
CVector3f::CVector3f(CInputStream& Input)
|
||||
{
|
||||
x = Input.ReadFloat();
|
||||
y = Input.ReadFloat();
|
||||
z = Input.ReadFloat();
|
||||
}
|
||||
|
||||
void CVector3f::Write(COutputStream &Output)
|
||||
{
|
||||
Output.WriteFloat(x);
|
||||
Output.WriteFloat(y);
|
||||
Output.WriteFloat(z);
|
||||
}
|
||||
|
||||
// ************ SWIZZLE ************
|
||||
CVector2f CVector3f::xy()
|
||||
{
|
||||
return CVector2f(x, y);
|
||||
}
|
||||
|
||||
CVector2f CVector3f::xz()
|
||||
{
|
||||
return CVector2f(x, z);
|
||||
}
|
||||
|
||||
CVector2f CVector3f::yz()
|
||||
{
|
||||
return CVector2f(y, z);
|
||||
}
|
||||
|
||||
// ************ MATH ************
|
||||
float CVector3f::Magnitude() const
|
||||
{
|
||||
return sqrtf(SquaredMagnitude());
|
||||
}
|
||||
|
||||
float CVector3f::SquaredMagnitude() const
|
||||
{
|
||||
return (powf(x,2) + powf(y,2) + powf(z,2));
|
||||
}
|
||||
|
||||
CVector3f CVector3f::Normalized() const
|
||||
{
|
||||
return *this / Magnitude();;
|
||||
}
|
||||
|
||||
float CVector3f::Dot(const CVector3f& other) const
|
||||
{
|
||||
return (x * other.x) + (y * other.y) + (z * other.z);
|
||||
}
|
||||
|
||||
CVector3f CVector3f::Cross(const CVector3f& other) const
|
||||
{
|
||||
return CVector3f((y * other.z) - (z * other.y), (z * other.x) - (x * other.z), (x * other.y) - (y * other.x));
|
||||
}
|
||||
|
||||
float CVector3f::Distance(const CVector3f& point) const
|
||||
{
|
||||
return (*this - point).Magnitude();
|
||||
}
|
||||
|
||||
float CVector3f::SquaredDistance(const CVector3f& point) const
|
||||
{
|
||||
return (*this - point).SquaredMagnitude();
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
// VECTOR/VECTOR
|
||||
CVector3f CVector3f::operator+(const CVector3f& src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x + src.x;
|
||||
out.y = this->y + src.y;
|
||||
out.z = this->z + src.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator-(const CVector3f& src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x - src.x;
|
||||
out.y = this->y - src.y;
|
||||
out.z = this->z - src.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator*(const CVector3f& src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x * src.x;
|
||||
out.y = this->y * src.y;
|
||||
out.z = this->z * src.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator/(const CVector3f& src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x / src.x;
|
||||
out.y = this->y / src.y;
|
||||
out.z = this->z / src.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector3f::operator+=(const CVector3f& other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector3f::operator-=(const CVector3f& other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector3f::operator*=(const CVector3f& other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector3f::operator/=(const CVector3f& other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
bool CVector3f::operator> (const CVector3f& other) const
|
||||
{
|
||||
return ((x > other.x) && (y > other.y) && (z > other.z));
|
||||
}
|
||||
|
||||
bool CVector3f::operator>=(const CVector3f& other) const
|
||||
{
|
||||
return ((x >= other.x) && (y >= other.y) && (z >= other.z));
|
||||
}
|
||||
|
||||
bool CVector3f::operator< (const CVector3f& other) const
|
||||
{
|
||||
return ((x < other.x) && (y < other.y) && (z < other.z));
|
||||
}
|
||||
|
||||
bool CVector3f::operator<=(const CVector3f& other) const
|
||||
{
|
||||
return ((x <= other.x) && (y <= other.y) && (z <= other.z));
|
||||
}
|
||||
|
||||
bool CVector3f::operator==(const CVector3f& other) const
|
||||
{
|
||||
return ((x == other.x) && (y == other.y) && (z == other.z));
|
||||
}
|
||||
|
||||
bool CVector3f::operator!=(const CVector3f& other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
// VECTOR/FLOAT
|
||||
CVector3f CVector3f::operator+(const float src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x + src;
|
||||
out.y = this->y + src;
|
||||
out.z = this->z + src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator-(const float src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x - src;
|
||||
out.y = this->y - src;
|
||||
out.z = this->z - src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator*(const float src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x * src;
|
||||
out.y = this->y * src;
|
||||
out.z = this->z * src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator/(const float src) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = this->x / src;
|
||||
out.y = this->y / src;
|
||||
out.z = this->z / src;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector3f::operator+=(const float other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector3f::operator-=(const float other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector3f::operator*=(const float other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector3f::operator/=(const float other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
// VECTOR/MATRIX
|
||||
CVector3f CVector3f::operator*(const CTransform4f& mtx) const
|
||||
{
|
||||
CVector3f out;
|
||||
out.x = (x * mtx[0][0]) + (y * mtx[1][0]) + (z * mtx[2][0]);
|
||||
out.y = (x * mtx[0][1]) + (y * mtx[1][1]) + (z * mtx[2][1]);
|
||||
out.z = (x * mtx[0][2]) + (y * mtx[1][2]) + (z * mtx[2][2]);
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector3f::operator*=(const CTransform4f& mtx)
|
||||
{
|
||||
*this = *this * mtx;
|
||||
}
|
||||
|
||||
CVector3f CVector3f::operator*(const CMatrix4f& mtx) const
|
||||
{
|
||||
// To multiply by a Matrix4f, we consider the vector w component to be 1
|
||||
CVector3f out;
|
||||
float w = (x * mtx[0][3]) + (y * mtx[1][3]) + (z * mtx[2][3]) + mtx[3][3];
|
||||
out.x = ((x * mtx[0][0]) + (y * mtx[1][0]) + (z * mtx[2][0]) + mtx[3][0]) / w;
|
||||
out.y = ((x * mtx[0][1]) + (y * mtx[1][1]) + (z * mtx[2][1]) + mtx[3][1]) / w;
|
||||
out.z = ((x * mtx[0][2]) + (y * mtx[1][2]) + (z * mtx[2][2]) + mtx[3][2]) / w;
|
||||
return out;
|
||||
}
|
||||
|
||||
// UNARY
|
||||
CVector3f CVector3f::operator-() const
|
||||
{
|
||||
return CVector3f(-x, -y, -z);
|
||||
}
|
||||
|
||||
float& CVector3f::operator[](long index)
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
const float& CVector3f::operator[](long index) const
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// ************ CONSTANTS ************
|
||||
const CVector3f CVector3f::skZero = CVector3f(0.f);
|
||||
const CVector3f CVector3f::skOne = CVector3f(1.f);
|
||||
const CVector3f CVector3f::skInfinite = CVector3f(FLT_MAX);
|
||||
|
||||
// ************ OTHER ************
|
||||
std::ostream& operator<<(std::ostream& o, const CVector3f& Vector)
|
||||
{
|
||||
o << std::setprecision(6)
|
||||
<< std::fixed
|
||||
<< "["
|
||||
<< ((Vector.x >= 0) ? " " : "")
|
||||
<< Vector.x
|
||||
<< ", "
|
||||
<< ((Vector.y >= 0) ? " " : "")
|
||||
<< Vector.y
|
||||
<< ", "
|
||||
<< ((Vector.z >= 0) ? " " : "")
|
||||
<< Vector.z
|
||||
<< "]";
|
||||
|
||||
return o;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef CVECTOR3F
|
||||
#define CVECTOR3F
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
#include <ostream>
|
||||
|
||||
class CMatrix4f;
|
||||
class CVector2f;
|
||||
class CVector4f;
|
||||
class CTransform4f;
|
||||
|
||||
class CVector3f
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
|
||||
CVector3f();
|
||||
CVector3f(float xyz);
|
||||
CVector3f(float _x, float _y, float _z);
|
||||
CVector3f(CInputStream& Input);
|
||||
void Write(COutputStream& Output);
|
||||
|
||||
// Swizzle
|
||||
CVector2f xy();
|
||||
CVector2f xz();
|
||||
CVector2f yz();
|
||||
|
||||
// Math
|
||||
float Magnitude() const;
|
||||
float SquaredMagnitude() const;
|
||||
CVector3f Normalized() const;
|
||||
float Dot(const CVector3f& other) const;
|
||||
CVector3f Cross(const CVector3f& other) const;
|
||||
float Distance(const CVector3f& point) const;
|
||||
float SquaredDistance(const CVector3f& point) const;
|
||||
|
||||
// Vector/Vector
|
||||
CVector3f operator+(const CVector3f& other) const;
|
||||
CVector3f operator-(const CVector3f& other) const;
|
||||
CVector3f operator*(const CVector3f& other) const;
|
||||
CVector3f operator/(const CVector3f& other) const;
|
||||
void operator+=(const CVector3f& other);
|
||||
void operator-=(const CVector3f& other);
|
||||
void operator*=(const CVector3f& other);
|
||||
void operator/=(const CVector3f& other);
|
||||
bool operator> (const CVector3f& other) const;
|
||||
bool operator>=(const CVector3f& other) const;
|
||||
bool operator< (const CVector3f& other) const;
|
||||
bool operator<=(const CVector3f& other) const;
|
||||
bool operator==(const CVector3f& other) const;
|
||||
bool operator!=(const CVector3f& other) const;
|
||||
|
||||
// Vector/Float
|
||||
CVector3f operator+(const float other) const;
|
||||
CVector3f operator-(const float other) const;
|
||||
CVector3f operator*(const float other) const;
|
||||
CVector3f operator/(const float other) const;
|
||||
void operator+=(const float other);
|
||||
void operator-=(const float other);
|
||||
void operator*=(const float other);
|
||||
void operator/=(const float other);
|
||||
|
||||
// Vector/Matrix
|
||||
CVector3f operator*(const CTransform4f& mtx) const;
|
||||
void operator*=(const CTransform4f& mtx);
|
||||
CVector3f operator*(const CMatrix4f& mtx) const;
|
||||
|
||||
// Unary
|
||||
CVector3f operator-() const;
|
||||
float& operator[](long index);
|
||||
const float& operator[](long index) const;
|
||||
|
||||
// Constants
|
||||
static const CVector3f skZero;
|
||||
static const CVector3f skOne;
|
||||
static const CVector3f skInfinite;
|
||||
|
||||
// Other
|
||||
friend std::ostream& operator<<(std::ostream& o, const CVector3f& Vector);
|
||||
};
|
||||
|
||||
#endif // CVECTOR3F
|
|
@ -0,0 +1,273 @@
|
|||
#include "CVector4f.h"
|
||||
#include "CVector2f.h"
|
||||
#include "CVector3f.h"
|
||||
#include "CTransform4f.h"
|
||||
|
||||
CVector4f::CVector4f()
|
||||
{
|
||||
x = y = z = w = 0.f;
|
||||
}
|
||||
|
||||
CVector4f::CVector4f(float xyzw)
|
||||
{
|
||||
x = y = z = w = xyzw;
|
||||
}
|
||||
|
||||
CVector4f::CVector4f(float _x, float _y, float _z, float _w)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
CVector4f::CVector4f(const CVector2f& xy, float _z, float _w)
|
||||
{
|
||||
x = xy.x;
|
||||
y = xy.y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
CVector4f::CVector4f(const CVector3f& xyz)
|
||||
{
|
||||
x = xyz.x;
|
||||
y = xyz.y;
|
||||
z = xyz.z;
|
||||
w = 1.f;
|
||||
}
|
||||
|
||||
CVector4f::CVector4f(const CVector3f& xyz, float _w)
|
||||
{
|
||||
x = xyz.x;
|
||||
y = xyz.y;
|
||||
z = xyz.z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
CVector4f::CVector4f(CInputStream& Input)
|
||||
{
|
||||
x = Input.ReadFloat();
|
||||
y = Input.ReadFloat();
|
||||
z = Input.ReadFloat();
|
||||
w = Input.ReadFloat();
|
||||
}
|
||||
|
||||
void CVector4f::Write(COutputStream &Output)
|
||||
{
|
||||
Output.WriteFloat(x);
|
||||
Output.WriteFloat(y);
|
||||
Output.WriteFloat(z);
|
||||
Output.WriteFloat(w);
|
||||
}
|
||||
|
||||
// ************ SWIZZLE ************
|
||||
CVector3f CVector4f::xyz()
|
||||
{
|
||||
return CVector3f(x, y, z);
|
||||
}
|
||||
|
||||
CVector3f CVector4f::xzw()
|
||||
{
|
||||
return CVector3f(x, z, w);
|
||||
}
|
||||
|
||||
CVector3f CVector4f::yzw()
|
||||
{
|
||||
return CVector3f(y, z, w);
|
||||
}
|
||||
|
||||
CVector2f CVector4f::xy()
|
||||
{
|
||||
return CVector2f(x, y);
|
||||
}
|
||||
|
||||
CVector2f CVector4f::xz()
|
||||
{
|
||||
return CVector2f(x, z);
|
||||
}
|
||||
|
||||
CVector2f CVector4f::xw()
|
||||
{
|
||||
return CVector2f(x, w);
|
||||
}
|
||||
|
||||
CVector2f CVector4f::yz()
|
||||
{
|
||||
return CVector2f(y, z);
|
||||
}
|
||||
|
||||
CVector2f CVector4f::yw()
|
||||
{
|
||||
return CVector2f(y, w);
|
||||
}
|
||||
|
||||
CVector2f CVector4f::zw()
|
||||
{
|
||||
return CVector2f(z, w);
|
||||
}
|
||||
|
||||
// ************ MATH ************
|
||||
// ************ VECTOR/VECTOR ************
|
||||
CVector4f CVector4f::operator+(const CVector4f& src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x + src.x;
|
||||
out.y = this->y + src.y;
|
||||
out.z = this->z + src.z;
|
||||
out.w = this->w + src.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator-(const CVector4f& src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x - src.x;
|
||||
out.y = this->y - src.y;
|
||||
out.z = this->z - src.z;
|
||||
out.w = this->w - src.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator*(const CVector4f& src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x * src.x;
|
||||
out.y = this->y * src.y;
|
||||
out.z = this->z * src.z;
|
||||
out.w = this->w * src.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator/(const CVector4f& src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x / src.x;
|
||||
out.y = this->y / src.y;
|
||||
out.z = this->z / src.z;
|
||||
out.w = this->w / src.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector4f::operator+=(const CVector4f& other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector4f::operator-=(const CVector4f& other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector4f::operator*=(const CVector4f& other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector4f::operator/=(const CVector4f& other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
bool CVector4f::operator==(const CVector4f& other) const
|
||||
{
|
||||
return ((x == other.x) && (y == other.y) && (z == other.z) && (w == other.w));
|
||||
}
|
||||
|
||||
// ************ VECTOR/FLOAT ************
|
||||
CVector4f CVector4f::operator+(const float src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x + src;
|
||||
out.y = this->y + src;
|
||||
out.z = this->z + src;
|
||||
out.w = this->w + src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator-(const float src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x - src;
|
||||
out.y = this->y - src;
|
||||
out.z = this->z - src;
|
||||
out.w = this->w - src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator*(const float src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x * src;
|
||||
out.y = this->y * src;
|
||||
out.z = this->z * src;
|
||||
out.w = this->w * src;
|
||||
return out;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator/(const float src) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = this->x / src;
|
||||
out.y = this->y / src;
|
||||
out.z = this->z / src;
|
||||
out.w = this->w / src;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector4f::operator+=(const float other)
|
||||
{
|
||||
*this = *this + other;
|
||||
}
|
||||
|
||||
void CVector4f::operator-=(const float other)
|
||||
{
|
||||
*this = *this - other;
|
||||
}
|
||||
|
||||
void CVector4f::operator*=(const float other)
|
||||
{
|
||||
*this = *this * other;
|
||||
}
|
||||
|
||||
void CVector4f::operator/=(const float other)
|
||||
{
|
||||
*this = *this / other;
|
||||
}
|
||||
|
||||
// ************ VECTOR/MATRIX ************
|
||||
CVector4f CVector4f::operator*(const CTransform4f& mtx) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = (x * mtx[0][0]) + (y * mtx[1][0]) + (z * mtx[2][0]);
|
||||
out.y = (x * mtx[0][1]) + (y * mtx[1][1]) + (z * mtx[2][1]);
|
||||
out.z = (x * mtx[0][2]) + (y * mtx[1][2]) + (z * mtx[2][2]);
|
||||
out.w = (x * mtx[0][3]) + (y * mtx[1][3]) + (z * mtx[2][3]) + w;
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector4f::operator*=(const CTransform4f& mtx)
|
||||
{
|
||||
*this = *this * mtx;
|
||||
}
|
||||
|
||||
CVector4f CVector4f::operator*(const CMatrix4f& mtx) const
|
||||
{
|
||||
CVector4f out;
|
||||
out.x = (x * mtx[0][0]) + (y * mtx[1][0]) + (z * mtx[2][0]) + (w * mtx[3][0]);
|
||||
out.y = (x * mtx[0][1]) + (y * mtx[1][1]) + (z * mtx[2][1]) + (w * mtx[3][1]);
|
||||
out.z = (x * mtx[0][2]) + (y * mtx[1][2]) + (z * mtx[2][2]) + (w * mtx[3][2]);
|
||||
out.w = (x * mtx[0][3]) + (y * mtx[1][3]) + (z * mtx[2][3]) + (w * mtx[3][3]);
|
||||
return out;
|
||||
}
|
||||
|
||||
void CVector4f::operator*=(const CMatrix4f& mtx)
|
||||
{
|
||||
*this = *this * mtx;
|
||||
}
|
||||
|
||||
// ************ UNARY ************
|
||||
float& CVector4f::operator[](long index)
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef CVECTOR4F
|
||||
#define CVECTOR4F
|
||||
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
|
||||
class CMatrix4f;
|
||||
class CTransform4f;
|
||||
class CVector2f;
|
||||
class CVector3f;
|
||||
|
||||
class CVector4f
|
||||
{
|
||||
public:
|
||||
float x, y, z, w;
|
||||
|
||||
CVector4f();
|
||||
CVector4f(float xyzw);
|
||||
CVector4f(float _x, float _y, float _z, float _w);
|
||||
CVector4f(const CVector2f& xy, float _z, float _w);
|
||||
CVector4f(const CVector3f& xyz);
|
||||
CVector4f(const CVector3f& xyz, float _w);
|
||||
CVector4f(CInputStream& Input);
|
||||
void Write(COutputStream& Output);
|
||||
|
||||
// Swizzle
|
||||
CVector3f xyz();
|
||||
CVector3f xzw();
|
||||
CVector3f yzw();
|
||||
CVector2f xy();
|
||||
CVector2f xz();
|
||||
CVector2f xw();
|
||||
CVector2f yz();
|
||||
CVector2f yw();
|
||||
CVector2f zw();
|
||||
|
||||
// Vector/Vector
|
||||
CVector4f operator+(const CVector4f& other) const;
|
||||
CVector4f operator-(const CVector4f& other) const;
|
||||
CVector4f operator*(const CVector4f& other) const;
|
||||
CVector4f operator/(const CVector4f& other) const;
|
||||
void operator+=(const CVector4f& other);
|
||||
void operator-=(const CVector4f& other);
|
||||
void operator*=(const CVector4f& other);
|
||||
void operator/=(const CVector4f& other);
|
||||
bool operator==(const CVector4f& other) const;
|
||||
|
||||
// Vector/Float
|
||||
CVector4f operator+(const float other) const;
|
||||
CVector4f operator-(const float other) const;
|
||||
CVector4f operator*(const float other) const;
|
||||
CVector4f operator/(const float other) const;
|
||||
void operator+=(const float other);
|
||||
void operator-=(const float other);
|
||||
void operator*=(const float other);
|
||||
void operator/=(const float other);
|
||||
|
||||
// Vector/Matrix
|
||||
CVector4f operator*(const CTransform4f& mtx) const;
|
||||
void operator*=(const CTransform4f& mtx);
|
||||
CVector4f operator*(const CMatrix4f& mtx) const;
|
||||
void operator*=(const CMatrix4f& mtx);
|
||||
|
||||
// Unary
|
||||
float& operator[](long index);
|
||||
};
|
||||
|
||||
#endif // CVECTOR4F
|
|
@ -0,0 +1,39 @@
|
|||
#include "types.h"
|
||||
#include <lzo/lzo1x.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace CompressionUtil
|
||||
{
|
||||
bool DecompressAreaLZO(u8 *src, u32 src_len, u8 *dst, u32 dst_len)
|
||||
{
|
||||
u8 *src_end = src + src_len;
|
||||
u8 *dst_end = dst + dst_len;
|
||||
|
||||
lzo_init();
|
||||
lzo_uint decmp;
|
||||
|
||||
while ((src < src_end) && (dst < dst_end))
|
||||
{
|
||||
u8 a = *src++;
|
||||
u8 b = *src++;
|
||||
u16 size = (a << 8) | b;
|
||||
|
||||
if (size >= 0xC000)
|
||||
{
|
||||
size = 0x10000 - size;
|
||||
memcpy(dst, src, size);
|
||||
dst += size;
|
||||
src += size;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lzo1x_decompress(src, size, dst, &decmp, LZO1X_MEM_DECOMPRESS);
|
||||
src += size;
|
||||
dst += decmp;
|
||||
}
|
||||
}
|
||||
|
||||
return ((src == src_end) && (dst == dst_end));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef COMPRESSIONUTIL_H
|
||||
#define COMPRESSIONUTIL_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace CompressionUtil
|
||||
{
|
||||
bool DecompressAreaLZO(u8 *src, u32 src_len, u8 *dst, u32 dst_len);
|
||||
}
|
||||
|
||||
#endif // COMPRESSIONUTIL_H
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef EKEYINPUTS
|
||||
#define EKEYINPUTS
|
||||
|
||||
#include "EnumUtil.h"
|
||||
|
||||
enum EKeyInputs
|
||||
{
|
||||
eNoKeys = 0,
|
||||
eCtrlKey = 0x1,
|
||||
eAltKey = 0x2,
|
||||
eQKey = 0x4,
|
||||
eWKey = 0x8,
|
||||
eEKey = 0x10,
|
||||
eAKey = 0x20,
|
||||
eSKey = 0x40,
|
||||
eDKey = 0x80
|
||||
};
|
||||
DEFINE_ENUM_FLAGS(EKeyInputs)
|
||||
|
||||
#endif // EKEYINPUTS
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef EMOUSEINPUTS
|
||||
#define EMOUSEINPUTS
|
||||
|
||||
#include "EnumUtil.h"
|
||||
|
||||
enum EMouseInputs
|
||||
{
|
||||
eLeftButton = 0x1,
|
||||
eMiddleButton = 0x2,
|
||||
eRightButton = 0x4
|
||||
};
|
||||
DEFINE_ENUM_FLAGS(EMouseInputs)
|
||||
|
||||
#endif // EMOUSEINPUTS
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef ENUMUTIL
|
||||
#define ENUMUTIL
|
||||
|
||||
#define DEFINE_ENUM_FLAGS(X) \
|
||||
inline X operator|(const X& A, const X& B) { \
|
||||
return (X) ((int) A | (int) B); \
|
||||
} \
|
||||
inline void operator|= (X& A, X& B) { \
|
||||
A = A | B; \
|
||||
} \
|
||||
inline X operator|(const X& A, const int B) { \
|
||||
return (X) ((int) A | B); \
|
||||
} \
|
||||
inline void operator|= (X& A, int B) { \
|
||||
A = A | B; \
|
||||
}
|
||||
|
||||
#endif // ENUMUTIL
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
#include "Math.h"
|
||||
|
||||
namespace Math
|
||||
{
|
||||
|
||||
float Pow(float Base, float Exponent)
|
||||
{
|
||||
return pow(Base, Exponent);
|
||||
}
|
||||
|
||||
float Distance(const CVector3f& A, const CVector3f& B)
|
||||
{
|
||||
return sqrtf( Pow(B.x - A.x, 2.f) +
|
||||
Pow(B.y - A.y, 2.f) +
|
||||
Pow(B.z - A.z, 2.f) );
|
||||
}
|
||||
|
||||
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box)
|
||||
{
|
||||
// Code slightly modified from Ogre
|
||||
// https://github.com/ehsan/ogre/blob/master/OgreMain/src/OgreMath.cpp
|
||||
if (Box.IsNull()) return std::pair<bool,float>(false, 0);
|
||||
if (Box.IsInfinite()) return std::pair<bool,float>(true, 0);
|
||||
|
||||
float lowt = 0.0f;
|
||||
float t;
|
||||
bool Hit = false;
|
||||
CVector3f HitPoint;
|
||||
const CVector3f& RayOrig = Ray.Origin();
|
||||
const CVector3f& RayDir = Ray.Direction();
|
||||
const CVector3f Min = Box.Min();
|
||||
const CVector3f Max = Box.Max();
|
||||
|
||||
// Check origin inside first
|
||||
if ( RayOrig > Min && RayOrig < Max )
|
||||
{
|
||||
return std::pair<bool, float>(true, 0);
|
||||
}
|
||||
|
||||
// Check each face in turn, only check closest 3
|
||||
// Min x
|
||||
if (RayOrig.x <= Min.x && RayDir.x > 0)
|
||||
{
|
||||
t = (Min.x - RayOrig.x) / RayDir.x;
|
||||
if (t >= 0)
|
||||
{
|
||||
// Substitute t back into ray and check bounds and dist
|
||||
HitPoint = RayOrig + RayDir * t;
|
||||
if (HitPoint.y >= Min.y && HitPoint.y <= Max.y &&
|
||||
HitPoint.z >= Min.z && HitPoint.z <= Max.z &&
|
||||
(!Hit || t < lowt))
|
||||
{
|
||||
Hit = true;
|
||||
lowt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Max x
|
||||
if (RayOrig.x >= Max.x && RayDir.x < 0)
|
||||
{
|
||||
t = (Max.x - RayOrig.x) / RayDir.x;
|
||||
if (t >= 0)
|
||||
{
|
||||
// Substitute t back into ray and check bounds and dist
|
||||
HitPoint = RayOrig + RayDir * t;
|
||||
if (HitPoint.y >= Min.y && HitPoint.y <= Max.y &&
|
||||
HitPoint.z >= Min.z && HitPoint.z <= Max.z &&
|
||||
(!Hit || t < lowt))
|
||||
{
|
||||
Hit = true;
|
||||
lowt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Min y
|
||||
if (RayOrig.y <= Min.y && RayDir.y > 0)
|
||||
{
|
||||
t = (Min.y - RayOrig.y) / RayDir.y;
|
||||
if (t >= 0)
|
||||
{
|
||||
// Substitute t back into ray and check bounds and dist
|
||||
HitPoint = RayOrig + RayDir * t;
|
||||
if (HitPoint.x >= Min.x && HitPoint.x <= Max.x &&
|
||||
HitPoint.z >= Min.z && HitPoint.z <= Max.z &&
|
||||
(!Hit || t < lowt))
|
||||
{
|
||||
Hit = true;
|
||||
lowt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Max y
|
||||
if (RayOrig.y >= Max.y && RayDir.y < 0)
|
||||
{
|
||||
t = (Max.y - RayOrig.y) / RayDir.y;
|
||||
if (t >= 0)
|
||||
{
|
||||
// Substitute t back into ray and check bounds and dist
|
||||
HitPoint = RayOrig + RayDir * t;
|
||||
if (HitPoint.x >= Min.x && HitPoint.x <= Max.x &&
|
||||
HitPoint.z >= Min.z && HitPoint.z <= Max.z &&
|
||||
(!Hit || t < lowt))
|
||||
{
|
||||
Hit = true;
|
||||
lowt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Min z
|
||||
if (RayOrig.z <= Min.z && RayDir.z > 0)
|
||||
{
|
||||
t = (Min.z - RayOrig.z) / RayDir.z;
|
||||
if (t >= 0)
|
||||
{
|
||||
// Substitute t back into ray and check bounds and dist
|
||||
HitPoint = RayOrig + RayDir * t;
|
||||
if (HitPoint.x >= Min.x && HitPoint.x <= Max.x &&
|
||||
HitPoint.y >= Min.y && HitPoint.y <= Max.y &&
|
||||
(!Hit || t < lowt))
|
||||
{
|
||||
Hit = true;
|
||||
lowt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Max z
|
||||
if (RayOrig.z >= Max.z && RayDir.z < 0)
|
||||
{
|
||||
t = (Max.z - RayOrig.z) / RayDir.z;
|
||||
if (t >= 0)
|
||||
{
|
||||
// Substitute t back into ray and check bounds and dist
|
||||
HitPoint = RayOrig + RayDir * t;
|
||||
if (HitPoint.x >= Min.x && HitPoint.x <= Max.x &&
|
||||
HitPoint.y >= Min.y && HitPoint.y <= Max.y &&
|
||||
(!Hit || t < lowt))
|
||||
{
|
||||
Hit = true;
|
||||
lowt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<bool,float>(Hit, lowt);
|
||||
}
|
||||
|
||||
std::pair<bool,float> RayTriangleIntersection(const CRay& Ray,
|
||||
const CVector3f& vtxA, const CVector3f& vtxB,
|
||||
const CVector3f& vtxC, bool AllowBackfaces)
|
||||
{
|
||||
// Ogre code cuz I'm lazy and bad at math
|
||||
// https://github.com/ehsan/ogre/blob/master/OgreMain/src/OgreMath.cpp#L709
|
||||
CVector3f FaceNormal = (vtxB - vtxA).Cross(vtxC - vtxA);
|
||||
|
||||
//
|
||||
// Calculate intersection with plane.
|
||||
//
|
||||
float t;
|
||||
{
|
||||
float denom = FaceNormal.Dot(Ray.Direction());
|
||||
|
||||
// Check intersect side
|
||||
if (denom > + std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
if (!AllowBackfaces)
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
else if (denom < - std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
if (false)
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parallel or triangle area is close to zero when
|
||||
// the plane normal not normalised.
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
|
||||
t = FaceNormal.Dot(vtxA - Ray.Origin()) / denom;
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
// Intersection is behind origin
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the largest area projection plane in X, Y or Z.
|
||||
//
|
||||
size_t i0, i1;
|
||||
{
|
||||
float n0 = fabs(FaceNormal[0]);
|
||||
float n1 = fabs(FaceNormal[1]);
|
||||
float n2 = fabs(FaceNormal[2]);
|
||||
|
||||
i0 = 1; i1 = 2;
|
||||
if (n1 > n2)
|
||||
{
|
||||
if (n1 > n0) i0 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n2 > n0) i1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check the intersection point is inside the triangle.
|
||||
//
|
||||
{
|
||||
float u1 = vtxB[i0] - vtxA[i0];
|
||||
float v1 = vtxB[i1] - vtxA[i1];
|
||||
float u2 = vtxC[i0] - vtxA[i0];
|
||||
float v2 = vtxC[i1] - vtxA[i1];
|
||||
float u0 = t * Ray.Direction()[i0] + Ray.Origin()[i0] - vtxA[i0];
|
||||
float v0 = t * Ray.Direction()[i1] + Ray.Origin()[i1] - vtxA[i1];
|
||||
|
||||
float alpha = u0 * v2 - u2 * v0;
|
||||
float beta = u1 * v0 - u0 * v1;
|
||||
float area = u1 * v2 - u2 * v1;
|
||||
|
||||
// epsilon to avoid float precision error
|
||||
const float EPSILON = 1e-6f;
|
||||
|
||||
float tolerance = - EPSILON * area;
|
||||
|
||||
if (area > 0)
|
||||
{
|
||||
if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<bool,float>(true, t);
|
||||
}
|
||||
|
||||
} // End namespace
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef MATH
|
||||
#define MATH
|
||||
|
||||
#include "CAABox.h"
|
||||
#include "CRay.h"
|
||||
#include "CVector3f.h"
|
||||
#include "SRayIntersection.h"
|
||||
#include <utility>
|
||||
|
||||
namespace Math
|
||||
{
|
||||
|
||||
float Pow(float Base, float Exponent);
|
||||
|
||||
float Distance(const CVector3f& A, const CVector3f& B);
|
||||
|
||||
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box);
|
||||
|
||||
std::pair<bool,float> RayTriangleIntersection(const CRay& Ray, const CVector3f& PointA,
|
||||
const CVector3f& PointB, const CVector3f& PointC,
|
||||
bool AllowBackfaces = false);
|
||||
}
|
||||
|
||||
#endif // MATH
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef SRAYINTERSECTION
|
||||
#define SRAYINTERSECTION
|
||||
|
||||
#include "types.h"
|
||||
class CSceneNode;
|
||||
|
||||
struct SRayIntersection
|
||||
{
|
||||
bool Hit;
|
||||
float Distance;
|
||||
CSceneNode *pNode;
|
||||
u32 AssetIndex;
|
||||
|
||||
SRayIntersection() {}
|
||||
SRayIntersection(bool _Hit, float _Distance, CSceneNode *_pNode, u32 _AssetIndex)
|
||||
: Hit(_Hit), Distance(_Distance), pNode(_pNode), AssetIndex(_AssetIndex) {}
|
||||
};
|
||||
|
||||
#endif // SRAYINTERSECTION
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include <FileIO/IOUtil.h> // For SwapBytes
|
||||
|
||||
namespace StringUtil
|
||||
{
|
||||
std::string GetFileDirectory(std::string path)
|
||||
{
|
||||
size_t endpath = path.find_last_of("\\/");
|
||||
return path.substr(0, endpath + 1);
|
||||
}
|
||||
|
||||
std::string GetFileName(std::string path)
|
||||
{
|
||||
size_t endpath = path.find_last_of("\\/") + 1;
|
||||
size_t endname = path.find_last_of(".");
|
||||
return path.substr(endpath, endname - endpath);
|
||||
}
|
||||
|
||||
std::string GetFileNameWithExtension(std::string path)
|
||||
{
|
||||
size_t endpath = path.find_last_of("\\/");
|
||||
return path.substr(endpath + 1, path.size() - endpath);
|
||||
}
|
||||
|
||||
std::string GetPathWithoutExtension(std::string path)
|
||||
{
|
||||
size_t endname = path.find_last_of(".");
|
||||
return path.substr(0, endname);
|
||||
}
|
||||
|
||||
std::string GetExtension(std::string path)
|
||||
{
|
||||
size_t endname = path.find_last_of(".");
|
||||
return path.substr(endname + 1, path.size() - endname);
|
||||
}
|
||||
|
||||
|
||||
// Not convinced stringstream is the best way to do string conversions of asset IDs - don't know of a better way tho
|
||||
std::string ResToStr(unsigned long assetID)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << std::hex << std::setw(8) << std::setfill('0') << assetID << std::dec;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
std::string ResToStr(unsigned long long assetID)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << std::hex << std::setw(16) << std::setfill('0') << assetID << std::dec;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
std::string ToUpper(std::string str)
|
||||
{
|
||||
for (unsigned int i = 0; i < str.length(); i++)
|
||||
{
|
||||
if ((str[i] >= 0x61) && (str[i] <= 0x7A))
|
||||
str[i] -= 0x20;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string ToLower(std::string str)
|
||||
{
|
||||
for (unsigned int i = 0; i < str.length(); i++)
|
||||
{
|
||||
if ((str[i] >= 0x41) && (str[i] <= 0x5A))
|
||||
str[i] += 0x20;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string ToHexString(unsigned char num, bool addPrefix, int width)
|
||||
{
|
||||
return ToHexString((unsigned long) num, addPrefix, width);
|
||||
}
|
||||
|
||||
std::string ToHexString(unsigned short num, bool addPrefix, int width)
|
||||
{
|
||||
return ToHexString((unsigned long) num, addPrefix, width);
|
||||
}
|
||||
|
||||
std::string ToHexString(unsigned long num, bool addPrefix, int width)
|
||||
{
|
||||
std::stringstream str;
|
||||
if (addPrefix) str << "0x";
|
||||
str << std::hex << std::setw(width) << std::setfill('0') << num;
|
||||
return str.str();
|
||||
}
|
||||
|
||||
long Hash32(std::string str)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
|
||||
for (unsigned int c = 0; c < str.size(); c++) {
|
||||
hash += str[c];
|
||||
hash *= 101;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
long long Hash64(std::string str)
|
||||
{
|
||||
unsigned long long hash = 0;
|
||||
|
||||
for (unsigned int c = 0; c < str.size(); c++) {
|
||||
hash += str[c];
|
||||
hash *= 101;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
long StrToRes32(std::string str) {
|
||||
return std::stoul(str, nullptr, 16);
|
||||
}
|
||||
|
||||
long long StrToRes64(std::string str) {
|
||||
return std::stoull(str, nullptr, 16);
|
||||
}
|
||||
|
||||
void StrToRes128(std::string str, char *out) {
|
||||
long long Part1 = std::stoull(str.substr(0, 16), nullptr, 16);
|
||||
long long Part2 = std::stoull(str.substr(16, 16), nullptr, 16);
|
||||
|
||||
if (IOUtil::SystemEndianness == IOUtil::LittleEndian)
|
||||
{
|
||||
IOUtil::SwapBytes(Part1);
|
||||
IOUtil::SwapBytes(Part2);
|
||||
}
|
||||
|
||||
memcpy(out, &Part1, 8);
|
||||
memcpy(out + 8, &Part2, 8);
|
||||
}
|
||||
|
||||
long GetResID32(std::string str)
|
||||
{
|
||||
long resID;
|
||||
if (IsHexString(str, false, 8))
|
||||
resID = StrToRes32(str);
|
||||
else
|
||||
resID = Hash32(GetFileName(str));
|
||||
return resID;
|
||||
}
|
||||
|
||||
bool IsHexString(std::string str, bool requirePrefix, long width)
|
||||
{
|
||||
str = GetFileName(str);
|
||||
|
||||
if (requirePrefix && (str.substr(0, 2) != "0x"))
|
||||
return false;
|
||||
|
||||
if ((width == -1) && (str.substr(0, 2) == "0x"))
|
||||
str = str.substr(2, str.size() - 2);
|
||||
|
||||
if (width == -1)
|
||||
width = str.size();
|
||||
|
||||
if ((str.size() == width + 2) && (str.substr(0, 2) == "0x"))
|
||||
str = str.substr(2, width);
|
||||
|
||||
if (str.size() != width) return false;
|
||||
|
||||
for (int c = 0; c < width; c++)
|
||||
{
|
||||
char chr = str[c];
|
||||
if (!((chr >= '0') && (chr <= '9')) &&
|
||||
!((chr >= 'a') && (chr <= 'f')) &&
|
||||
!((chr >= 'A') && (chr <= 'F')))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string AppendSlash(std::string str)
|
||||
{
|
||||
char a = str.back();
|
||||
char b = str[str.length() - 1];
|
||||
|
||||
if (a == 0)
|
||||
{
|
||||
if ((b != '/') && (b != '\\'))
|
||||
{
|
||||
str.back() = '/';
|
||||
str.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
else if ((a != '/') && (b != '\\'))
|
||||
str.push_back('/');
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
std::wstring UTF8to16(std::string str)
|
||||
{
|
||||
const char *cstr = str.c_str();
|
||||
std::vector<int> CodePoints;
|
||||
|
||||
// Step 1: decode UTF-8 code points
|
||||
while (cstr[0])
|
||||
{
|
||||
int CodePoint;
|
||||
|
||||
// One byte
|
||||
if ((cstr[0] & 0x80000000) == 0)
|
||||
{
|
||||
CodePoint = cstr[0] & 0x7FFFFFFF;
|
||||
cstr++;
|
||||
}
|
||||
|
||||
// Two bytes
|
||||
else if ((cstr[0] & 0xE0) == 0xC0)
|
||||
{
|
||||
CodePoint = (((cstr[0] & 0x1F) << 6) |
|
||||
(cstr[1] & 0x3F));
|
||||
cstr += 2;
|
||||
}
|
||||
|
||||
// Three bytes
|
||||
else if ((cstr[0] & 0xF0) == 0xE0)
|
||||
{
|
||||
CodePoint = (((cstr[0] & 0xF) << 12) |
|
||||
((cstr[1] & 0x3F) << 6) |
|
||||
(cstr[2] & 0x3F));
|
||||
cstr += 3;
|
||||
}
|
||||
|
||||
// Four bytes
|
||||
else if ((cstr[0] & 0xF8) == 0xF0)
|
||||
{
|
||||
CodePoint = (((cstr[0] & 0x7) << 18) |
|
||||
((cstr[1] & 0x3F) << 12) |
|
||||
((cstr[2] & 0x3F) << 6) |
|
||||
(cstr[3] & 0x3F));
|
||||
cstr += 4;
|
||||
}
|
||||
|
||||
// Five bytes
|
||||
else if ((cstr[0] & 0xFC) == 0xF8)
|
||||
{
|
||||
CodePoint = (((cstr[0] & 0x3) << 24) |
|
||||
((cstr[1] & 0x3F) << 18) |
|
||||
((cstr[2] & 0x3F) << 12) |
|
||||
((cstr[3] & 0x3F) << 6) |
|
||||
(cstr[4] & 0x3F));
|
||||
cstr += 5;
|
||||
}
|
||||
|
||||
// Six bytes
|
||||
else if ((cstr[0] & 0xFE) == 0xFC)
|
||||
{
|
||||
CodePoint = (((cstr[0] & 0x1) << 30) |
|
||||
((cstr[1] & 0x3F) << 24) |
|
||||
((cstr[2] & 0x3F) << 18) |
|
||||
((cstr[3] & 0x3F) << 12) |
|
||||
((cstr[4] & 0x3F) << 6) |
|
||||
(cstr[5] & 0x3F));
|
||||
cstr += 6;
|
||||
}
|
||||
|
||||
CodePoints.push_back(CodePoint);
|
||||
}
|
||||
|
||||
// Step 2: encode as UTF-16
|
||||
std::wstring out;
|
||||
out.reserve(CodePoints.size());
|
||||
|
||||
for (int c = 0; c < CodePoints.size(); c++)
|
||||
{
|
||||
// todo: support all code points
|
||||
if (((CodePoints[c] >= 0) && (CodePoints[c] <= 0xD7FF)) ||
|
||||
((CodePoints[c] >= 0xE000) && (CodePoints[c] <= 0xFFFF)))
|
||||
{
|
||||
out.push_back(CodePoints[c] & 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
CStringList Tokenize(const std::string& str, const char *pTokens)
|
||||
{
|
||||
CStringList out;
|
||||
int lastSplit = 0;
|
||||
|
||||
// Iterate over all characters in the input string
|
||||
for (int iChr = 0; iChr < str.length(); iChr++)
|
||||
{
|
||||
// Check whether this character is one of the user-provided tokens
|
||||
for (int iTok = 0; true; iTok++)
|
||||
{
|
||||
if (!pTokens[iTok]) break;
|
||||
|
||||
if (str[iChr] == pTokens[iTok])
|
||||
{
|
||||
// Token found - split string
|
||||
if (iChr > lastSplit)
|
||||
out.push_back(str.substr(lastSplit, iChr - lastSplit));
|
||||
|
||||
lastSplit = iChr + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add final string
|
||||
if (lastSplit != str.length())
|
||||
out.push_back(str.substr(lastSplit, str.length() - lastSplit));
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef STRINGUTIL_H
|
||||
#define STRINGUTIL_H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
typedef std::list<std::string> CStringList;
|
||||
|
||||
namespace StringUtil
|
||||
{
|
||||
std::string GetFileDirectory(std::string path);
|
||||
std::string GetFileName(std::string path);
|
||||
std::string GetFileNameWithExtension(std::string path);
|
||||
std::string GetPathWithoutExtension(std::string path);
|
||||
std::string GetExtension(std::string path);
|
||||
std::string ResToStr(unsigned long ID);
|
||||
std::string ResToStr(unsigned long long ID);
|
||||
std::string ToUpper(std::string str);
|
||||
std::string ToLower(std::string str);
|
||||
std::string ToHexString(unsigned char num, bool addPrefix = true, int width = 0);
|
||||
std::string ToHexString(unsigned short num, bool addPrefix = true, int width = 0);
|
||||
std::string ToHexString(unsigned long num, bool addPrefix = true, int width = 0);
|
||||
long Hash32(std::string str);
|
||||
long long Hash64(std::string str);
|
||||
long StrToRes32(std::string str);
|
||||
long long StrToRes64(std::string str);
|
||||
void StrToRes128(std::string str, char *out);
|
||||
long GetResID32(std::string str);
|
||||
bool IsHexString(std::string str, bool requirePrefix = false, long width = -1);
|
||||
std::string AppendSlash(std::string str);
|
||||
CStringList Tokenize(const std::string& str, const char *pTokens);
|
||||
|
||||
std::wstring UTF8to16(std::string str);
|
||||
}
|
||||
|
||||
#endif // STRINGUTIL_H
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned long u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed long s32;
|
||||
typedef signed long long s64;
|
||||
|
||||
|
||||
|
||||
#endif // TYPES_H
|
|
@ -0,0 +1,55 @@
|
|||
#include "CAreaAttributes.h"
|
||||
#include <Resource/script/CMasterTemplate.h>
|
||||
#include <Resource/script/CScriptLayer.h>
|
||||
|
||||
CAreaAttributes::CAreaAttributes(CScriptObject *pObj)
|
||||
{
|
||||
SetObject(pObj);
|
||||
}
|
||||
|
||||
CAreaAttributes::~CAreaAttributes()
|
||||
{
|
||||
}
|
||||
|
||||
void CAreaAttributes::SetObject(CScriptObject *pObj)
|
||||
{
|
||||
mpObj = pObj;
|
||||
mGame = pObj->Template()->MasterTemplate()->GetGame();
|
||||
}
|
||||
|
||||
bool CAreaAttributes::IsLayerEnabled()
|
||||
{
|
||||
return mpObj->Layer()->IsActive();
|
||||
}
|
||||
|
||||
bool CAreaAttributes::IsSkyEnabled()
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = mpObj->Properties();
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrime:
|
||||
case eEchoes:
|
||||
return static_cast<CBoolProperty*>(pBaseStruct->PropertyByIndex(1))->Get();
|
||||
case eCorruption:
|
||||
return static_cast<CBoolProperty*>(pBaseStruct->PropertyByIndex(9))->Get();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CModel* CAreaAttributes::SkyModel()
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = mpObj->Properties();
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrime:
|
||||
case eEchoes:
|
||||
return (CModel*) static_cast<CFileProperty*>(pBaseStruct->PropertyByIndex(7))->Get();
|
||||
case eCorruption:
|
||||
return (CModel*) static_cast<CFileProperty*>(pBaseStruct->PropertyByIndex(8))->Get();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef CAREAATTRIBUTES_H
|
||||
#define CAREAATTRIBUTES_H
|
||||
|
||||
#include <Resource/script/CScriptObject.h>
|
||||
|
||||
class CAreaAttributes
|
||||
{
|
||||
EGame mGame;
|
||||
CScriptObject *mpObj;
|
||||
|
||||
public:
|
||||
CAreaAttributes(CScriptObject *pObj);
|
||||
~CAreaAttributes();
|
||||
void SetObject(CScriptObject *pObj);
|
||||
bool IsLayerEnabled();
|
||||
bool IsSkyEnabled();
|
||||
CModel* SkyModel();
|
||||
};
|
||||
|
||||
#endif // CAREAATTRIBUTES_H
|
|
@ -0,0 +1,286 @@
|
|||
#include "CCamera.h"
|
||||
#include "CGraphics.h"
|
||||
#include <Common/CQuaternion.h>
|
||||
|
||||
#include <gtc/matrix_transform.hpp>
|
||||
|
||||
#define HALF_PI 1.570796371f
|
||||
|
||||
CCamera::CCamera()
|
||||
{
|
||||
mMode = eFreeCamera;
|
||||
mPosition = CVector3f(0);
|
||||
mAspectRatio = 1.7777777f;
|
||||
|
||||
mYaw = -HALF_PI;
|
||||
mPitch = 0.0f;
|
||||
CalculateDirection();
|
||||
|
||||
mMoveSpeed = 1.f; // Old: 0.01f
|
||||
mLookSpeed = 1.f; // Old: 0.003f
|
||||
mViewOutdated = true;
|
||||
mProjectionOutdated = true;
|
||||
}
|
||||
|
||||
CCamera::CCamera(CVector3f Position, CVector3f)
|
||||
{
|
||||
// todo: make it actually look at the target!
|
||||
// Not using parameter 2 (CVector3f - Target)
|
||||
mMode = eFreeCamera;
|
||||
mMoveSpeed = 1.f; // Old: 0.01f
|
||||
mLookSpeed = 1.f; // Old: 0.003f
|
||||
mPosition = Position;
|
||||
mYaw = -HALF_PI;
|
||||
mPitch = 0.0f;
|
||||
CalculateDirection();
|
||||
}
|
||||
|
||||
void CCamera::Pan(float XAmount, float YAmount)
|
||||
{
|
||||
switch (mMode)
|
||||
{
|
||||
|
||||
case eFreeCamera:
|
||||
{
|
||||
CVector3f Right(
|
||||
cos(mYaw - HALF_PI),
|
||||
sin(mYaw - HALF_PI),
|
||||
0
|
||||
);
|
||||
CVector3f Up = Right.Cross(mDirection);
|
||||
|
||||
mPosition += Right * (XAmount * mMoveSpeed);
|
||||
mPosition += Up * (YAmount * mMoveSpeed);
|
||||
mViewOutdated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Unfinished
|
||||
case eOrbitCamera:
|
||||
{
|
||||
CVector3f Right(
|
||||
cos(mYaw - HALF_PI),
|
||||
sin(mYaw - HALF_PI),
|
||||
0
|
||||
);
|
||||
CVector3f Up = Right.Cross(mDirection);
|
||||
|
||||
CVector3f TargetDirection = mPosition - mOrbitTarget;
|
||||
//CMatrix4f YawRotation = CQuaternion::F
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::Rotate(float XAmount, float YAmount)
|
||||
{
|
||||
switch (mMode)
|
||||
{
|
||||
case eFreeCamera:
|
||||
mYaw -= (XAmount * mLookSpeed * 0.3f);
|
||||
mPitch -= (YAmount * mLookSpeed * 0.3f);
|
||||
mViewOutdated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::Zoom(float Amount)
|
||||
{
|
||||
mPosition += (mDirection * Amount) * (mMoveSpeed * 25.f);
|
||||
mViewOutdated = true;
|
||||
}
|
||||
|
||||
void CCamera::Snap(CVector3f Position)
|
||||
{
|
||||
mPosition = Position;
|
||||
mYaw = -1.570796371f;
|
||||
mPitch = 0.0f;
|
||||
mViewOutdated = true;
|
||||
}
|
||||
|
||||
void CCamera::ProcessKeyInput(EKeyInputs KeyFlags, double DeltaTime)
|
||||
{
|
||||
float FDeltaTime = (float) DeltaTime;
|
||||
if (mMode == eFreeCamera)
|
||||
{
|
||||
if (KeyFlags & eWKey) Zoom(FDeltaTime);
|
||||
if (KeyFlags & eSKey) Zoom(-FDeltaTime);
|
||||
if (KeyFlags & eQKey) Pan(0, -FDeltaTime * 25.f);
|
||||
if (KeyFlags & eEKey) Pan(0, FDeltaTime * 25.f);
|
||||
if (KeyFlags & eAKey) Pan(-FDeltaTime * 25.f, 0);
|
||||
if (KeyFlags & eDKey) Pan(FDeltaTime * 25.f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::ProcessMouseInput(EKeyInputs KeyFlags, EMouseInputs MouseFlags, float XMovement, float YMovement)
|
||||
{
|
||||
// Free Camera
|
||||
if (mMode == eFreeCamera)
|
||||
{
|
||||
if (MouseFlags & eMiddleButton)
|
||||
{
|
||||
if (KeyFlags & eCtrlKey) Zoom(-YMovement * 0.2f);
|
||||
else Pan(-XMovement, YMovement);
|
||||
}
|
||||
|
||||
else if (MouseFlags & eRightButton) Rotate(XMovement, YMovement);
|
||||
}
|
||||
|
||||
// Orbit Camera
|
||||
else if (mMode == eOrbitCamera)
|
||||
{
|
||||
if ((MouseFlags & eMiddleButton) && (KeyFlags & eCtrlKey))
|
||||
Zoom(-YMovement * 0.2f);
|
||||
|
||||
else if ((MouseFlags & eMiddleButton) || (MouseFlags & eRightButton))
|
||||
Pan(XMovement, YMovement);
|
||||
}
|
||||
}
|
||||
|
||||
CRay CCamera::CastRay(CVector2f DeviceCoords)
|
||||
{
|
||||
CMatrix4f InverseVP = (ViewMatrix().Transpose() * ProjectionMatrix().Transpose()).Inverse();
|
||||
|
||||
CVector3f RayOrigin = CVector3f(DeviceCoords.x, DeviceCoords.y, -1.f) * InverseVP;
|
||||
CVector3f RayTarget = CVector3f(DeviceCoords.x, DeviceCoords.y, 0.f) * InverseVP;
|
||||
CVector3f RayDir = (RayTarget - RayOrigin).Normalized();
|
||||
|
||||
CRay Ray;
|
||||
Ray.SetOrigin(RayOrigin);
|
||||
Ray.SetDirection(RayDir);
|
||||
return Ray;
|
||||
}
|
||||
|
||||
void CCamera::LoadMatrices()
|
||||
{
|
||||
CGraphics::sMVPBlock.ViewMatrix = ViewMatrix();
|
||||
CGraphics::sMVPBlock.ProjectionMatrix = ProjectionMatrix();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
CVector3f CCamera::Position() const
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
CVector3f CCamera::GetDirection() const
|
||||
{
|
||||
return mDirection;
|
||||
}
|
||||
|
||||
float CCamera::GetYaw() const
|
||||
{
|
||||
return mYaw;
|
||||
}
|
||||
|
||||
float CCamera::GetPitch() const
|
||||
{
|
||||
return mPitch;
|
||||
}
|
||||
|
||||
|
||||
const CMatrix4f& CCamera::ViewMatrix()
|
||||
{
|
||||
if (mViewOutdated)
|
||||
CalculateView();
|
||||
|
||||
return mCachedViewMatrix;
|
||||
}
|
||||
|
||||
const CMatrix4f& CCamera::ProjectionMatrix()
|
||||
{
|
||||
if (mProjectionOutdated)
|
||||
CalculateProjection();
|
||||
|
||||
return mCachedProjectionMatrix;
|
||||
}
|
||||
|
||||
// ************ SETTERS ************
|
||||
void CCamera::SetPosition(CVector3f Position)
|
||||
{
|
||||
mPosition = Position;
|
||||
mViewOutdated = true;
|
||||
}
|
||||
|
||||
void CCamera::SetDirection(CVector3f Direction)
|
||||
{
|
||||
mDirection = Direction;
|
||||
mViewOutdated = true;
|
||||
}
|
||||
|
||||
void CCamera::SetYaw(float Yaw)
|
||||
{
|
||||
mYaw = Yaw;
|
||||
}
|
||||
|
||||
void CCamera::SetPitch(float Pitch)
|
||||
{
|
||||
mPitch = Pitch;
|
||||
}
|
||||
|
||||
void CCamera::SetMoveSpeed(float MoveSpeed)
|
||||
{
|
||||
mMoveSpeed = MoveSpeed;
|
||||
}
|
||||
|
||||
void CCamera::SetLookSpeed(float LookSpeed)
|
||||
{
|
||||
mLookSpeed = LookSpeed;
|
||||
}
|
||||
|
||||
void CCamera::SetFree()
|
||||
{
|
||||
mMode = eFreeCamera;
|
||||
}
|
||||
|
||||
void CCamera::SetOrbit(const CVector3f& OrbitTarget)
|
||||
{
|
||||
mMode = eOrbitCamera;
|
||||
mOrbitTarget = OrbitTarget;
|
||||
}
|
||||
|
||||
void CCamera::SetAspectRatio(float AspectRatio)
|
||||
{
|
||||
mAspectRatio = AspectRatio;
|
||||
mProjectionOutdated = true;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CCamera::CalculateDirection()
|
||||
{
|
||||
if (mPitch > HALF_PI) mPitch = HALF_PI;
|
||||
if (mPitch < -HALF_PI) mPitch = -HALF_PI;
|
||||
|
||||
mDirection = CVector3f(
|
||||
cos(mPitch) * cos(mYaw),
|
||||
cos(mPitch) * sin(mYaw),
|
||||
sin(mPitch)
|
||||
);
|
||||
}
|
||||
|
||||
void CCamera::CalculateView()
|
||||
{
|
||||
// todo: don't use glm
|
||||
CalculateDirection();
|
||||
|
||||
CVector3f Right(
|
||||
cos(mYaw - HALF_PI),
|
||||
sin(mYaw - HALF_PI),
|
||||
0
|
||||
);
|
||||
|
||||
CVector3f Up = Right.Cross(mDirection);
|
||||
|
||||
glm::vec3 glmpos(mPosition.x, mPosition.y, mPosition.z);
|
||||
glm::vec3 glmdir(mDirection.x, mDirection.y, mDirection.z);
|
||||
glm::vec3 glmup(Up.x, Up.y, Up.z);
|
||||
mCachedViewMatrix = CMatrix4f::FromGlmMat4(glm::lookAt(glmpos, glmpos + glmdir, glmup)).Transpose();
|
||||
mViewOutdated = false;
|
||||
}
|
||||
|
||||
void CCamera::CalculateProjection()
|
||||
{
|
||||
// todo: don't use glm
|
||||
mCachedProjectionMatrix = CMatrix4f::FromGlmMat4(glm::perspective(55.f, mAspectRatio, 0.1f, 4096.f)).Transpose();
|
||||
mProjectionOutdated = false;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef CCAMERA_H
|
||||
#define CCAMERA_H
|
||||
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <Common/CRay.h>
|
||||
#include <Common/CVector2i.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Common/types.h>
|
||||
#include <Common/EKeyInputs.h>
|
||||
#include <Common/EMouseInputs.h>
|
||||
|
||||
enum ECameraMoveMode
|
||||
{
|
||||
eFreeCamera, eOrbitCamera
|
||||
};
|
||||
|
||||
class CCamera
|
||||
{
|
||||
ECameraMoveMode mMode;
|
||||
CVector3f mPosition;
|
||||
CVector3f mDirection;
|
||||
float mAspectRatio;
|
||||
|
||||
float mYaw;
|
||||
float mPitch;
|
||||
CVector3f mOrbitTarget;
|
||||
float mMoveSpeed;
|
||||
float mLookSpeed;
|
||||
|
||||
CMatrix4f mCachedViewMatrix;
|
||||
CMatrix4f mCachedProjectionMatrix;
|
||||
bool mViewOutdated;
|
||||
bool mProjectionOutdated;
|
||||
|
||||
public:
|
||||
CCamera();
|
||||
CCamera(CVector3f Position, CVector3f Target);
|
||||
|
||||
void Pan(float XAmount, float YAmount);
|
||||
void Rotate(float XAmount, float YAmount);
|
||||
void Zoom(float Amount);
|
||||
void Snap(CVector3f Position);
|
||||
void ProcessKeyInput(EKeyInputs KeyFlags, double DeltaTime);
|
||||
void ProcessMouseInput(EKeyInputs KeyFlags, EMouseInputs MouseFlags, float XMovement, float YMovement);
|
||||
CRay CastRay(CVector2f DeviceCoords);
|
||||
void LoadMatrices();
|
||||
|
||||
// Getters
|
||||
CVector3f Position() const;
|
||||
CVector3f GetDirection() const;
|
||||
float GetYaw() const;
|
||||
float GetPitch() const;
|
||||
const CMatrix4f& ViewMatrix();
|
||||
const CMatrix4f& ProjectionMatrix();
|
||||
|
||||
// Setters
|
||||
void SetPosition(CVector3f Position);
|
||||
void SetDirection(CVector3f Direction);
|
||||
void SetYaw(float Yaw);
|
||||
void SetPitch(float Pitch);
|
||||
void SetMoveSpeed(float MoveSpeed);
|
||||
void SetLookSpeed(float LookSpeed);
|
||||
void SetFree();
|
||||
void SetOrbit(const CVector3f& OrbitTarget);
|
||||
void SetOrbit(const CAABox& OrbitTarget);
|
||||
void SetAspectRatio(float AspectRatio);
|
||||
|
||||
// Private
|
||||
private:
|
||||
void CalculateDirection();
|
||||
void CalculateView();
|
||||
void CalculateProjection();
|
||||
};
|
||||
|
||||
#endif // CCAMERA_H
|
|
@ -0,0 +1,436 @@
|
|||
#include "CDrawUtil.h"
|
||||
#include "CGraphics.h"
|
||||
#include "CResCache.h"
|
||||
#include <Common/CTransform4f.h>
|
||||
#include <iostream>
|
||||
#include "Log.h"
|
||||
|
||||
// ************ MEMBER INITIALIZATION ************
|
||||
CVertexBuffer CDrawUtil::mGridVertices;
|
||||
CIndexBuffer CDrawUtil::mGridIndices;
|
||||
|
||||
CDynamicVertexBuffer CDrawUtil::mSquareVertices;
|
||||
CIndexBuffer CDrawUtil::mSquareIndices;
|
||||
|
||||
CDynamicVertexBuffer CDrawUtil::mLineVertices;
|
||||
CIndexBuffer CDrawUtil::mLineIndices;
|
||||
|
||||
CModel *CDrawUtil::mpCubeModel;
|
||||
CToken CDrawUtil::mCubeToken;
|
||||
|
||||
CVertexBuffer CDrawUtil::mWireCubeVertices;
|
||||
CIndexBuffer CDrawUtil::mWireCubeIndices;
|
||||
|
||||
CModel *CDrawUtil::mpSphereModel;
|
||||
CModel *CDrawUtil::mpDoubleSidedSphereModel;
|
||||
CToken CDrawUtil::mSphereToken;
|
||||
CToken CDrawUtil::mDoubleSidedSphereToken;
|
||||
|
||||
CShader *CDrawUtil::mpColorShader;
|
||||
CShader *CDrawUtil::mpColorShaderLighting;
|
||||
CShader *CDrawUtil::mpTextureShader;
|
||||
CShader *CDrawUtil::mpCollisionShader;
|
||||
CShader *CDrawUtil::mpTextShader;
|
||||
|
||||
CTexture *CDrawUtil::mpCheckerTexture;
|
||||
CToken CDrawUtil::mCheckerTextureToken;
|
||||
|
||||
bool CDrawUtil::mDrawUtilInitialized = false;
|
||||
|
||||
// ************ PUBLIC ************
|
||||
void CDrawUtil::DrawGrid()
|
||||
{
|
||||
Init();
|
||||
|
||||
mGridVertices.Bind();
|
||||
|
||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
glLineWidth(1.0f);
|
||||
UseColorShader(CColor(0.6f, 0.6f, 0.6f, 0.f));
|
||||
mGridIndices.DrawElements(0, mGridIndices.GetSize() - 4);
|
||||
|
||||
glLineWidth(1.5f);
|
||||
UseColorShader(CColor::skTransparentBlack);
|
||||
mGridIndices.DrawElements(mGridIndices.GetSize() - 4, 4);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawSquare()
|
||||
{
|
||||
// Overload with default tex coords
|
||||
CVector2f TexCoords[4] = { CVector2f(0.f, 1.f), CVector2f(1.f, 1.f), CVector2f(1.f, 0.f), CVector2f(0.f, 0.f) };
|
||||
DrawSquare(&TexCoords[0].x);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawSquare(const CVector2f& TexUL, const CVector2f& TexUR, const CVector2f& TexBR, const CVector2f& TexBL)
|
||||
{
|
||||
// Overload with tex coords specified via parameters
|
||||
// I don't think that parameters are guaranteed to be contiguous in memory, so:
|
||||
CVector2f TexCoords[4] = { TexUL, TexUR, TexBR, TexBL };
|
||||
DrawSquare(&TexCoords[0].x);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawSquare(const float *pTexCoords)
|
||||
{
|
||||
Init();
|
||||
|
||||
// Set tex coords
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
{
|
||||
EVertexDescription TexAttrib = (EVertexDescription) (eTex0 << (iTex *2));
|
||||
mSquareVertices.BufferAttrib(TexAttrib, pTexCoords);
|
||||
}
|
||||
|
||||
// Draw
|
||||
mSquareVertices.Bind();
|
||||
mSquareIndices.DrawElements();
|
||||
mSquareVertices.Unbind();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawLine(const CVector3f& PointA, const CVector3f& PointB)
|
||||
{
|
||||
DrawLine(PointA, PointB, CColor::skWhite);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawLine(const CVector3f& PointA, const CVector3f& PointB, const CColor& LineColor)
|
||||
{
|
||||
Init();
|
||||
|
||||
glLineWidth(1.f);
|
||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Copy vec3s into an array to ensure they are adjacent in memory
|
||||
CVector3f Points[2] = { PointA, PointB };
|
||||
mLineVertices.BufferAttrib(ePosition, Points);
|
||||
|
||||
// Draw
|
||||
UseColorShader(LineColor);
|
||||
mLineVertices.Bind();
|
||||
mLineIndices.DrawElements();
|
||||
mLineVertices.Unbind();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawCube()
|
||||
{
|
||||
Init();
|
||||
mpCubeModel->Draw(eNoMaterialSetup, 0);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawCube(const CColor& Color)
|
||||
{
|
||||
Init();
|
||||
UseColorShader(Color);
|
||||
DrawCube();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawShadedCube(const CColor& Color)
|
||||
{
|
||||
Init();
|
||||
UseColorShaderLighting(Color);
|
||||
DrawCube();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawWireCube()
|
||||
{
|
||||
Init();
|
||||
glLineWidth(1.f);
|
||||
mWireCubeVertices.Bind();
|
||||
mWireCubeIndices.DrawElements();
|
||||
mWireCubeVertices.Unbind();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawWireCube(const CAABox& kAABox, const CColor& kColor)
|
||||
{
|
||||
Init();
|
||||
|
||||
// Calculate model matrix
|
||||
CTransform4f Transform;
|
||||
Transform.Scale(kAABox.GetSize());
|
||||
Transform.Translate(kAABox.Center());
|
||||
CGraphics::sMVPBlock.ModelMatrix = Transform.ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
UseColorShader(kColor);
|
||||
DrawWireCube();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawSphere(bool DoubleSided)
|
||||
{
|
||||
Init();
|
||||
|
||||
if (!DoubleSided)
|
||||
mpSphereModel->Draw(eNoMaterialSetup, 0);
|
||||
else
|
||||
mpDoubleSidedSphereModel->Draw(eNoMaterialSetup, 0);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawSphere(const CColor &kColor)
|
||||
{
|
||||
Init();
|
||||
UseColorShader(kColor);
|
||||
DrawSphere(false);
|
||||
}
|
||||
|
||||
void CDrawUtil::UseColorShader(const CColor& kColor)
|
||||
{
|
||||
Init();
|
||||
mpColorShader->SetCurrent();
|
||||
|
||||
GLuint ColorLoc = mpColorShader->GetUniformLocation("ColorIn");
|
||||
CVector4f ColorVec4 = kColor.ToVector4f();
|
||||
glUniform4f(ColorLoc, ColorVec4.x, ColorVec4.y, ColorVec4.z, ColorVec4.w);
|
||||
|
||||
CMaterial::KillCachedMaterial();
|
||||
}
|
||||
|
||||
void CDrawUtil::UseColorShaderLighting(const CColor& kColor)
|
||||
{
|
||||
Init();
|
||||
mpColorShaderLighting->SetCurrent();
|
||||
|
||||
GLuint NumLightsLoc = mpColorShaderLighting->GetUniformLocation("NumLights");
|
||||
glUniform1i(NumLightsLoc, CGraphics::sNumLights);
|
||||
|
||||
GLuint ColorLoc = mpColorShaderLighting->GetUniformLocation("ColorIn");
|
||||
CVector4f ColorVec4 = kColor.ToVector4f();
|
||||
glUniform4f(ColorLoc, ColorVec4.x, ColorVec4.y, ColorVec4.z, ColorVec4.w);
|
||||
|
||||
CMaterial::KillCachedMaterial();
|
||||
}
|
||||
|
||||
void CDrawUtil::UseTextureShader()
|
||||
{
|
||||
UseTextureShader(CColor::skWhite);
|
||||
}
|
||||
|
||||
void CDrawUtil::UseTextureShader(const CColor& TintColor)
|
||||
{
|
||||
Init();
|
||||
mpTextureShader->SetCurrent();
|
||||
|
||||
GLuint TintColorLoc = mpTextureShader->GetUniformLocation("TintColor");
|
||||
CVector4f TintVec4 = TintColor.ToVector4f();
|
||||
glUniform4f(TintColorLoc, TintVec4.x, TintVec4.y, TintVec4.z, TintVec4.w);
|
||||
|
||||
CMaterial::KillCachedMaterial();
|
||||
}
|
||||
|
||||
void CDrawUtil::UseCollisionShader()
|
||||
{
|
||||
Init();
|
||||
mpCollisionShader->SetCurrent();
|
||||
LoadCheckerboardTexture(0);
|
||||
|
||||
CMaterial::KillCachedMaterial();
|
||||
}
|
||||
|
||||
CShader* CDrawUtil::GetTextShader()
|
||||
{
|
||||
Init();
|
||||
return mpTextShader;
|
||||
}
|
||||
|
||||
void CDrawUtil::LoadCheckerboardTexture(u32 GLTextureUnit)
|
||||
{
|
||||
Init();
|
||||
mpCheckerTexture->Bind(GLTextureUnit);
|
||||
}
|
||||
|
||||
CModel* CDrawUtil::GetCubeModel()
|
||||
{
|
||||
Init();
|
||||
return mpCubeModel;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
CDrawUtil::CDrawUtil()
|
||||
{
|
||||
}
|
||||
|
||||
void CDrawUtil::Init()
|
||||
{
|
||||
if (!mDrawUtilInitialized)
|
||||
{
|
||||
Log::Write("Initializing CDrawUtil");
|
||||
InitGrid();
|
||||
InitSquare();
|
||||
InitLine();
|
||||
InitCube();
|
||||
InitWireCube();
|
||||
InitSphere();
|
||||
InitShaders();
|
||||
InitTextures();
|
||||
mDrawUtilInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CDrawUtil::InitGrid()
|
||||
{
|
||||
Log::Write("Creating grid");
|
||||
mGridVertices.SetVertexDesc(ePosition);
|
||||
mGridVertices.Reserve(64);
|
||||
|
||||
for (s32 i = -7; i < 8; i++)
|
||||
{
|
||||
if (i == 0) continue;
|
||||
mGridVertices.AddVertex(CVector3f(-7.0f, float(i), 0.0f));
|
||||
mGridVertices.AddVertex(CVector3f( 7.0f, float(i), 0.0f));
|
||||
mGridVertices.AddVertex(CVector3f(float(i), -7.0f, 0.0f));
|
||||
mGridVertices.AddVertex(CVector3f(float(i), 7.0f, 0.0f));
|
||||
}
|
||||
|
||||
mGridVertices.AddVertex(CVector3f(-7.0f, 0, 0.0f));
|
||||
mGridVertices.AddVertex(CVector3f( 7.0f, 0, 0.0f));
|
||||
mGridVertices.AddVertex(CVector3f(0, -7.0f, 0.0f));
|
||||
mGridVertices.AddVertex(CVector3f(0, 7.0f, 0.0f));
|
||||
|
||||
mGridIndices.Reserve(60);
|
||||
for (u16 i = 0; i < 60; i++) mGridIndices.AddIndex(i);
|
||||
mGridIndices.SetPrimitiveType(GL_LINES);
|
||||
}
|
||||
|
||||
void CDrawUtil::InitSquare()
|
||||
{
|
||||
Log::Write("Creating square");
|
||||
mSquareVertices.SetActiveAttribs(ePosition | eNormal |
|
||||
eTex0 | eTex1 | eTex2 | eTex3 |
|
||||
eTex4 | eTex5 | eTex6 | eTex7);
|
||||
mSquareVertices.SetVertexCount(4);
|
||||
|
||||
CVector3f SquareVertices[] = {
|
||||
CVector3f(-1.f, 1.f, 0.f),
|
||||
CVector3f( 1.f, 1.f, 0.f),
|
||||
CVector3f( 1.f, -1.f, 0.f),
|
||||
CVector3f(-1.f, -1.f, 0.f)
|
||||
};
|
||||
|
||||
CVector3f SquareNormals[] = {
|
||||
CVector3f(0.f, 0.f, 1.f),
|
||||
CVector3f(0.f, 0.f, 1.f),
|
||||
CVector3f(0.f, 0.f, 1.f),
|
||||
CVector3f(0.f, 0.f, 1.f)
|
||||
};
|
||||
|
||||
CVector2f SquareTexCoords[] = {
|
||||
CVector2f(0.f, 1.f),
|
||||
CVector2f(1.f, 1.f),
|
||||
CVector2f(1.f, 0.f),
|
||||
CVector2f(0.f, 0.f)
|
||||
};
|
||||
|
||||
mSquareVertices.BufferAttrib(ePosition, SquareVertices);
|
||||
mSquareVertices.BufferAttrib(eNormal, SquareNormals);
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
{
|
||||
EVertexDescription Attrib = (EVertexDescription) (eTex0 << (iTex *2));
|
||||
mSquareVertices.BufferAttrib(Attrib, SquareTexCoords);
|
||||
}
|
||||
|
||||
mSquareIndices.Reserve(4);
|
||||
mSquareIndices.SetPrimitiveType(GL_TRIANGLE_STRIP);
|
||||
mSquareIndices.AddIndex(3);
|
||||
mSquareIndices.AddIndex(2);
|
||||
mSquareIndices.AddIndex(0);
|
||||
mSquareIndices.AddIndex(1);
|
||||
}
|
||||
|
||||
void CDrawUtil::InitLine()
|
||||
{
|
||||
Log::Write("Creating line");
|
||||
mLineVertices.SetActiveAttribs(ePosition);
|
||||
mLineVertices.SetVertexCount(2);
|
||||
|
||||
mLineIndices.Reserve(2);
|
||||
mLineIndices.SetPrimitiveType(GL_LINES);
|
||||
mLineIndices.AddIndex(0);
|
||||
mLineIndices.AddIndex(1);
|
||||
}
|
||||
|
||||
void CDrawUtil::InitCube()
|
||||
{
|
||||
Log::Write("Creating cube");
|
||||
mpCubeModel = (CModel*) gResCache.GetResource("../resources/Cube.cmdl");
|
||||
mCubeToken = CToken(mpCubeModel);
|
||||
}
|
||||
|
||||
void CDrawUtil::InitWireCube()
|
||||
{
|
||||
Log::Write("Creating wire cube");
|
||||
mWireCubeVertices.SetVertexDesc(ePosition);
|
||||
mWireCubeVertices.Reserve(8);
|
||||
mWireCubeVertices.AddVertex(CVector3f(-0.5f, -0.5f, -0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f(-0.5f, 0.5f, -0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f( 0.5f, 0.5f, -0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f( 0.5f, -0.5f, -0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f(-0.5f, -0.5f, 0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f( 0.5f, -0.5f, 0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f( 0.5f, 0.5f, 0.5f));
|
||||
mWireCubeVertices.AddVertex(CVector3f(-0.5f, 0.5f, 0.5f));
|
||||
|
||||
u16 Indices[] = {
|
||||
0, 1,
|
||||
1, 2,
|
||||
2, 3,
|
||||
3, 0,
|
||||
4, 5,
|
||||
5, 6,
|
||||
6, 7,
|
||||
7, 4,
|
||||
0, 4,
|
||||
1, 7,
|
||||
2, 6,
|
||||
3, 5
|
||||
};
|
||||
mWireCubeIndices.AddIndices(Indices, sizeof(Indices) / sizeof(u16));
|
||||
mWireCubeIndices.SetPrimitiveType(GL_LINES);
|
||||
}
|
||||
|
||||
void CDrawUtil::InitSphere()
|
||||
{
|
||||
Log::Write("Creating sphere");
|
||||
mpSphereModel = (CModel*) gResCache.GetResource("../resources/Sphere.cmdl");
|
||||
mpDoubleSidedSphereModel = (CModel*) gResCache.GetResource("../resources/SphereDoubleSided.cmdl");
|
||||
mSphereToken = CToken(mpSphereModel);
|
||||
mDoubleSidedSphereToken = CToken(mpDoubleSidedSphereModel);
|
||||
}
|
||||
|
||||
void CDrawUtil::InitShaders()
|
||||
{
|
||||
Log::Write("Creating shaders");
|
||||
mpColorShader = CShader::FromResourceFile("ColorShader");
|
||||
mpColorShaderLighting = CShader::FromResourceFile("ColorShaderLighting");
|
||||
mpTextureShader = CShader::FromResourceFile("TextureShader");
|
||||
mpCollisionShader = CShader::FromResourceFile("CollisionShader");
|
||||
mpTextShader = CShader::FromResourceFile("TextShader");
|
||||
}
|
||||
|
||||
void CDrawUtil::InitTextures()
|
||||
{
|
||||
Log::Write("Loading checkerboard texture");
|
||||
mpCheckerTexture = (CTexture*) gResCache.GetResource("../resources/Checkerboard.txtr");
|
||||
mCheckerTextureToken = CToken(mpCheckerTexture);
|
||||
}
|
||||
|
||||
void CDrawUtil::Shutdown()
|
||||
{
|
||||
if (mDrawUtilInitialized)
|
||||
{
|
||||
Log::Write("Shutting down");
|
||||
mCubeToken = CToken();
|
||||
mSphereToken = CToken();
|
||||
mDoubleSidedSphereToken = CToken();
|
||||
delete mpColorShader;
|
||||
delete mpColorShaderLighting;
|
||||
delete mpTextureShader;
|
||||
delete mpCollisionShader;
|
||||
delete mpTextShader;
|
||||
mDrawUtilInitialized = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#ifndef CDRAWUTIL
|
||||
#define CDRAWUTIL
|
||||
|
||||
#include <OpenGL/CVertexBuffer.h>
|
||||
#include <OpenGL/CDynamicVertexBuffer.h>
|
||||
#include <OpenGL/CIndexBuffer.h>
|
||||
#include <Resource/model/CModel.h>
|
||||
|
||||
class CDrawUtil
|
||||
{
|
||||
// 7x7 Grid
|
||||
static CVertexBuffer mGridVertices;
|
||||
static CIndexBuffer mGridIndices;
|
||||
|
||||
// Square
|
||||
static CDynamicVertexBuffer mSquareVertices;
|
||||
static CIndexBuffer mSquareIndices;
|
||||
|
||||
// Line
|
||||
static CDynamicVertexBuffer mLineVertices;
|
||||
static CIndexBuffer mLineIndices;
|
||||
|
||||
// Cube
|
||||
static CModel *mpCubeModel;
|
||||
static CToken mCubeToken;
|
||||
|
||||
// Wire Cube
|
||||
static CVertexBuffer mWireCubeVertices;
|
||||
static CIndexBuffer mWireCubeIndices;
|
||||
|
||||
// Sphere
|
||||
static CModel *mpSphereModel;
|
||||
static CModel *mpDoubleSidedSphereModel;
|
||||
static CToken mSphereToken;
|
||||
static CToken mDoubleSidedSphereToken;
|
||||
|
||||
// Shaders
|
||||
static CShader *mpColorShader;
|
||||
static CShader *mpColorShaderLighting;
|
||||
static CShader *mpTextureShader;
|
||||
static CShader *mpCollisionShader;
|
||||
static CShader *mpTextShader;
|
||||
|
||||
// Textures
|
||||
static CTexture *mpCheckerTexture;
|
||||
static CToken mCheckerTextureToken;
|
||||
|
||||
// Have all the above members been initialized?
|
||||
static bool mDrawUtilInitialized;
|
||||
|
||||
public:
|
||||
static void DrawGrid();
|
||||
static void DrawSquare();
|
||||
static void DrawSquare(const CVector2f& TexUL, const CVector2f& TexUR, const CVector2f& TexBR, const CVector2f& TexBL);
|
||||
static void DrawSquare(const float *pTexCoords);
|
||||
static void DrawLine(const CVector3f& PointA, const CVector3f& PointB);
|
||||
static void DrawLine(const CVector3f& PointA, const CVector3f& PointB, const CColor& LineColor);
|
||||
static void DrawCube();
|
||||
static void DrawCube(const CColor& Color);
|
||||
static void DrawShadedCube(const CColor& Color);
|
||||
static void DrawWireCube();
|
||||
static void DrawWireCube(const CAABox& AABox, const CColor& Color);
|
||||
static void DrawSphere(bool DoubleSided = false);
|
||||
static void DrawSphere(const CColor& Color);
|
||||
static void UseColorShader(const CColor& Color);
|
||||
static void UseColorShaderLighting(const CColor& Color);
|
||||
static void UseTextureShader();
|
||||
static void UseTextureShader(const CColor& TintColor);
|
||||
static void UseCollisionShader();
|
||||
static CShader* GetTextShader();
|
||||
static void LoadCheckerboardTexture(u32 GLTextureUnit);
|
||||
static CModel* GetCubeModel();
|
||||
|
||||
private:
|
||||
CDrawUtil(); // Private constructor to prevent class from being instantiated
|
||||
static void Init();
|
||||
static void InitGrid();
|
||||
static void InitSquare();
|
||||
static void InitLine();
|
||||
static void InitCube();
|
||||
static void InitWireCube();
|
||||
static void InitSphere();
|
||||
static void InitShaders();
|
||||
static void InitTextures();
|
||||
|
||||
public:
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
#endif // CDRAWUTIL
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
#include "CGraphics.h"
|
||||
#include <OpenGL/CShader.h>
|
||||
#include <Resource/CMaterial.h>
|
||||
#include "Log.h"
|
||||
|
||||
// ************ MEMBER INITIALIZATION ************
|
||||
CUniformBuffer* CGraphics::mpMVPBlockBuffer;
|
||||
CUniformBuffer* CGraphics::mpVertexBlockBuffer;
|
||||
CUniformBuffer* CGraphics::mpPixelBlockBuffer;
|
||||
CUniformBuffer* CGraphics::mpLightBlockBuffer;
|
||||
u32 CGraphics::mContextIndices = 0;
|
||||
u32 CGraphics::mActiveContext = -1;
|
||||
bool CGraphics::mInitialized = false;
|
||||
std::vector<CVertexArrayManager*> CGraphics::mVAMs;
|
||||
|
||||
CGraphics::SMVPBlock CGraphics::sMVPBlock;
|
||||
CGraphics::SVertexBlock CGraphics::sVertexBlock;
|
||||
CGraphics::SPixelBlock CGraphics::sPixelBlock;
|
||||
CGraphics::SLightBlock CGraphics::sLightBlock;
|
||||
|
||||
CGraphics::ELightingMode CGraphics::sLightMode;
|
||||
u32 CGraphics::sNumLights;
|
||||
const CColor CGraphics::skDefaultAmbientColor = CColor(0.5f, 0.5f, 0.5f, 1.f);
|
||||
CColor CGraphics::sAreaAmbientColor = CColor::skBlack;
|
||||
float CGraphics::sWorldLightMultiplier;
|
||||
CLight CGraphics::sDefaultDirectionalLights[3] = {
|
||||
*CLight::BuildDirectional(CVector3f(0), CVector3f (0.f, -0.866025f, -0.5f), CColor(0.3f, 0.3f, 0.3f, 1.f)),
|
||||
*CLight::BuildDirectional(CVector3f(0), CVector3f(-0.75f, 0.433013f, -0.5f), CColor(0.3f, 0.3f, 0.3f, 1.f)),
|
||||
*CLight::BuildDirectional(CVector3f(0), CVector3f( 0.75f, 0.433013f, -0.5f), CColor(0.3f, 0.3f, 0.3f, 1.f))
|
||||
};
|
||||
|
||||
// ************ FUNCTIONS ************
|
||||
void CGraphics::Initialize()
|
||||
{
|
||||
if (!mInitialized)
|
||||
{
|
||||
Log::Write("Initializing GLEW");
|
||||
glewExperimental = true;
|
||||
glewInit();
|
||||
glGetError(); // This is to work around a glew bug - error is always set after initializing
|
||||
|
||||
Log::Write("Creating uniform buffers");
|
||||
mpMVPBlockBuffer = new CUniformBuffer(sizeof(sMVPBlock));
|
||||
mpVertexBlockBuffer = new CUniformBuffer(sizeof(sVertexBlock));
|
||||
mpPixelBlockBuffer = new CUniformBuffer(sizeof(sPixelBlock));
|
||||
mpLightBlockBuffer = new CUniformBuffer(sizeof(sLightBlock));
|
||||
|
||||
sLightMode = WorldLighting;
|
||||
sNumLights = 0;
|
||||
sWorldLightMultiplier = 1.f;
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
mpMVPBlockBuffer->BindBase(0);
|
||||
mpVertexBlockBuffer->BindBase(1);
|
||||
mpPixelBlockBuffer->BindBase(2);
|
||||
mpLightBlockBuffer->BindBase(3);
|
||||
}
|
||||
|
||||
void CGraphics::Shutdown()
|
||||
{
|
||||
if (mInitialized)
|
||||
{
|
||||
Log::Write("Shutting down CGraphics");
|
||||
delete mpMVPBlockBuffer;
|
||||
delete mpVertexBlockBuffer;
|
||||
delete mpPixelBlockBuffer;
|
||||
delete mpLightBlockBuffer;
|
||||
mInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::UpdateMVPBlock()
|
||||
{
|
||||
mpMVPBlockBuffer->Buffer(&sMVPBlock);
|
||||
}
|
||||
|
||||
void CGraphics::UpdateVertexBlock()
|
||||
{
|
||||
mpVertexBlockBuffer->Buffer(&sVertexBlock);
|
||||
}
|
||||
|
||||
void CGraphics::UpdatePixelBlock()
|
||||
{
|
||||
mpPixelBlockBuffer->Buffer(&sPixelBlock);
|
||||
}
|
||||
|
||||
void CGraphics::UpdateLightBlock()
|
||||
{
|
||||
mpLightBlockBuffer->Buffer(&sLightBlock);
|
||||
}
|
||||
|
||||
GLuint CGraphics::MVPBlockBindingPoint()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint CGraphics::VertexBlockBindingPoint()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
GLuint CGraphics::PixelBlockBindingPoint()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
GLuint CGraphics::LightBlockBindingPoint()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
u32 CGraphics::GetContextIndex()
|
||||
{
|
||||
for (u32 iCon = 0; iCon < 32; iCon++)
|
||||
{
|
||||
u32 Mask = (1 << iCon);
|
||||
if ((mContextIndices & Mask) == 0)
|
||||
{
|
||||
mContextIndices |= Mask;
|
||||
|
||||
CVertexArrayManager *pVAM = new CVertexArrayManager;
|
||||
if (mVAMs.size() >= iCon) mVAMs.resize(iCon + 1);
|
||||
mVAMs[iCon] = pVAM;
|
||||
|
||||
return iCon;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 CGraphics::GetActiveContext()
|
||||
{
|
||||
return mActiveContext;
|
||||
}
|
||||
|
||||
void CGraphics::ReleaseContext(u32 Index)
|
||||
{
|
||||
if (Index < 32) mContextIndices &= ~(1 << Index);
|
||||
if (mActiveContext == Index) mActiveContext = -1;
|
||||
delete mVAMs[Index];
|
||||
}
|
||||
|
||||
void CGraphics::SetActiveContext(u32 Index)
|
||||
{
|
||||
mActiveContext = Index;
|
||||
mVAMs[Index]->SetCurrent();
|
||||
CMaterial::KillCachedMaterial();
|
||||
CShader::KillCachedShader();
|
||||
}
|
||||
|
||||
void CGraphics::SetDefaultLighting()
|
||||
{
|
||||
sNumLights = 0; // CLight load function increments the light count by 1, which is why I set it to 0
|
||||
sDefaultDirectionalLights[0].Load();
|
||||
sDefaultDirectionalLights[1].Load();
|
||||
sDefaultDirectionalLights[2].Load();
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef CGRAPHICS_H
|
||||
#define CGRAPHICS_H
|
||||
|
||||
#include <Common/CColor.h>
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Common/CVector4f.h>
|
||||
#include <GL/glew.h>
|
||||
#include <OpenGL/CUniformBuffer.h>
|
||||
#include <OpenGL/CVertexArrayManager.h>
|
||||
#include <Resource/CLight.h>
|
||||
|
||||
class CGraphics
|
||||
{
|
||||
static CUniformBuffer *mpMVPBlockBuffer;
|
||||
static CUniformBuffer *mpVertexBlockBuffer;
|
||||
static CUniformBuffer *mpPixelBlockBuffer;
|
||||
static CUniformBuffer *mpLightBlockBuffer;
|
||||
static u32 mContextIndices;
|
||||
static u32 mActiveContext;
|
||||
static bool mInitialized;
|
||||
static std::vector<CVertexArrayManager*> mVAMs;
|
||||
|
||||
public:
|
||||
// SMVPBlock
|
||||
struct SMVPBlock
|
||||
{
|
||||
CMatrix4f ModelMatrix;
|
||||
CMatrix4f ViewMatrix;
|
||||
CMatrix4f ProjectionMatrix;
|
||||
};
|
||||
static SMVPBlock sMVPBlock;
|
||||
|
||||
// SVertexBlock
|
||||
struct SVertexBlock
|
||||
{
|
||||
CMatrix4f TexMatrices[10];
|
||||
CMatrix4f PostMatrices[20];
|
||||
CVector4f COLOR0_Amb;
|
||||
CVector4f COLOR0_Mat;
|
||||
CVector4f COLOR1_Amb;
|
||||
CVector4f COLOR1_Mat;
|
||||
};
|
||||
static SVertexBlock sVertexBlock;
|
||||
|
||||
// SPixelBlock
|
||||
struct SPixelBlock
|
||||
{
|
||||
CVector4f Konst[4];
|
||||
CVector4f TevColor;
|
||||
CVector4f TintColor;
|
||||
};
|
||||
static SPixelBlock sPixelBlock;
|
||||
|
||||
// SLightBlock
|
||||
struct SLightBlock
|
||||
{
|
||||
struct SGXLight
|
||||
{
|
||||
CVector4f Position;
|
||||
CVector4f Direction;
|
||||
CVector4f Color;
|
||||
CVector4f DistAtten;
|
||||
CVector4f AngleAtten;
|
||||
};
|
||||
SGXLight Lights[8];
|
||||
};
|
||||
static SLightBlock sLightBlock;
|
||||
|
||||
// Lighting-related
|
||||
enum ELightingMode { NoLighting, BasicLighting, WorldLighting };
|
||||
static ELightingMode sLightMode;
|
||||
static u32 sNumLights;
|
||||
static const CColor skDefaultAmbientColor;
|
||||
static CColor sAreaAmbientColor;
|
||||
static float sWorldLightMultiplier;
|
||||
static CLight sDefaultDirectionalLights[3];
|
||||
|
||||
// Functions
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
static void UpdateMVPBlock();
|
||||
static void UpdateVertexBlock();
|
||||
static void UpdatePixelBlock();
|
||||
static void UpdateLightBlock();
|
||||
static GLuint MVPBlockBindingPoint();
|
||||
static GLuint VertexBlockBindingPoint();
|
||||
static GLuint PixelBlockBindingPoint();
|
||||
static GLuint LightBlockBindingPoint();
|
||||
static u32 GetContextIndex();
|
||||
static u32 GetActiveContext();
|
||||
static void ReleaseContext(u32 Index);
|
||||
static void SetActiveContext(u32 Index);
|
||||
static void SetDefaultLighting();
|
||||
};
|
||||
|
||||
#endif // CGRAPHICS_H
|
|
@ -0,0 +1,89 @@
|
|||
#include "CRenderBucket.h"
|
||||
#include <algorithm>
|
||||
#include "CDrawUtil.h"
|
||||
#include "CGraphics.h"
|
||||
|
||||
CRenderBucket::CRenderBucket()
|
||||
{
|
||||
mEstSize = 0;
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
void CRenderBucket::SetSortType(ESortType Type)
|
||||
{
|
||||
mSortType = Type;
|
||||
}
|
||||
|
||||
void CRenderBucket::Add(const SMeshPointer& Mesh)
|
||||
{
|
||||
if (mSize >= mEstSize)
|
||||
mNodes.push_back(Mesh);
|
||||
else
|
||||
mNodes[mSize] = Mesh;
|
||||
|
||||
mSize++;
|
||||
}
|
||||
|
||||
void CRenderBucket::Sort(CCamera& Camera)
|
||||
{
|
||||
struct {
|
||||
CCamera *pCamera;
|
||||
bool operator()(SMeshPointer left, SMeshPointer right) {
|
||||
CVector3f cPos = pCamera->Position();
|
||||
CVector3f cDir = pCamera->GetDirection();
|
||||
|
||||
CVector3f distL = left.AABox.ClosestPointAlongVector(cDir) - cPos;
|
||||
float dotL = distL.Dot(cDir);
|
||||
CVector3f distR = right.AABox.ClosestPointAlongVector(cDir) - cPos;
|
||||
float dotR = distR.Dot(cDir);
|
||||
return (dotL > dotR);
|
||||
}
|
||||
} backToFront;
|
||||
backToFront.pCamera = &Camera;
|
||||
|
||||
if (mSortType == BackToFront)
|
||||
std::stable_sort(mNodes.begin(), mNodes.begin() + mSize, backToFront);
|
||||
|
||||
// Test: draw node bounding boxes + vertices used for sorting
|
||||
/*for (u32 iNode = 0; iNode < mNodes.size(); iNode++)
|
||||
{
|
||||
SMeshPointer *pNode = &mNodes[iNode];
|
||||
CVector3f Vert = pNode->AABox.ClosestPointAlongVector(Camera.GetDirection());
|
||||
CDrawUtil::DrawWireCube(pNode->AABox, CColor::skWhite);
|
||||
|
||||
CVector3f Dist = Vert - Camera.GetPosition();
|
||||
float Dot = Dist.Dot(Camera.GetDirection());
|
||||
if (Dot < 0.f) Dot = -Dot;
|
||||
if (Dot > 50.f) Dot = 50.f;
|
||||
float Intensity = 1.f - (Dot / 50.f);
|
||||
CColor CubeColor(Intensity, Intensity, Intensity, 1.f);
|
||||
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Vert).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
CDrawUtil::DrawCube(CubeColor);
|
||||
}*/
|
||||
}
|
||||
|
||||
void CRenderBucket::Clear()
|
||||
{
|
||||
mEstSize = mSize;
|
||||
if (mNodes.size() > mSize) mNodes.resize(mSize);
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
void CRenderBucket::Draw(ERenderOptions Options)
|
||||
{
|
||||
for (u32 n = 0; n < mSize; n++)
|
||||
{
|
||||
if (mNodes[n].Command == eDrawMesh)
|
||||
mNodes[n].pNode->Draw(Options);
|
||||
|
||||
else if (mNodes[n].Command == eDrawAsset)
|
||||
mNodes[n].pNode->DrawAsset(Options, mNodes[n].Asset);
|
||||
|
||||
else if (mNodes[n].Command == eDrawSelection)
|
||||
mNodes[n].pNode->DrawSelection();
|
||||
|
||||
// todo: implementation for eDrawExtras
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef CRENDERBUCKET_H
|
||||
#define CRENDERBUCKET_H
|
||||
|
||||
#include "CCamera.h"
|
||||
#include "ERenderOptions.h"
|
||||
#include <Common/types.h>
|
||||
#include <OpenGL/SMeshPointer.h>
|
||||
#include <vector>
|
||||
|
||||
class CRenderBucket
|
||||
{
|
||||
public:
|
||||
enum ESortType
|
||||
{
|
||||
BackToFront,
|
||||
FrontToBack
|
||||
};
|
||||
private:
|
||||
ESortType mSortType;
|
||||
std::vector<SMeshPointer> mNodes;
|
||||
u32 mEstSize;
|
||||
u32 mSize;
|
||||
|
||||
public:
|
||||
CRenderBucket();
|
||||
void SetSortType(ESortType Type);
|
||||
void Add(const SMeshPointer& Mesh);
|
||||
void Sort(CCamera& Camera);
|
||||
void Clear();
|
||||
void Draw(ERenderOptions Options);
|
||||
};
|
||||
|
||||
#endif // CRENDERBUCKET_H
|
|
@ -0,0 +1,328 @@
|
|||
#include "CRenderer.h"
|
||||
|
||||
#include "CDrawUtil.h"
|
||||
#include "CGraphics.h"
|
||||
#include "CResCache.h"
|
||||
#include <Common/AnimUtil.h>
|
||||
#include <Common/CTransform4f.h>
|
||||
#include <Resource/factory/CTextureDecoder.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <gtx/transform.hpp>
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
u32 CRenderer::sNumRenderers = 0;
|
||||
|
||||
// ************ INITIALIZATION ************
|
||||
CRenderer::CRenderer()
|
||||
{
|
||||
mOptions = eEnableUVScroll | eEnableBackfaceCull;
|
||||
mBloomMode = eNoBloom;
|
||||
mDrawGrid = true;
|
||||
mInitialized = false;
|
||||
mContextIndex = -1;
|
||||
mOpaqueBucket.SetSortType(CRenderBucket::FrontToBack);
|
||||
mTransparentBucket.SetSortType(CRenderBucket::BackToFront);
|
||||
sNumRenderers++;
|
||||
}
|
||||
|
||||
CRenderer::~CRenderer()
|
||||
{
|
||||
sNumRenderers--;
|
||||
|
||||
if (sNumRenderers == 0)
|
||||
{
|
||||
CGraphics::Shutdown();
|
||||
CDrawUtil::Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::Init()
|
||||
{
|
||||
if (!mInitialized)
|
||||
{
|
||||
CVector4f ClearVec = mClearColor.ToVector4f();
|
||||
glClearColor(ClearVec.x, ClearVec.y, ClearVec.z, ClearVec.w);
|
||||
mContextIndex = CGraphics::GetContextIndex();
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ GETTERS/SETTERS ************
|
||||
bool CRenderer::IsUVAnimationOn()
|
||||
{
|
||||
return ((mOptions & eUVScroll) != 0);
|
||||
}
|
||||
|
||||
void CRenderer::ToggleBackfaceCull(bool b)
|
||||
{
|
||||
mOptions = (ERenderOptions) ((mOptions & ~eEnableBackfaceCull) | (b << 1));
|
||||
}
|
||||
|
||||
void CRenderer::ToggleUVAnimation(bool b)
|
||||
{
|
||||
mOptions = (ERenderOptions) ((mOptions & ~eEnableUVScroll) | b);
|
||||
}
|
||||
|
||||
void CRenderer::ToggleGrid(bool b)
|
||||
{
|
||||
mDrawGrid = b;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleOccluders(bool b)
|
||||
{
|
||||
mOptions = (ERenderOptions) ((mOptions & ~eEnableOccluders) | (b << 2));
|
||||
}
|
||||
|
||||
void CRenderer::ToggleAlphaDisabled(bool b)
|
||||
{
|
||||
mOptions = (ERenderOptions) ((mOptions & ~eNoAlpha) | (b << 5));
|
||||
}
|
||||
|
||||
void CRenderer::SetBloom(EBloomMode BloomMode)
|
||||
{
|
||||
mBloomMode = BloomMode;
|
||||
|
||||
if (BloomMode != eNoBloom)
|
||||
mOptions = (ERenderOptions) (mOptions | eEnableBloom);
|
||||
else
|
||||
mOptions = (ERenderOptions) (mOptions & ~eEnableBloom);
|
||||
}
|
||||
|
||||
void CRenderer::SetFont(CFont *pFont)
|
||||
{
|
||||
}
|
||||
|
||||
void CRenderer::SetClearColor(CColor Clear)
|
||||
{
|
||||
mClearColor = Clear;
|
||||
CVector4f ClearVec = Clear.ToVector4f();
|
||||
ClearVec.w = 0.f;
|
||||
glClearColor(ClearVec.x, ClearVec.y, ClearVec.z, ClearVec.w);
|
||||
}
|
||||
|
||||
void CRenderer::SetViewportSize(u32 Width, u32 Height)
|
||||
{
|
||||
mViewportWidth = Width;
|
||||
mViewportHeight = Height;
|
||||
mBloomHScale = ((float) Width / 640);
|
||||
mBloomVScale = ((float) Height / 528);
|
||||
mBloomWidth = (u32) (320 * mBloomHScale);
|
||||
mBloomHeight = (u32) (224 * mBloomVScale);
|
||||
mBloomHScale = 1.f / mBloomHScale;
|
||||
mBloomVScale = 1.f / mBloomVScale;
|
||||
}
|
||||
|
||||
// ************ RENDER ************
|
||||
void CRenderer::RenderScene(CCamera& Camera)
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
|
||||
// Render scene to texture
|
||||
glDepthRange(0.f, 1.f);
|
||||
|
||||
mOpaqueBucket.Draw(mOptions);
|
||||
mOpaqueBucket.Clear();
|
||||
mTransparentBucket.Sort(Camera);
|
||||
mTransparentBucket.Draw(mOptions);
|
||||
mTransparentBucket.Clear();
|
||||
}
|
||||
|
||||
void CRenderer::RenderBloom()
|
||||
{
|
||||
// Setup
|
||||
static const float skHOffset[6] = { -0.008595f, -0.005470f, -0.002345f,
|
||||
0.002345f, 0.005470f, 0.008595f };
|
||||
|
||||
static const float skVOffset[6] = { -0.012275f, -0.007815f, -0.003350f,
|
||||
0.003350f, 0.007815f, 0.012275f };
|
||||
|
||||
static const CColor skTintColors[6] = { CColor((u8) 17, 17, 17, 255),
|
||||
CColor((u8) 53, 53, 53, 255),
|
||||
CColor((u8) 89, 89, 89, 255),
|
||||
CColor((u8) 89, 89, 89, 255),
|
||||
CColor((u8) 53, 53, 53, 255),
|
||||
CColor((u8) 17, 17, 17, 255) };
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, mBloomWidth, mBloomHeight);
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Pass 1: Alpha-blend the scene texture on a black background
|
||||
mBloomFramebuffers[0].Resize(mBloomWidth, mBloomHeight);
|
||||
mBloomFramebuffers[0].Bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
CDrawUtil::UseTextureShader();
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
|
||||
mSceneFramebuffer.Texture()->Bind(0);
|
||||
CDrawUtil::DrawSquare();
|
||||
|
||||
// Pass 2: Horizontal blur
|
||||
mBloomFramebuffers[1].Resize(mBloomWidth, mBloomHeight);
|
||||
mBloomFramebuffers[1].Bind();
|
||||
|
||||
CDrawUtil::UseTextureShader(CColor::skGray);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
mBloomFramebuffers[0].Texture()->Bind(0);
|
||||
CDrawUtil::DrawSquare();
|
||||
|
||||
for (u32 iPass = 0; iPass < 6; iPass++)
|
||||
{
|
||||
CDrawUtil::UseTextureShader(skTintColors[iPass]);
|
||||
CVector3f Translate(skHOffset[iPass] * mBloomHScale, 0.f, 0.f);
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Translate).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
CDrawUtil::DrawSquare();
|
||||
}
|
||||
|
||||
// Pass 3: Vertical blur
|
||||
mBloomFramebuffers[2].Resize(mBloomWidth, mBloomHeight);
|
||||
mBloomFramebuffers[2].Bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
CDrawUtil::UseTextureShader(CColor::skGray);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
mBloomFramebuffers[1].Texture()->Bind(0);
|
||||
CDrawUtil::DrawSquare();
|
||||
|
||||
for (u32 iPass = 0; iPass < 6; iPass++)
|
||||
{
|
||||
CDrawUtil::UseTextureShader(skTintColors[iPass]);
|
||||
CVector3f Translate(0.f, skVOffset[iPass] * mBloomVScale, 0.f);
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Translate).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
CDrawUtil::DrawSquare();
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::RenderSky(CModel *pSkyboxModel, CVector3f CameraPosition)
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
|
||||
if (!pSkyboxModel) return;
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
CTransform4f ModelMtx;
|
||||
ModelMtx.Translate(CameraPosition);
|
||||
|
||||
CGraphics::sMVPBlock.ModelMatrix = ModelMtx.ToMatrix4f();
|
||||
CGraphics::sVertexBlock.COLOR0_Amb = CVector4f(1.f, 1.f, 1.f, 1.f);
|
||||
CGraphics::sPixelBlock.TevColor = CVector4f(1.f, 1.f, 1.f, 1.f);
|
||||
CGraphics::sNumLights = 0;
|
||||
CGraphics::UpdateMVPBlock();
|
||||
CGraphics::UpdateVertexBlock();
|
||||
CGraphics::UpdatePixelBlock();
|
||||
CGraphics::UpdateLightBlock();
|
||||
|
||||
glDepthRange(1.f, 1.f);
|
||||
pSkyboxModel->Draw(mOptions, 0);
|
||||
}
|
||||
|
||||
void CRenderer::AddOpaqueMesh(CSceneNode *pNode, u32 AssetID, CAABox& AABox, ERenderCommand Command)
|
||||
{
|
||||
SMeshPointer mesh;
|
||||
mesh.pNode = pNode;
|
||||
mesh.Asset = AssetID;
|
||||
mesh.AABox = AABox;
|
||||
mesh.Command = Command;
|
||||
mOpaqueBucket.Add(mesh);
|
||||
}
|
||||
|
||||
void CRenderer::AddTransparentMesh(CSceneNode *pNode, u32 AssetID, CAABox& AABox, ERenderCommand Command)
|
||||
{
|
||||
SMeshPointer mesh;
|
||||
mesh.pNode = pNode;
|
||||
mesh.Asset = AssetID;
|
||||
mesh.AABox = AABox;
|
||||
mesh.Command = Command;
|
||||
mTransparentBucket.Add(mesh);
|
||||
}
|
||||
|
||||
void CRenderer::BeginFrame()
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
|
||||
CGraphics::SetActiveContext(mContextIndex);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mDefaultFramebuffer);
|
||||
|
||||
mSceneFramebuffer.Resize(mViewportWidth, mViewportHeight);
|
||||
mSceneFramebuffer.Bind();
|
||||
|
||||
glViewport(0, 0, mViewportWidth, mViewportHeight);
|
||||
|
||||
InitFramebuffer();
|
||||
|
||||
if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE);
|
||||
else glDisable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
void CRenderer::EndFrame()
|
||||
{
|
||||
// Post-processing
|
||||
if (mBloomMode == eBloom)
|
||||
RenderBloom();
|
||||
|
||||
// Render result to screen
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mDefaultFramebuffer);
|
||||
InitFramebuffer();
|
||||
glViewport(0, 0, mViewportWidth, mViewportHeight);
|
||||
|
||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
CDrawUtil::UseTextureShader();
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
mSceneFramebuffer.Texture()->Bind(0);
|
||||
CDrawUtil::DrawSquare();
|
||||
|
||||
if (mBloomMode == eBloom)
|
||||
{
|
||||
CDrawUtil::UseTextureShader();
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
mBloomFramebuffers[2].Texture()->Bind(0);
|
||||
CDrawUtil::DrawSquare();
|
||||
}
|
||||
|
||||
else if (mBloomMode == eBloomMaps)
|
||||
{
|
||||
// Bloom maps are in the framebuffer alpha channel.
|
||||
// White * dst alpha = bloom map colors
|
||||
CDrawUtil::UseColorShader(CColor::skWhite);
|
||||
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
|
||||
CDrawUtil::DrawSquare();
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
gDrawCount = 0;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CRenderer::InitFramebuffer()
|
||||
{
|
||||
CVector4f Clear = mClearColor.ToVector4f();
|
||||
Clear.w = 0.f;
|
||||
glClearColor(Clear.x, Clear.y, Clear.z, Clear.w);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
u32 gDrawCount;
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef CRENDERER_H
|
||||
#define CRENDERER_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
|
||||
#include "CCamera.h"
|
||||
#include "CGraphics.h"
|
||||
#include "CRenderBucket.h"
|
||||
#include "ERenderOptions.h"
|
||||
#include "ERenderCommand.h"
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/CColor.h>
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <Common/types.h>
|
||||
#include <OpenGL/CFramebuffer.h>
|
||||
#include <OpenGL/SMeshPointer.h>
|
||||
#include <Resource/CFont.h>
|
||||
#include <Resource/CLight.h>
|
||||
#include <Resource/CTexture.h>
|
||||
#include <Scene/CSceneNode.h>
|
||||
|
||||
class CRenderer
|
||||
{
|
||||
public:
|
||||
enum EBloomMode {
|
||||
eNoBloom, eBloom, eBloomMaps
|
||||
};
|
||||
|
||||
private:
|
||||
ERenderOptions mOptions;
|
||||
EBloomMode mBloomMode;
|
||||
bool mDrawGrid;
|
||||
CColor mClearColor;
|
||||
u32 mContextIndex;
|
||||
CRenderBucket mOpaqueBucket;
|
||||
CRenderBucket mTransparentBucket;
|
||||
bool mInitialized;
|
||||
u32 mViewportWidth, mViewportHeight;
|
||||
u32 mBloomWidth, mBloomHeight;
|
||||
float mBloomHScale, mBloomVScale;
|
||||
|
||||
CFramebuffer mSceneFramebuffer;
|
||||
CFramebuffer mBloomFramebuffers[3];
|
||||
GLint mDefaultFramebuffer;
|
||||
|
||||
// Static Members
|
||||
static u32 sNumRenderers;
|
||||
|
||||
public:
|
||||
// Initialization
|
||||
CRenderer();
|
||||
~CRenderer();
|
||||
void Init();
|
||||
|
||||
// Getters/Setters
|
||||
bool IsUVAnimationOn();
|
||||
void ToggleBackfaceCull(bool b);
|
||||
void ToggleUVAnimation(bool b);
|
||||
void ToggleGrid(bool b);
|
||||
void ToggleOccluders(bool b);
|
||||
void ToggleAlphaDisabled(bool b);
|
||||
void SetBloom(EBloomMode BloomMode);
|
||||
void SetFont(CFont *pFont);
|
||||
void SetClearColor(CColor Clear);
|
||||
void SetViewportSize(u32 Width, u32 Height);
|
||||
|
||||
// Render
|
||||
void RenderScene(CCamera& Camera);
|
||||
void RenderBloom();
|
||||
void RenderSky(CModel *pSkyboxModel, CVector3f CameraPosition);
|
||||
void AddOpaqueMesh(CSceneNode *pNode, u32 AssetID, CAABox& AABox, ERenderCommand Command);
|
||||
void AddTransparentMesh(CSceneNode *pNode, u32 AssetID, CAABox& AABox, ERenderCommand Command);
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
|
||||
// Private
|
||||
private:
|
||||
void InitFramebuffer();
|
||||
};
|
||||
|
||||
extern u32 gDrawCount;
|
||||
|
||||
#endif // RENDERMANAGER_H
|
|
@ -0,0 +1,236 @@
|
|||
#include "CResCache.h"
|
||||
#include "Log.h"
|
||||
#include <Common/StringUtil.h>
|
||||
#include <FileIO/FileIO.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
// Loaders
|
||||
#include <Resource/factory/CAreaLoader.h>
|
||||
#include <Resource/factory/CAnimSetLoader.h>
|
||||
#include <Resource/factory/CCollisionLoader.h>
|
||||
#include <Resource/factory/CFontLoader.h>
|
||||
#include <Resource/factory/CModelLoader.h>
|
||||
#include <Resource/factory/CScanLoader.h>
|
||||
#include <Resource/factory/CStringLoader.h>
|
||||
#include <Resource/factory/CTextureDecoder.h>
|
||||
#include <Resource/factory/CWorldLoader.h>
|
||||
|
||||
CResCache::CResCache()
|
||||
{
|
||||
mpPak = nullptr;
|
||||
}
|
||||
|
||||
CResCache::~CResCache()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
void CResCache::Clean()
|
||||
{
|
||||
if (mResourceCache.empty()) return;
|
||||
Log::Write("Cleaning unused resources");
|
||||
|
||||
// I couldn't get this to work properly using reverse iterators, lol.
|
||||
// Resources get cached after their dependencies, which is why I go backwards
|
||||
// while loop is to ensure -all- unused resources are cleaned. Not sure of a better way to do it.
|
||||
int numResourcesCleaned = 1;
|
||||
|
||||
while (numResourcesCleaned)
|
||||
{
|
||||
numResourcesCleaned = 0;
|
||||
|
||||
for (auto it = mResourceCache.end(); it != mResourceCache.begin();)
|
||||
{
|
||||
it--;
|
||||
if (it->second->mRefCount <= 0)
|
||||
{
|
||||
delete it->second;
|
||||
it = mResourceCache.erase(it);
|
||||
numResourcesCleaned++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log::Write(std::to_string(mResourceCache.size()) + " resources loaded");
|
||||
}
|
||||
|
||||
void CResCache::SetFolder(std::string path)
|
||||
{
|
||||
StringUtil::AppendSlash(path);
|
||||
mResSource.Path = path;
|
||||
mResSource.Source = SResSource::Folder;
|
||||
Log::Write("Set resource folder: " + path);
|
||||
}
|
||||
|
||||
void CResCache::SetPak(std::string path)
|
||||
{
|
||||
CFileInStream *pakfile = new CFileInStream(path, IOUtil::BigEndian);
|
||||
if (!pakfile->IsValid())
|
||||
{
|
||||
Log::Error("Couldn't load pak file: " + path);
|
||||
delete pakfile;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mpPak) delete mpPak;
|
||||
mpPak = new CPakFile(pakfile);
|
||||
mResSource.Path = path;
|
||||
mResSource.Source = SResSource::PakFile;
|
||||
Log::Write("Loaded pak file: " + path);
|
||||
}
|
||||
|
||||
void CResCache::SetResSource(SResSource& ResSource)
|
||||
{
|
||||
mResSource = ResSource;
|
||||
}
|
||||
|
||||
SResSource CResCache::GetResSource()
|
||||
{
|
||||
return mResSource;
|
||||
}
|
||||
|
||||
std::string CResCache::GetSourcePath()
|
||||
{
|
||||
return mResSource.Path;
|
||||
}
|
||||
|
||||
CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
|
||||
{
|
||||
if (!ResID.IsValid()) return nullptr;
|
||||
|
||||
auto got = mResourceCache.find(ResID.ToLongLong());
|
||||
|
||||
if (got != mResourceCache.end())
|
||||
return got->second;
|
||||
|
||||
std::vector<u8> *pBuffer = nullptr;
|
||||
std::string Source;
|
||||
|
||||
// Load from pak
|
||||
if (mResSource.Source == SResSource::PakFile)
|
||||
{
|
||||
pBuffer = mpPak->getResource(ResID.ToLongLong(), type);
|
||||
Source = ResID.ToString() + "." + type.ToString();
|
||||
}
|
||||
|
||||
// Load from folder
|
||||
else
|
||||
{
|
||||
Source = mResSource.Path + StringUtil::ResToStr(ResID.ToLong()) + "." + type.ToString();
|
||||
CFileInStream file(Source, IOUtil::BigEndian);
|
||||
if (!file.IsValid())
|
||||
{
|
||||
Source = mResSource.Path + StringUtil::ResToStr(ResID.ToLongLong()) + "." + type.ToString();
|
||||
file.Open(Source, IOUtil::BigEndian);
|
||||
if (!file.IsValid())
|
||||
{
|
||||
Log::Error("Couldn't open resource: " + ResID.ToString() + "." + type.ToString());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
pBuffer = new std::vector<u8>;
|
||||
pBuffer->resize(file.Size());
|
||||
file.ReadBytes(pBuffer->data(), pBuffer->size());
|
||||
}
|
||||
if (!pBuffer) return nullptr;
|
||||
|
||||
// Load resource
|
||||
CMemoryInStream mem(pBuffer->data(), pBuffer->size(), IOUtil::BigEndian);
|
||||
mem.SetSourceString(StringUtil::GetFileNameWithExtension(Source));
|
||||
CResource *Res = nullptr;
|
||||
bool SupportedFormat = true;
|
||||
|
||||
if (type == "CMDL") Res = CModelLoader::LoadCMDL(mem);
|
||||
else if (type == "TXTR") Res = CTextureDecoder::LoadTXTR(mem);
|
||||
else if (type == "ANCS") Res = CAnimSetLoader::LoadANCS(mem);
|
||||
else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(mem);
|
||||
else if (type == "MREA") Res = CAreaLoader::LoadMREA(mem);
|
||||
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(mem);
|
||||
else if (type == "STRG") Res = CStringLoader::LoadSTRG(mem);
|
||||
else if (type == "FONT") Res = CFontLoader::LoadFONT(mem);
|
||||
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem);
|
||||
else SupportedFormat = false;
|
||||
|
||||
// Log errors
|
||||
if (!SupportedFormat)
|
||||
Log::Write("Unsupported format; unable to load " + type.ToString() + " " + ResID.ToString());
|
||||
|
||||
if (!Res) Res = new CResource(); // Default for invalid resource or unsupported format
|
||||
|
||||
// Add to cache and cleanup
|
||||
Res->mID = ResID;
|
||||
Res->mResSource = Source;
|
||||
mResourceCache[ResID.ToLongLong()] = Res;
|
||||
delete pBuffer;
|
||||
return Res;
|
||||
}
|
||||
|
||||
CResource* CResCache::GetResource(std::string ResPath)
|
||||
{
|
||||
// Since this function takes a string argument it always loads directly from a file - no pak
|
||||
CUniqueID ResID = StringUtil::Hash64(ResPath);
|
||||
|
||||
auto got = mResourceCache.find(ResID.ToLongLong());
|
||||
|
||||
if (got != mResourceCache.end())
|
||||
return got->second;
|
||||
|
||||
CFileInStream file(ResPath, IOUtil::BigEndian);
|
||||
if (!file.IsValid())
|
||||
{
|
||||
Log::Error("Couldn't open resource: " + ResPath);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Save old ResSource to restore later
|
||||
const SResSource OldSource = mResSource;
|
||||
mResSource.Source = SResSource::Folder;
|
||||
mResSource.Path = StringUtil::GetFileDirectory(ResPath);
|
||||
|
||||
// Load resource
|
||||
CResource *Res = nullptr;
|
||||
CFourCC type = StringUtil::ToUpper( StringUtil::GetExtension(ResPath) ).c_str();
|
||||
bool SupportedFormat = true;
|
||||
|
||||
if (type == "CMDL") Res = CModelLoader::LoadCMDL(file);
|
||||
else if (type == "TXTR") Res = CTextureDecoder::LoadTXTR(file);
|
||||
else if (type == "ANCS") Res = CAnimSetLoader::LoadANCS(file);
|
||||
else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(file);
|
||||
else if (type == "MREA") Res = CAreaLoader::LoadMREA(file);
|
||||
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file);
|
||||
else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
|
||||
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
|
||||
else SupportedFormat = false;
|
||||
|
||||
if (!Res) Res = new CResource(); // Default for unsupported formats
|
||||
|
||||
// Add to cache and cleanup
|
||||
Res->mID = ResPath.c_str();
|
||||
Res->mResSource = ResPath;
|
||||
mResourceCache[ResID.ToLongLong()] = Res;
|
||||
mResSource = OldSource;
|
||||
return Res;
|
||||
}
|
||||
|
||||
void CResCache::CacheResource(CResource *pRes)
|
||||
{
|
||||
u64 ID = pRes->ResID().ToLongLong();
|
||||
auto got = mResourceCache.find(ID);
|
||||
|
||||
if (got != mResourceCache.end())
|
||||
mResourceCache[ID] = pRes;
|
||||
}
|
||||
|
||||
void CResCache::DeleteResource(CUniqueID ResID)
|
||||
{
|
||||
auto got = mResourceCache.find(ResID.ToLongLong());
|
||||
|
||||
if (got != mResourceCache.end())
|
||||
{
|
||||
delete got->second;
|
||||
mResourceCache.erase(got, got);
|
||||
}
|
||||
}
|
||||
|
||||
CResCache gResCache;
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef CRESCACHE_H
|
||||
#define CRESCACHE_H
|
||||
|
||||
#include <Common/types.h>
|
||||
#include <Resource/CPakFile.h>
|
||||
#include <Resource/CResource.h>
|
||||
#include <unordered_map>
|
||||
|
||||
struct SResSource
|
||||
{
|
||||
std::string Path;
|
||||
enum {
|
||||
Folder, PakFile
|
||||
} Source;
|
||||
};
|
||||
|
||||
class CResCache
|
||||
{
|
||||
std::unordered_map<u64, CResource*> mResourceCache;
|
||||
CPakFile *mpPak;
|
||||
SResSource mResSource;
|
||||
|
||||
public:
|
||||
CResCache();
|
||||
~CResCache();
|
||||
void Clean();
|
||||
void SetFolder(std::string path);
|
||||
void SetPak(std::string path);
|
||||
void SetResSource(SResSource& ResSource);
|
||||
SResSource GetResSource();
|
||||
std::string GetSourcePath();
|
||||
CResource* GetResource(CUniqueID ResID, CFourCC type);
|
||||
CResource* GetResource(std::string res);
|
||||
void CacheResource(CResource *pRes);
|
||||
void DeleteResource(CUniqueID ResID);
|
||||
};
|
||||
|
||||
extern CResCache gResCache;
|
||||
|
||||
#endif // CRESCACHE_H
|
|
@ -0,0 +1,380 @@
|
|||
#include "CSceneManager.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include <Common/CRay.h>
|
||||
#include <Common/CRayCollisionTester.h>
|
||||
#include <Common/StringUtil.h>
|
||||
#include <Core/CGraphics.h>
|
||||
#include <Core/CResCache.h>
|
||||
#include <FileIO/CFileInStream.h>
|
||||
|
||||
/**
|
||||
* This class direly needs a rewrite
|
||||
* Future plan is to integrate a "scene layer" system, where nodes are grouped into layers
|
||||
* We would have terrain layer, lights layer, collision layer, multiple script layers, etc
|
||||
* Advantage of this is that I don't need to write separate functions for every single node type
|
||||
* They can all be tracked together and the code could be streamlined a lot.
|
||||
*/
|
||||
CSceneManager::CSceneManager()
|
||||
{
|
||||
mShowTerrain = true;
|
||||
mShowCollision = false;
|
||||
mShowObjects = true;
|
||||
mShowLights = true;
|
||||
mSplitTerrain = true;
|
||||
mNodeCount = 0;
|
||||
mpSceneRootNode = new CRootNode(this, nullptr);
|
||||
mpArea = nullptr;
|
||||
mpWorld = nullptr;
|
||||
mpAreaRootNode = nullptr;
|
||||
}
|
||||
|
||||
CSceneManager::~CSceneManager()
|
||||
{
|
||||
ClearScene();
|
||||
}
|
||||
|
||||
CModelNode* CSceneManager::AddModel(CModel *m)
|
||||
{
|
||||
if (m == nullptr) return nullptr;
|
||||
|
||||
CModelNode *node = new CModelNode(this, mpSceneRootNode, m);
|
||||
mModelNodes.push_back(node);
|
||||
mNodeCount++;
|
||||
return node;
|
||||
}
|
||||
|
||||
CStaticNode* CSceneManager::AddStaticModel(CStaticModel *mdl)
|
||||
{
|
||||
if (mdl == nullptr) return nullptr;
|
||||
|
||||
CStaticNode *node = new CStaticNode(this, mpAreaRootNode, mdl);
|
||||
mStaticNodes.push_back(node);
|
||||
mNodeCount++;
|
||||
return node;
|
||||
}
|
||||
|
||||
CCollisionNode* CSceneManager::AddCollision(CCollisionMesh *mesh)
|
||||
{
|
||||
if (mesh == nullptr) return nullptr;
|
||||
|
||||
CCollisionNode *node = new CCollisionNode(this, mpAreaRootNode, mesh);
|
||||
mCollisionNodes.push_back(node);
|
||||
mNodeCount++;
|
||||
return node;
|
||||
}
|
||||
|
||||
CScriptNode* CSceneManager::AddScriptObject(CScriptObject *obj)
|
||||
{
|
||||
if (obj == nullptr) return nullptr;
|
||||
|
||||
CScriptNode *node = new CScriptNode(this, mpAreaRootNode, obj);
|
||||
mScriptNodes.push_back(node);
|
||||
mNodeCount++;
|
||||
return node;
|
||||
}
|
||||
|
||||
CLightNode* CSceneManager::AddLight(CLight *Light)
|
||||
{
|
||||
if (Light == nullptr) return nullptr;
|
||||
|
||||
CLightNode *node = new CLightNode(this, mpAreaRootNode, Light);
|
||||
mLightNodes.push_back(node);
|
||||
mNodeCount++;
|
||||
return node;
|
||||
}
|
||||
|
||||
void CSceneManager::SetActiveArea(CGameArea* _area)
|
||||
{
|
||||
// Clear existing area
|
||||
delete mpAreaRootNode;
|
||||
mModelNodes.clear();
|
||||
mStaticNodes.clear();
|
||||
mCollisionNodes.clear();
|
||||
mScriptNodes.clear();
|
||||
mLightNodes.clear();
|
||||
mAreaAttributesObjects.clear();
|
||||
mpActiveAreaAttributes = nullptr;
|
||||
mScriptNodeMap.clear();
|
||||
|
||||
// Create nodes for new area
|
||||
mpArea = _area;
|
||||
mAreaToken = CToken(mpArea);
|
||||
mpAreaRootNode = new CRootNode(this, mpSceneRootNode);
|
||||
|
||||
if (mSplitTerrain)
|
||||
{
|
||||
u32 count = mpArea->GetStaticModelCount();
|
||||
for (u32 m = 0; m < count; m++)
|
||||
AddStaticModel(mpArea->GetStaticModel(m));
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 count = mpArea->GetTerrainModelCount();
|
||||
for (u32 m = 0; m < count; m++)
|
||||
{
|
||||
CModel *mdl = mpArea->GetTerrainModel(m);
|
||||
CModelNode *node = AddModel(mdl);
|
||||
node->SetDynamicLighting(false);
|
||||
}
|
||||
}
|
||||
|
||||
AddCollision(mpArea->GetCollision());
|
||||
|
||||
u32 NumLayers = mpArea->GetScriptLayerCount();
|
||||
for (u32 l = 0; l < NumLayers; l++)
|
||||
{
|
||||
CScriptLayer *layer = mpArea->GetScriptLayer(l);
|
||||
u32 NumObjects = layer->GetNumObjects();
|
||||
mScriptNodes.reserve(mScriptNodes.size() + NumObjects);
|
||||
|
||||
for (u32 o = 0; o < NumObjects; o++)
|
||||
{
|
||||
CScriptObject *pObj = layer->ObjectByIndex(o);
|
||||
CScriptNode *Node = AddScriptObject( pObj );
|
||||
Node->BuildLightList(mpArea);
|
||||
|
||||
// Add to map
|
||||
mScriptNodeMap[pObj->InstanceID()] = Node;
|
||||
|
||||
// AreaAttributes check
|
||||
switch (pObj->ObjectTypeID())
|
||||
{
|
||||
case 0x4E: // MP1 AreaAttributes ID
|
||||
case 0x52454141: // MP2 AreaAttributes ID ("REAA")
|
||||
mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CScriptLayer *pGenLayer = mpArea->GetGeneratorLayer();
|
||||
if (pGenLayer)
|
||||
{
|
||||
for (u32 o = 0; o < pGenLayer->GetNumObjects(); o++)
|
||||
{
|
||||
CScriptObject *pObj = pGenLayer->ObjectByIndex(o);
|
||||
CScriptNode *Node = AddScriptObject(pObj);
|
||||
Node->BuildLightList(mpArea);
|
||||
|
||||
// Add to map
|
||||
mScriptNodeMap[pObj->InstanceID()] = Node;
|
||||
}
|
||||
}
|
||||
PickEnvironmentObjects();
|
||||
|
||||
// Ensure script nodes have valid positions
|
||||
for (auto it = mScriptNodeMap.begin(); it != mScriptNodeMap.end(); it++)
|
||||
it->second->GeneratePosition();
|
||||
|
||||
u32 NumLightLayers = mpArea->GetLightLayerCount();
|
||||
CGraphics::sAreaAmbientColor = CColor::skBlack;
|
||||
|
||||
for (u32 ly = 0; ly < NumLightLayers; ly++)
|
||||
{
|
||||
u32 NumLights = mpArea->GetLightCount(ly);
|
||||
|
||||
for (u32 l = 0; l < NumLights; l++)
|
||||
{
|
||||
CLight *Light = mpArea->GetLight(ly, l);
|
||||
|
||||
if (Light->GetType() == eLocalAmbient)
|
||||
CGraphics::sAreaAmbientColor += Light->GetColor();
|
||||
|
||||
AddLight(Light);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << CSceneNode::NumNodes() << " nodes\n";
|
||||
}
|
||||
|
||||
void CSceneManager::SetActiveWorld(CWorld* _world)
|
||||
{
|
||||
mpWorld = _world;
|
||||
mWorldToken = CToken(mpWorld);
|
||||
}
|
||||
|
||||
void CSceneManager::ClearScene()
|
||||
{
|
||||
mpAreaRootNode->Unparent();
|
||||
delete mpAreaRootNode;
|
||||
|
||||
mModelNodes.clear();
|
||||
mStaticNodes.clear();
|
||||
mCollisionNodes.clear();
|
||||
mScriptNodes.clear();
|
||||
mLightNodes.clear();
|
||||
|
||||
mpArea = nullptr;
|
||||
mAreaToken.Unlock();
|
||||
mpWorld = nullptr;
|
||||
mWorldToken.Unlock();
|
||||
mNodeCount = 0;
|
||||
}
|
||||
|
||||
void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
|
||||
{
|
||||
if (mShowTerrain)
|
||||
{
|
||||
for (u32 n = 0; n < mModelNodes.size(); n++)
|
||||
if (mModelNodes[n]->IsVisible())
|
||||
mModelNodes[n]->AddToRenderer(pRenderer);
|
||||
|
||||
for (u32 n = 0; n < mStaticNodes.size(); n++)
|
||||
if (mStaticNodes[n]->IsVisible())
|
||||
mStaticNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if (mShowCollision)
|
||||
{
|
||||
for (u32 n = 0; n < mCollisionNodes.size(); n++)
|
||||
if (mCollisionNodes[n]->IsVisible())
|
||||
mCollisionNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if (mShowObjects)
|
||||
{
|
||||
for (u32 n = 0; n < mScriptNodes.size(); n++)
|
||||
if (mScriptNodes[n]->IsVisible())
|
||||
mScriptNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if (mShowLights)
|
||||
{
|
||||
for (u32 n = 0; n < mLightNodes.size(); n++)
|
||||
if (mLightNodes[n]->IsVisible())
|
||||
mLightNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
|
||||
{
|
||||
// Terribly hacky stuff to avoid having tons of redundant code
|
||||
// because I'm too lazy to rewrite CSceneManager right now and fix it
|
||||
// (I'm probably going to do it soon...)
|
||||
std::vector<CSceneNode*> *pNodeVectors[5] = {
|
||||
reinterpret_cast<std::vector<CSceneNode*>*>(&mModelNodes),
|
||||
reinterpret_cast<std::vector<CSceneNode*>*>(&mStaticNodes),
|
||||
reinterpret_cast<std::vector<CSceneNode*>*>(&mCollisionNodes),
|
||||
reinterpret_cast<std::vector<CSceneNode*>*>(&mScriptNodes),
|
||||
reinterpret_cast<std::vector<CSceneNode*>*>(&mLightNodes),
|
||||
};
|
||||
bool NodesVisible[5] = {
|
||||
true, mShowTerrain, mShowCollision, mShowObjects, mShowLights
|
||||
};
|
||||
|
||||
// Less hacky stuff
|
||||
CRayCollisionTester Tester(Ray);
|
||||
|
||||
for (u32 iVec = 0; iVec < 5; iVec++)
|
||||
{
|
||||
if (!NodesVisible[iVec]) continue;
|
||||
|
||||
std::vector<CSceneNode*>& vec = *pNodeVectors[iVec];
|
||||
|
||||
for (u32 iNode = 0; iNode < vec.size(); iNode++)
|
||||
if (vec[iNode]->IsVisible())
|
||||
vec[iNode]->RayAABoxIntersectTest(Tester);
|
||||
}
|
||||
|
||||
return Tester.TestNodes();
|
||||
}
|
||||
|
||||
void CSceneManager::PickEnvironmentObjects()
|
||||
{
|
||||
// Pick AreaAttributes
|
||||
for (auto it = mAreaAttributesObjects.begin(); it != mAreaAttributesObjects.end(); it++)
|
||||
{
|
||||
if ((*it).IsLayerEnabled())
|
||||
{
|
||||
mpActiveAreaAttributes = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CScriptNode* CSceneManager::ScriptNodeByID(u32 InstanceID)
|
||||
{
|
||||
auto it = mScriptNodeMap.find(InstanceID);
|
||||
|
||||
if (it != mScriptNodeMap.end()) return it->second;
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
CScriptNode* CSceneManager::NodeForObject(CScriptObject *pObj)
|
||||
{
|
||||
return ScriptNodeByID(pObj->InstanceID());
|
||||
}
|
||||
|
||||
CLightNode* CSceneManager::NodeForLight(CLight *pLight)
|
||||
{
|
||||
// Slow. Is there a better way to do this?
|
||||
for (auto it = mLightNodes.begin(); it != mLightNodes.end(); it++)
|
||||
if ((*it)->Light() == pLight) return *it;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CModel* CSceneManager::GetActiveSkybox()
|
||||
{
|
||||
if (mpActiveAreaAttributes)
|
||||
{
|
||||
if (mpActiveAreaAttributes->IsSkyEnabled())
|
||||
{
|
||||
CModel *pSky = mpActiveAreaAttributes->SkyModel();
|
||||
if (pSky) return pSky;
|
||||
else return mpWorld->GetDefaultSkybox();
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
CGameArea* CSceneManager::GetActiveArea()
|
||||
{
|
||||
return mpArea;
|
||||
}
|
||||
|
||||
void CSceneManager::SetWorld(bool on)
|
||||
{
|
||||
mShowTerrain = on;
|
||||
}
|
||||
|
||||
void CSceneManager::SetCollision(bool on)
|
||||
{
|
||||
mShowCollision = on;
|
||||
}
|
||||
|
||||
void CSceneManager::SetLights(bool on)
|
||||
{
|
||||
mShowLights = on;
|
||||
}
|
||||
|
||||
void CSceneManager::SetObjects(bool on)
|
||||
{
|
||||
mShowObjects = on;
|
||||
}
|
||||
|
||||
bool CSceneManager::IsTerrainEnabled()
|
||||
{
|
||||
return mShowTerrain;
|
||||
}
|
||||
|
||||
bool CSceneManager::IsCollisionEnabled()
|
||||
{
|
||||
return mShowCollision;
|
||||
}
|
||||
|
||||
bool CSceneManager::AreLightsEnabled()
|
||||
{
|
||||
return mShowLights;
|
||||
}
|
||||
|
||||
bool CSceneManager::AreScriptObjectsEnabled()
|
||||
{
|
||||
return mShowObjects;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef CSCENEMANAGER_h
|
||||
#define CSCENEMANAGER_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "CAreaAttributes.h"
|
||||
#include "CRenderer.h"
|
||||
#include <Common/SRayIntersection.h>
|
||||
#include <Common/types.h>
|
||||
#include <Scene/CSceneNode.h>
|
||||
#include <Scene/CRootNode.h>
|
||||
#include <Scene/CLightNode.h>
|
||||
#include <Scene/CModelNode.h>
|
||||
#include <Scene/CScriptNode.h>
|
||||
#include <Scene/CStaticNode.h>
|
||||
#include <Scene/CCollisionNode.h>
|
||||
#include <Resource/CGameArea.h>
|
||||
#include <Resource/CWorld.h>
|
||||
|
||||
class CSceneManager
|
||||
{
|
||||
bool mShowTerrain;
|
||||
bool mShowCollision;
|
||||
bool mShowObjects;
|
||||
bool mShowLights;
|
||||
bool mSplitTerrain;
|
||||
|
||||
u32 mNodeCount;
|
||||
std::vector<CModelNode*> mModelNodes;
|
||||
std::vector<CStaticNode*> mStaticNodes;
|
||||
std::vector<CCollisionNode*> mCollisionNodes;
|
||||
std::vector<CScriptNode*> mScriptNodes;
|
||||
std::vector<CLightNode*> mLightNodes;
|
||||
CRootNode *mpSceneRootNode;
|
||||
|
||||
CGameArea *mpArea;
|
||||
CWorld *mpWorld;
|
||||
CToken mAreaToken;
|
||||
CToken mWorldToken;
|
||||
CRootNode *mpAreaRootNode;
|
||||
|
||||
// Environment
|
||||
std::vector<CAreaAttributes> mAreaAttributesObjects;
|
||||
CAreaAttributes *mpActiveAreaAttributes;
|
||||
|
||||
// Objects
|
||||
std::unordered_map<u32, CScriptNode*> mScriptNodeMap;
|
||||
|
||||
public:
|
||||
CSceneManager();
|
||||
~CSceneManager();
|
||||
|
||||
// Scene Management
|
||||
CModelNode* AddModel(CModel *mdl);
|
||||
CStaticNode* AddStaticModel(CStaticModel *mdl);
|
||||
CCollisionNode* AddCollision(CCollisionMesh *mesh);
|
||||
CScriptNode* AddScriptObject(CScriptObject *obj);
|
||||
CLightNode* AddLight(CLight *Light);
|
||||
void SetActiveArea(CGameArea *_area);
|
||||
void SetActiveWorld(CWorld *_world);
|
||||
void ClearScene();
|
||||
void AddSceneToRenderer(CRenderer *pRenderer);
|
||||
SRayIntersection SceneRayCast(const CRay& Ray);
|
||||
void PickEnvironmentObjects();
|
||||
CScriptNode* ScriptNodeByID(u32 InstanceID);
|
||||
CScriptNode* NodeForObject(CScriptObject *pObj);
|
||||
CLightNode* NodeForLight(CLight *pLight);
|
||||
|
||||
// Setters/Getters
|
||||
CModel* GetActiveSkybox();
|
||||
CGameArea* GetActiveArea();
|
||||
|
||||
void SetBackfaceCulling(bool on);
|
||||
void SetWorld(bool on);
|
||||
void SetCollision(bool on);
|
||||
void SetObjects(bool on);
|
||||
void SetLights(bool on);
|
||||
bool IsBackfaceCullEnabled();
|
||||
bool IsTerrainEnabled();
|
||||
bool IsCollisionEnabled();
|
||||
bool AreLightsEnabled();
|
||||
bool AreScriptObjectsEnabled();
|
||||
};
|
||||
|
||||
#endif // CSCENEMANAGER_H
|
|
@ -0,0 +1,55 @@
|
|||
#include "CToken.h"
|
||||
|
||||
CToken::CToken()
|
||||
{
|
||||
mpRes = nullptr;
|
||||
mLocked = false;
|
||||
}
|
||||
|
||||
CToken::CToken(CResource *pRes)
|
||||
{
|
||||
mpRes = pRes;
|
||||
mLocked = false;
|
||||
Lock();
|
||||
}
|
||||
|
||||
CToken::CToken(const CToken& Source)
|
||||
{
|
||||
mLocked = false;
|
||||
*this = Source;
|
||||
}
|
||||
|
||||
CToken::~CToken()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void CToken::Lock()
|
||||
{
|
||||
if (!mLocked)
|
||||
{
|
||||
if (mpRes)
|
||||
{
|
||||
mpRes->Lock();
|
||||
mLocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CToken::Unlock()
|
||||
{
|
||||
if (mLocked)
|
||||
{
|
||||
mpRes->Release();
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
CToken& CToken::operator=(const CToken& Source)
|
||||
{
|
||||
if (mLocked) Unlock();
|
||||
|
||||
mpRes = Source.mpRes;
|
||||
Lock();
|
||||
return *this;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef CTOKEN_H
|
||||
#define CTOKEN_H
|
||||
|
||||
#include <Resource/CResource.h>
|
||||
|
||||
class CToken
|
||||
{
|
||||
CResource *mpRes;
|
||||
bool mLocked;
|
||||
|
||||
public:
|
||||
CToken();
|
||||
CToken(CResource *pRes);
|
||||
CToken(const CToken& Source);
|
||||
~CToken();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
CToken& operator=(const CToken& Source);
|
||||
};
|
||||
|
||||
#endif // CTOKEN_H
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef ERENDERCOMMAND
|
||||
#define ERENDERCOMMAND
|
||||
|
||||
enum ERenderCommand
|
||||
{
|
||||
eDrawMesh,
|
||||
eDrawAsset,
|
||||
eDrawSelection,
|
||||
eDrawExtras
|
||||
};
|
||||
|
||||
#endif // ERENDERCOMMAND
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef ERENDEROPTIONS
|
||||
#define ERENDEROPTIONS
|
||||
|
||||
#include <Common/EnumUtil.h>
|
||||
|
||||
enum ERenderOptions
|
||||
{
|
||||
eEnableUVScroll = 0x1,
|
||||
eEnableBackfaceCull = 0x2,
|
||||
eEnableOccluders = 0x4,
|
||||
eNoMaterialSetup = 0x8,
|
||||
eEnableBloom = 0x10,
|
||||
eNoAlpha = 0x20
|
||||
};
|
||||
DEFINE_ENUM_FLAGS(ERenderOptions)
|
||||
|
||||
#endif // ERENDEROPTIONS
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <QMessageBox>
|
||||
#include <Common/StringUtil.h>
|
||||
|
||||
namespace Log
|
||||
{
|
||||
|
||||
static const std::string gskLogFilename = "primeworldeditor.log";
|
||||
FILE *gpLogFile = fopen(gskLogFilename.c_str(), "w");
|
||||
|
||||
void Write(const std::string& message)
|
||||
{
|
||||
|
||||
if (gpLogFile)
|
||||
{
|
||||
time_t RawTime;
|
||||
time(&RawTime);
|
||||
|
||||
tm *pTimeInfo = localtime(&RawTime);
|
||||
char Buffer[80];
|
||||
strftime(Buffer, 80, "[%H:%M:%S]", pTimeInfo);
|
||||
|
||||
fprintf(gpLogFile, "%s %s\n", Buffer, message.c_str());
|
||||
fflush(gpLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Error(const std::string& message)
|
||||
{
|
||||
Write("ERROR: " + message);
|
||||
|
||||
#ifdef _DEBUG
|
||||
std::cout << "ERROR: " << message << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
void Warning(const std::string& message)
|
||||
{
|
||||
Write("Warning: " + message);
|
||||
|
||||
#ifdef _DEBUG
|
||||
std::cout << "Warning: " << message << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileWrite(const std::string& filename, const std::string& message)
|
||||
{
|
||||
Write(filename + " : " + message);
|
||||
}
|
||||
|
||||
void FileWrite(const std::string& filename, unsigned long offset, const std::string& message)
|
||||
{
|
||||
Write(filename + " : " + StringUtil::ToHexString(offset) + " - " + message);
|
||||
}
|
||||
|
||||
void FileError(const std::string& filename, const std::string& message)
|
||||
{
|
||||
Error(filename + " : " + message);
|
||||
}
|
||||
|
||||
void FileError(const std::string &filename, unsigned long offset, const std::string &message)
|
||||
{
|
||||
Error(filename + " : " + StringUtil::ToHexString(offset) + " - " + message);
|
||||
}
|
||||
|
||||
void FileWarning(const std::string& filename, const std::string& message)
|
||||
{
|
||||
Warning(filename + " : " + message);
|
||||
}
|
||||
|
||||
void FileWarning(const std::string& filename, unsigned long offset, const std::string& message)
|
||||
{
|
||||
Warning(filename + " : " + StringUtil::ToHexString(offset) + " - " + message);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef INFO
|
||||
#define INFO
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Log
|
||||
{
|
||||
|
||||
void Write(const std::string& message);
|
||||
void Error(const std::string& message);
|
||||
void Warning(const std::string& message);
|
||||
void FileWrite(const std::string& filename, const std::string& message);
|
||||
void FileWrite(const std::string& filename, unsigned long offset, const std::string& message);
|
||||
void FileError(const std::string& filename, const std::string& message);
|
||||
void FileError(const std::string& filename, unsigned long offset, const std::string& message);
|
||||
void FileWarning(const std::string& filename, const std::string& message);
|
||||
void FileWarning(const std::string& filename, unsigned long offset, const std::string& message);
|
||||
|
||||
}
|
||||
|
||||
#endif // INFO
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include <QApplication>
|
||||
#include <UI/CStartWindow.h>
|
||||
#include <UI/CWorldEditorWindow.h>
|
||||
#include <UI/CModelEditorWindow.h>
|
||||
#include <UI/TestDialog.h>
|
||||
#include <Common/CTimer.h>
|
||||
#include <iostream>
|
||||
#include <QStyleFactory>
|
||||
#include <UI/CDarkStyle.h>
|
||||
#include <time.h>
|
||||
#include <Resource/factory/CTextureDecoder.h>
|
||||
#include <Resource/cooker/CTextureEncoder.h>
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <Resource/factory/CTemplateLoader.h>
|
||||
#include <Common/StringUtil.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
||||
QApplication app(argc, argv);
|
||||
CStartWindow w;
|
||||
w.show();
|
||||
|
||||
CTemplateLoader::LoadGameList();
|
||||
//CTexture *pTex = CTextureDecoder::LoadDDS(CFileInStream("E:/34f7c12211777ce8.dds", IOUtil::LittleEndian));
|
||||
//CTextureEncoder::EncodeTXTR(CFileOutStream("E:/Unpacked/Metroid Prime 3 Dolphin/Metroid4-pak/34f7c12211777ce8.TXTR", IOUtil::BigEndian), pTex);
|
||||
|
||||
app.setStyle(new CDarkStyle);
|
||||
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
QPalette darkPalette;
|
||||
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Base, QColor(25,25,25));
|
||||
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
|
||||
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Text, Qt::white);
|
||||
darkPalette.setColor(QPalette::Button, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
darkPalette.setColor(QPalette::BrightText, Qt::red);
|
||||
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
|
||||
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
|
||||
qApp->setPalette(darkPalette);
|
||||
|
||||
return app.exec();
|
||||
}
|
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,31 @@
|
|||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>EditorAssets/Down.png</file>
|
||||
<file>EditorAssets/Free Camera.png</file>
|
||||
<file>EditorAssets/Material Highlight.png</file>
|
||||
<file>EditorAssets/Minus v2.png</file>
|
||||
<file>EditorAssets/Minus.png</file>
|
||||
<file>EditorAssets/Orbit Camera v2.png</file>
|
||||
<file>EditorAssets/Orbit Camera.png</file>
|
||||
<file>EditorAssets/Plus.png</file>
|
||||
<file>EditorAssets/Rotate.png</file>
|
||||
<file>EditorAssets/Samus Silhouette Gradient.png</file>
|
||||
<file>EditorAssets/Scale.png</file>
|
||||
<file>EditorAssets/Sphere Preview.png</file>
|
||||
<file>EditorAssets/Square Preview.png</file>
|
||||
<file>EditorAssets/Translate.png</file>
|
||||
<file>EditorAssets/Up.png</file>
|
||||
<file>EditorAssets/Hide.png</file>
|
||||
<file>EditorAssets/Highlight.png</file>
|
||||
<file>EditorAssets/Model Preview.png</file>
|
||||
<file>EditorAssets/Show.png</file>
|
||||
<file>EditorAssets/GridLight.png</file>
|
||||
<file>EditorAssets/Create.png</file>
|
||||
<file>EditorAssets/Display.png</file>
|
||||
<file>EditorAssets/Instances.png</file>
|
||||
<file>EditorAssets/Link.png</file>
|
||||
<file>EditorAssets/Modify.png</file>
|
||||
<file>EditorAssets/Unlink.png</file>
|
||||
<file>EditorAssets/World.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,136 @@
|
|||
#include "CDynamicVertexBuffer.h"
|
||||
#include "CVertexArrayManager.h"
|
||||
|
||||
static const u32 gskAttribSize[] = {
|
||||
0xC, 0xC, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8
|
||||
};
|
||||
|
||||
CDynamicVertexBuffer::CDynamicVertexBuffer()
|
||||
{
|
||||
mAttribFlags = eNoAttributes;
|
||||
mBufferedFlags = eNoAttributes;
|
||||
mNumVertices = 0;
|
||||
}
|
||||
|
||||
CDynamicVertexBuffer::~CDynamicVertexBuffer()
|
||||
{
|
||||
CVertexArrayManager::DeleteAllArraysForVBO(this);
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::SetVertexCount(u32 NumVerts)
|
||||
{
|
||||
ClearBuffers();
|
||||
mNumVertices = NumVerts;
|
||||
InitBuffers();
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::Bind()
|
||||
{
|
||||
CVertexArrayManager::Current()->BindVAO(this);
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::Unbind()
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::SetActiveAttribs(u32 AttribFlags)
|
||||
{
|
||||
ClearBuffers();
|
||||
mAttribFlags = (EVertexDescription) AttribFlags;
|
||||
InitBuffers();
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::BufferAttrib(EVertexDescription Attrib, const void *pData)
|
||||
{
|
||||
u32 Index;
|
||||
|
||||
switch (Attrib)
|
||||
{
|
||||
case ePosition: Index = 0; break;
|
||||
case eNormal: Index = 1; break;
|
||||
case eColor0: Index = 2; break;
|
||||
case eColor1: Index = 3; break;
|
||||
case eTex0: Index = 4; break;
|
||||
case eTex1: Index = 5; break;
|
||||
case eTex2: Index = 6; break;
|
||||
case eTex3: Index = 7; break;
|
||||
case eTex4: Index = 8; break;
|
||||
case eTex5: Index = 9; break;
|
||||
case eTex6: Index = 10; break;
|
||||
case eTex7: Index = 11; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[Index]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, gskAttribSize[Index] * mNumVertices, pData);
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::ClearBuffers()
|
||||
{
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
u8 Bit = 1 << iAttrib;
|
||||
|
||||
if (mBufferedFlags & Bit)
|
||||
glDeleteBuffers(1, &mAttribBuffers[iAttrib]);
|
||||
}
|
||||
|
||||
mBufferedFlags = eNoAttributes;
|
||||
}
|
||||
|
||||
GLuint CDynamicVertexBuffer::CreateVAO()
|
||||
{
|
||||
GLuint VertexArray;
|
||||
glGenVertexArrays(1, &VertexArray);
|
||||
glBindVertexArray(VertexArray);
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
bool HasAttrib = ((3 << (iAttrib * 2)) != 0);
|
||||
|
||||
if (HasAttrib)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
GLuint NumComponents;
|
||||
GLenum DataType;
|
||||
|
||||
if ((iAttrib == 2) || (iAttrib == 3))
|
||||
{
|
||||
NumComponents = 4;
|
||||
DataType = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumComponents = gskAttribSize[iAttrib] / 4;
|
||||
DataType = GL_FLOAT;
|
||||
}
|
||||
|
||||
glVertexAttribPointer(iAttrib, NumComponents, DataType, GL_FALSE, 0, (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
return VertexArray;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CDynamicVertexBuffer::InitBuffers()
|
||||
{
|
||||
if (mBufferedFlags) ClearBuffers();
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
bool HasAttrib = ((3 << (iAttrib * 2)) != 0);
|
||||
|
||||
if (HasAttrib)
|
||||
{
|
||||
glGenBuffers(1, &mAttribBuffers[iAttrib]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, gskAttribSize[iAttrib] * mNumVertices, NULL, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
}
|
||||
mBufferedFlags = mAttribFlags;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef CDYNAMICVERTEXBUFFER_H
|
||||
#define CDYNAMICVERTEXBUFFER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Common/types.h>
|
||||
#include <Common/CVector2f.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Resource/model/EVertexDescription.h>
|
||||
#include <vector>
|
||||
|
||||
class CDynamicVertexBuffer
|
||||
{
|
||||
EVertexDescription mAttribFlags;
|
||||
EVertexDescription mBufferedFlags;
|
||||
u32 mNumVertices;
|
||||
GLuint mAttribBuffers[12];
|
||||
|
||||
public:
|
||||
CDynamicVertexBuffer();
|
||||
~CDynamicVertexBuffer();
|
||||
void SetVertexCount(u32 NumVerts);
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void SetActiveAttribs(u32 AttribFlags);
|
||||
void BufferAttrib(EVertexDescription Attrib, const void *pData);
|
||||
void ClearBuffers();
|
||||
GLuint CreateVAO();
|
||||
private:
|
||||
void InitBuffers();
|
||||
};
|
||||
|
||||
#endif // CDYNAMICVERTEXBUFFER_H
|
|
@ -0,0 +1,111 @@
|
|||
#include "CFramebuffer.h"
|
||||
#include <iostream>
|
||||
|
||||
CFramebuffer::CFramebuffer()
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mpRenderbuffer = nullptr;
|
||||
mpTexture = nullptr;
|
||||
}
|
||||
|
||||
CFramebuffer::CFramebuffer(u32 Width, u32 Height)
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mpRenderbuffer = nullptr;
|
||||
mpTexture = nullptr;
|
||||
Resize(Width, Height);
|
||||
}
|
||||
|
||||
CFramebuffer::~CFramebuffer()
|
||||
{
|
||||
if (mInitialized)
|
||||
{
|
||||
glDeleteFramebuffers(1, &mFramebuffer);
|
||||
delete mpRenderbuffer;
|
||||
delete mpTexture;
|
||||
}
|
||||
}
|
||||
|
||||
void CFramebuffer::Init()
|
||||
{
|
||||
if (!smStaticsInitialized)
|
||||
{
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &smDefaultFramebuffer);
|
||||
smStaticsInitialized = true;
|
||||
}
|
||||
|
||||
if (!mInitialized)
|
||||
{
|
||||
glGenFramebuffers(1, &mFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
|
||||
mpRenderbuffer = new CRenderbuffer(mWidth, mHeight);
|
||||
mpRenderbuffer->Bind();
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID()
|
||||
);
|
||||
|
||||
mpTexture = new CTexture(mWidth, mHeight);
|
||||
mpTexture->Bind(0);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->TextureID(), 0
|
||||
);
|
||||
|
||||
mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
if (mStatus != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cout << "\rError: Framebuffer not complete\n";
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CFramebuffer::Bind()
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
}
|
||||
|
||||
void CFramebuffer::Resize(u32 Width, u32 Height)
|
||||
{
|
||||
if ((mWidth != Width) || (mHeight != Height))
|
||||
{
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
|
||||
if (mInitialized)
|
||||
{
|
||||
mpRenderbuffer->Resize(Width, Height);
|
||||
mpTexture->Resize(Width, Height);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
mpRenderbuffer->Bind();
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID()
|
||||
);
|
||||
|
||||
mpTexture->Bind(0);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->TextureID(), 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTexture* CFramebuffer::Texture()
|
||||
{
|
||||
return mpTexture;
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
void CFramebuffer::BindDefaultFramebuffer()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, smDefaultFramebuffer);
|
||||
}
|
||||
|
||||
GLint CFramebuffer::smDefaultFramebuffer;
|
||||
bool CFramebuffer::smStaticsInitialized;
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef CFRAMEBUFFER_H
|
||||
#define CFRAMEBUFFER_H
|
||||
|
||||
#include "CRenderbuffer.h"
|
||||
#include <Resource/CTexture.h>
|
||||
#include <gl/glew.h>
|
||||
|
||||
class CFramebuffer
|
||||
{
|
||||
GLuint mFramebuffer;
|
||||
CRenderbuffer *mpRenderbuffer;
|
||||
CTexture *mpTexture;
|
||||
u32 mWidth, mHeight;
|
||||
bool mInitialized;
|
||||
GLenum mStatus;
|
||||
|
||||
static GLint smDefaultFramebuffer;
|
||||
static bool smStaticsInitialized;
|
||||
|
||||
public:
|
||||
CFramebuffer();
|
||||
CFramebuffer(u32 Width, u32 Height);
|
||||
~CFramebuffer();
|
||||
void Init();
|
||||
void Bind();
|
||||
void Resize(u32 Width, u32 Height);
|
||||
CTexture* Texture();
|
||||
static void BindDefaultFramebuffer();
|
||||
|
||||
};
|
||||
|
||||
#endif // CFRAMEBUFFER_H
|
|
@ -0,0 +1,41 @@
|
|||
#include "CGL.h"
|
||||
|
||||
// ************ PUBLIC ************
|
||||
void CGL::SetBlendMode(EBlendFactor Source, EBlendFactor Dest)
|
||||
{
|
||||
glBlendFuncSeparate(Source, Dest, eBlendZero, eBlendZero);
|
||||
mBlendSrcFac = Source;
|
||||
mBlendDstFac = Dest;
|
||||
}
|
||||
|
||||
void CGL::SetOpaqueBlend()
|
||||
{
|
||||
SetBlendMode(eBlendOne, eBlendZero);
|
||||
}
|
||||
|
||||
void CGL::SetAlphaBlend()
|
||||
{
|
||||
SetBlendMode(eBlendSrcAlpha, eBlendInvSrcAlpha);
|
||||
}
|
||||
|
||||
void CGL::SetAdditiveBlend()
|
||||
{
|
||||
SetBlendMode(eBlendOne, eBlendOne);
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CGL::Init()
|
||||
{
|
||||
if (!mInitialized)
|
||||
{
|
||||
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
mBlendSrcFac = eBlendOne;
|
||||
mBlendDstFac = eBlendZero;
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
bool CGL::mInitialized;
|
||||
EBlendFactor CGL::mBlendSrcFac;
|
||||
EBlendFactor CGL::mBlendDstFac;
|