Initial commit of current work on Prime World Editor

This commit is contained in:
parax0 2015-07-26 17:39:49 -04:00
commit 66e8c2ebcb
305 changed files with 33469 additions and 0 deletions

34
.gitignore vendored Normal file
View File

@ -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.*

10
Common/AnimUtil.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "CTimer.h"
#include <cmath>
namespace AnimUtil
{
float SecondsMod900()
{
return fmod((float) CTimer::GlobalTime(), 900.f);
}
}

9
Common/AnimUtil.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef ANIMUTIL_H
#define ANIMUTIL_H
namespace AnimUtil
{
float SecondsMod900();
}
#endif // ANIMUTIL_H

158
Common/CAABox.cpp Normal file
View File

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

51
Common/CAABox.h Normal file
View File

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

183
Common/CColor.cpp Normal file
View File

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

60
Common/CColor.h Normal file
View File

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

111
Common/CFourCC.cpp Normal file
View File

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

34
Common/CFourCC.h Normal file
View File

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

72
Common/CHashFNV1A.cpp Normal file
View File

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

36
Common/CHashFNV1A.h Normal file
View File

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

241
Common/CMatrix4f.cpp Normal file
View File

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

50
Common/CMatrix4f.h Normal file
View File

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

86
Common/CQuaternion.cpp Normal file
View File

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

25
Common/CQuaternion.h Normal file
View File

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

43
Common/CRay.cpp Normal file
View File

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

35
Common/CRay.h Normal file
View File

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

View File

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

View File

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

89
Common/CTimer.cpp Normal file
View File

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

28
Common/CTimer.h Normal file
View File

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

309
Common/CTransform4f.cpp Normal file
View File

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

70
Common/CTransform4f.h Normal file
View File

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

299
Common/CUniqueID.cpp Normal file
View File

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

56
Common/CUniqueID.h Normal file
View File

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

156
Common/CVector2f.cpp Normal file
View File

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

46
Common/CVector2f.h Normal file
View File

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

139
Common/CVector2i.cpp Normal file
View File

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

39
Common/CVector2i.h Normal file
View File

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

300
Common/CVector3f.cpp Normal file
View File

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

83
Common/CVector3f.h Normal file
View File

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

273
Common/CVector4f.cpp Normal file
View File

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

68
Common/CVector4f.h Normal file
View File

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

View File

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

11
Common/CompressionUtil.h Normal file
View File

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

21
Common/EKeyInputs.h Normal file
View File

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

15
Common/EMouseInputs.h Normal file
View File

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

19
Common/EnumUtil.h Normal file
View File

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

244
Common/Math.cpp Normal file
View File

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

25
Common/Math.h Normal file
View File

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

20
Common/SRayIntersection.h Normal file
View File

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

321
Common/StringUtil.cpp Normal file
View File

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

35
Common/StringUtil.h Normal file
View File

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

15
Common/types.h Normal file
View File

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

55
Core/CAreaAttributes.cpp Normal file
View File

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

20
Core/CAreaAttributes.h Normal file
View File

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

286
Core/CCamera.cpp Normal file
View File

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

76
Core/CCamera.h Normal file
View File

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

436
Core/CDrawUtil.cpp Normal file
View File

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

91
Core/CDrawUtil.h Normal file
View File

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

159
Core/CGraphics.cpp Normal file
View File

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

97
Core/CGraphics.h Normal file
View File

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

89
Core/CRenderBucket.cpp Normal file
View File

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

33
Core/CRenderBucket.h Normal file
View File

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

328
Core/CRenderer.cpp Normal file
View File

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

83
Core/CRenderer.h Normal file
View File

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

236
Core/CResCache.cpp Normal file
View File

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

40
Core/CResCache.h Normal file
View File

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

380
Core/CSceneManager.cpp Normal file
View File

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

87
Core/CSceneManager.h Normal file
View File

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

55
Core/CToken.cpp Normal file
View File

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

21
Core/CToken.h Normal file
View File

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

13
Core/ERenderCommand.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef ERENDERCOMMAND
#define ERENDERCOMMAND
enum ERenderCommand
{
eDrawMesh,
eDrawAsset,
eDrawSelection,
eDrawExtras
};
#endif // ERENDERCOMMAND

18
Core/ERenderOptions.h Normal file
View File

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

78
Core/Log.cpp Normal file
View File

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

22
Core/Log.h Normal file
View File

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

52
Core/main.cpp Normal file
View File

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

BIN
EditorAssets/Create.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
EditorAssets/Display.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
EditorAssets/Down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
EditorAssets/GridLight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
EditorAssets/Hide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
EditorAssets/Highlight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
EditorAssets/Instances.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
EditorAssets/Link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
EditorAssets/Minus v2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
EditorAssets/Minus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
EditorAssets/Modify.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
EditorAssets/Plus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
EditorAssets/Rotate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
EditorAssets/Scale.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
EditorAssets/Show.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
EditorAssets/Translate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
EditorAssets/Unlink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
EditorAssets/Up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
EditorAssets/World.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

31
Icons.qrc Normal file
View File

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

View File

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

View File

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

111
OpenGL/CFramebuffer.cpp Normal file
View File

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

32
OpenGL/CFramebuffer.h Normal file
View File

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

41
OpenGL/CGL.cpp Normal file
View File

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

Some files were not shown because too many files have changed in this diff Show More