mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-17 17:05:37 +00:00
Mass refactoring part 1/2: establishing multiple subprojects, moving source files to their new location, adding resources/templates to version control
This commit is contained in:
10
src/Common/AnimUtil.cpp
Normal file
10
src/Common/AnimUtil.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "CTimer.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace AnimUtil
|
||||
{
|
||||
float SecondsMod900()
|
||||
{
|
||||
return fmod((float) CTimer::GlobalTime(), 900.f);
|
||||
}
|
||||
}
|
||||
9
src/Common/AnimUtil.h
Normal file
9
src/Common/AnimUtil.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef ANIMUTIL_H
|
||||
#define ANIMUTIL_H
|
||||
|
||||
namespace AnimUtil
|
||||
{
|
||||
float SecondsMod900();
|
||||
}
|
||||
|
||||
#endif // ANIMUTIL_H
|
||||
211
src/Common/CColor.cpp
Normal file
211
src/Common/CColor.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
#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
|
||||
{
|
||||
CVector4f A = ToVector4f();
|
||||
CVector4f B = other.ToVector4f();
|
||||
|
||||
float NewR = A.x * B.x;
|
||||
float NewG = A.y * B.y;
|
||||
float NewB = A.z * B.z;
|
||||
float NewA = A.w * B.w;
|
||||
|
||||
return CColor(NewR, NewG, NewB, NewA);
|
||||
}
|
||||
|
||||
void CColor::operator*=(const CColor& other)
|
||||
{
|
||||
*this = (*this * other);
|
||||
}
|
||||
|
||||
CColor CColor::operator*(const float other) const
|
||||
{
|
||||
CVector4f Vec4f = ToVector4f() * other;
|
||||
return CColor(Vec4f.x, Vec4f.y, Vec4f.z, Vec4f.w);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CColor CColor::RandomColor(bool transparent)
|
||||
{
|
||||
CColor out;
|
||||
out.r = rand() % 255;
|
||||
out.g = rand() % 255;
|
||||
out.b = rand() % 255;
|
||||
out.a = (transparent ? rand() % 255 : 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
CColor CColor::RandomLightColor(bool transparent)
|
||||
{
|
||||
CColor out;
|
||||
out.r = 127 + (rand() % 128);
|
||||
out.g = 127 + (rand() % 128);
|
||||
out.b = 127 + (rand() % 128);
|
||||
out.a = (transparent ? 127 + (rand() % 128) : 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
CColor CColor::RandomDarkColor(bool transparent)
|
||||
{
|
||||
CColor out;
|
||||
out.r = rand() % 128;
|
||||
out.g = rand() % 128;
|
||||
out.b = rand() % 128;
|
||||
out.a = (transparent ? rand() % 128 : 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
// 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));
|
||||
65
src/Common/CColor.h
Normal file
65
src/Common/CColor.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#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);
|
||||
|
||||
// Static
|
||||
static CColor RandomColor(bool transparent);
|
||||
static CColor RandomLightColor(bool transparent);
|
||||
static CColor RandomDarkColor(bool transparent);
|
||||
|
||||
// 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
|
||||
120
src/Common/CFourCC.cpp
Normal file
120
src/Common/CFourCC.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "CFourCC.h"
|
||||
|
||||
// ************ CONSTRUCTORS ************
|
||||
CFourCC::CFourCC()
|
||||
{
|
||||
memset(mFourCC, 0, 4);
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(const char *src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(const TString& src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(u32 src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
CFourCC::CFourCC(CInputStream& src)
|
||||
{
|
||||
src.ReadBytes(&mFourCC[0], 4);
|
||||
}
|
||||
|
||||
// ************ FUNCTIONALITY ************
|
||||
void CFourCC::Write(COutputStream &Output)
|
||||
{
|
||||
Output.WriteBytes(mFourCC, 4);
|
||||
}
|
||||
|
||||
u32 CFourCC::ToLong() const
|
||||
{
|
||||
return mFourCC[0] << 24 | mFourCC[1] << 16 | mFourCC[2] << 8 | mFourCC[3];
|
||||
}
|
||||
|
||||
TString CFourCC::ToString() const
|
||||
{
|
||||
return TString(mFourCC, 4);
|
||||
}
|
||||
|
||||
CFourCC CFourCC::ToUpper() const
|
||||
{
|
||||
CFourCC Out;
|
||||
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
if ((mFourCC[c] >= 0x61) && (mFourCC[c] <= 0x7A))
|
||||
Out.mFourCC[c] = mFourCC[c] - 0x20;
|
||||
else
|
||||
Out.mFourCC[c] = mFourCC[c];
|
||||
}
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
CFourCC& CFourCC::operator=(const char *src)
|
||||
{
|
||||
memcpy(&mFourCC[0], src, 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFourCC& CFourCC::operator=(const TString& src)
|
||||
{
|
||||
memcpy(&mFourCC[0], src.CString(), 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFourCC& CFourCC::operator=(u32 src)
|
||||
{
|
||||
mFourCC[0] = (src >> 24) & 0xFF;
|
||||
mFourCC[1] = (src >> 16) & 0xFF;
|
||||
mFourCC[2] = (src >> 8) & 0xFF;
|
||||
mFourCC[3] = (src >> 0) & 0xFF;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CFourCC::operator==(const CFourCC& other) const
|
||||
{
|
||||
return ((mFourCC[0] == other.mFourCC[0]) && (mFourCC[1] == other.mFourCC[1]) && (mFourCC[2] == other.mFourCC[2]) && (mFourCC[3] == other.mFourCC[3]));
|
||||
}
|
||||
|
||||
bool CFourCC::operator!=(const CFourCC& other) const
|
||||
{
|
||||
return (!(*this == other));
|
||||
}
|
||||
|
||||
bool CFourCC::operator>(const CFourCC& other) const
|
||||
{
|
||||
return (ToLong() > other.ToLong());
|
||||
}
|
||||
|
||||
bool CFourCC::operator>=(const CFourCC& other) const
|
||||
{
|
||||
return (ToLong() >= other.ToLong());
|
||||
}
|
||||
|
||||
bool CFourCC::operator<(const CFourCC& other) const
|
||||
{
|
||||
return (ToLong() < other.ToLong());
|
||||
}
|
||||
|
||||
bool CFourCC::operator<=(const CFourCC& other) const
|
||||
{
|
||||
return (ToLong() <= other.ToLong());
|
||||
}
|
||||
|
||||
char CFourCC::operator[](int index)
|
||||
{
|
||||
return mFourCC[index];
|
||||
}
|
||||
|
||||
const char CFourCC::operator[](int index) const
|
||||
{
|
||||
return mFourCC[index];
|
||||
}
|
||||
40
src/Common/CFourCC.h
Normal file
40
src/Common/CFourCC.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef CFOURCC_H
|
||||
#define CFOURCC_H
|
||||
|
||||
#include "types.h"
|
||||
#include "TString.h"
|
||||
#include <FileIO/CInputStream.h>
|
||||
#include <FileIO/COutputStream.h>
|
||||
|
||||
class CFourCC
|
||||
{
|
||||
char mFourCC[4];
|
||||
public:
|
||||
// Constructors
|
||||
CFourCC();
|
||||
CFourCC(const char *src);
|
||||
CFourCC(const TString& src);
|
||||
CFourCC(u32 src);
|
||||
CFourCC(CInputStream& src);
|
||||
|
||||
// Functionality
|
||||
void Write(COutputStream& Output);
|
||||
u32 ToLong() const;
|
||||
TString ToString() const;
|
||||
CFourCC ToUpper() const;
|
||||
|
||||
// Operators
|
||||
CFourCC& operator=(const char *src);
|
||||
CFourCC& operator=(const TString& src);
|
||||
CFourCC& operator=(u32 src);
|
||||
bool operator==(const CFourCC& other) const;
|
||||
bool operator!=(const CFourCC& other) const;
|
||||
bool operator>(const CFourCC& other) const;
|
||||
bool operator>=(const CFourCC& other) const;
|
||||
bool operator<(const CFourCC& other) const;
|
||||
bool operator<=(const CFourCC& other) const;
|
||||
char operator[](int index);
|
||||
const char operator[](int index) const;
|
||||
};
|
||||
|
||||
#endif // CFOURCC_H
|
||||
72
src/Common/CHashFNV1A.cpp
Normal file
72
src/Common/CHashFNV1A.cpp
Normal 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 TString& v)
|
||||
{
|
||||
HashData(v.Data(), v.Size());
|
||||
}
|
||||
36
src/Common/CHashFNV1A.h
Normal file
36
src/Common/CHashFNV1A.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef CHASHFNV1A_H
|
||||
#define CHASHFNV1A_H
|
||||
|
||||
#include "types.h"
|
||||
#include "TString.h"
|
||||
|
||||
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 TString& v);
|
||||
};
|
||||
|
||||
#endif // CHASHFNV1A_H
|
||||
89
src/Common/CTimer.cpp
Normal file
89
src/Common/CTimer.cpp
Normal 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
src/Common/CTimer.h
Normal file
28
src/Common/CTimer.h
Normal 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
|
||||
300
src/Common/CUniqueID.cpp
Normal file
300
src/Common/CUniqueID.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
#include "CUniqueID.h"
|
||||
#include <Common/TString.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]);
|
||||
}
|
||||
|
||||
TString CUniqueID::ToString() const
|
||||
{
|
||||
switch (mLength)
|
||||
{
|
||||
case e32Bit:
|
||||
return TString::FromInt32(ToLong(), 8);
|
||||
|
||||
case e64Bit:
|
||||
return TString::FromInt64(ToLongLong(), 16);
|
||||
|
||||
case e128Bit:
|
||||
// todo: TString should have a "FromInt128" function
|
||||
std::stringstream Ret;
|
||||
Ret << std::hex << std::setfill('0');
|
||||
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
Ret << std::setw(2) << (u32) mID[i];
|
||||
|
||||
return Ret.str();
|
||||
}
|
||||
|
||||
return "INVALID ID LENGTH";
|
||||
}
|
||||
|
||||
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(const TString& String)
|
||||
{
|
||||
// If the input is a hex ID in string form, then preserve it... otherwise, generate an ID by hashing the string
|
||||
TString Name = String.GetFileName(false);
|
||||
u32 NameLength = Name.Length();
|
||||
|
||||
if (Name.IsHexString())
|
||||
{
|
||||
if (NameLength == 8)
|
||||
{
|
||||
CUniqueID ID;
|
||||
ID.mLength = e32Bit;
|
||||
|
||||
u32 LongID = Name.ToInt32();
|
||||
|
||||
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 = Name.ToInt64();
|
||||
|
||||
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;
|
||||
Name.ToInt128((char*) ID.mID);
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
return CUniqueID(String.Hash64());
|
||||
}
|
||||
|
||||
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);
|
||||
57
src/Common/CUniqueID.h
Normal file
57
src/Common/CUniqueID.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef CUNIQUEID_H
|
||||
#define CUNIQUEID_H
|
||||
|
||||
#include "types.h"
|
||||
#include "TString.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;
|
||||
TString 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(const TString& String);
|
||||
static CUniqueID FromData(void *pData, EUIDLength Length);
|
||||
static CUniqueID RandomID();
|
||||
|
||||
static CUniqueID skInvalidID32;
|
||||
static CUniqueID skInvalidID64;
|
||||
static CUniqueID skInvalidID128;
|
||||
};
|
||||
|
||||
#endif // CUNIQUEID_H
|
||||
95
src/Common/Common.pro
Normal file
95
src/Common/Common.pro
Normal file
@@ -0,0 +1,95 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2015-12-13T15:27:18
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT -= core gui
|
||||
|
||||
CONFIG += staticlib
|
||||
TEMPLATE = lib
|
||||
DESTDIR = $$PWD/../../build/Common
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
CONFIG (debug, debug|release) {
|
||||
# Debug Config
|
||||
OBJECTS_DIR = $$PWD/../../build/Common/debug
|
||||
TARGET = Commond
|
||||
|
||||
# Debug Libs
|
||||
LIBS += -L$$PWD/../../externals/FileIO/lib/ -lFileIOd
|
||||
}
|
||||
|
||||
CONFIG (release, debug|release) {
|
||||
# Release Config
|
||||
OBJECTS_DIR = $$PWD/../../build/Common/release
|
||||
TARGET = Common
|
||||
|
||||
# Release Libs
|
||||
LIBS += -L$$PWD/../../externals/FileIO/lib/ -lFileIO
|
||||
}
|
||||
|
||||
# Debug/Release Libs
|
||||
LIBS += -L$$PWD/../../externals/lzo-2.08/lib -llzo-2.08 \
|
||||
-L$$PWD/../../externals/zlib/lib -lzdll \
|
||||
|
||||
# Include Paths
|
||||
INCLUDEPATH += $$PWD/.. \
|
||||
$$PWD/../../externals/FileIO/include \
|
||||
$$PWD/../../externals/glm/glm \
|
||||
$$PWD/../../externals/lzo-2.08/include \
|
||||
$$PWD/../../externals/zlib/include
|
||||
|
||||
# Source Files
|
||||
HEADERS += \
|
||||
AnimUtil.h \
|
||||
CColor.h \
|
||||
CFourCC.h \
|
||||
CHashFNV1A.h \
|
||||
CompressionUtil.h \
|
||||
CTimer.h \
|
||||
CUniqueID.h \
|
||||
EKeyInputs.h \
|
||||
EMouseInputs.h \
|
||||
EnumUtil.h \
|
||||
ETransformSpace.h \
|
||||
TString.h \
|
||||
types.h \
|
||||
Math/CAABox.h \
|
||||
Math/CFrustumPlanes.h \
|
||||
Math/CMatrix4f.h \
|
||||
Math/CPlane.h \
|
||||
Math/CQuaternion.h \
|
||||
Math/CRay.h \
|
||||
Math/CTransform4f.h \
|
||||
Math/CVector2f.h \
|
||||
Math/CVector2i.h \
|
||||
Math/CVector3f.h \
|
||||
Math/CVector4f.h \
|
||||
Math/Math.h
|
||||
|
||||
SOURCES += \
|
||||
AnimUtil.cpp \
|
||||
CColor.cpp \
|
||||
CFourCC.cpp \
|
||||
CHashFNV1A.cpp \
|
||||
CompressionUtil.cpp \
|
||||
CTimer.cpp \
|
||||
CUniqueID.cpp \
|
||||
TString.cpp \
|
||||
Math/CAABox.cpp \
|
||||
Math/CFrustumPlanes.cpp \
|
||||
Math/CMatrix4f.cpp \
|
||||
Math/CPlane.cpp \
|
||||
Math/CQuaternion.cpp \
|
||||
Math/CRay.cpp \
|
||||
Math/CTransform4f.cpp \
|
||||
Math/CVector2f.cpp \
|
||||
Math/CVector2i.cpp \
|
||||
Math/CVector3f.cpp \
|
||||
Math/CVector4f.cpp \
|
||||
Math/Math.cpp
|
||||
39
src/Common/CompressionUtil.cpp
Normal file
39
src/Common/CompressionUtil.cpp
Normal 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
src/Common/CompressionUtil.h
Normal file
11
src/Common/CompressionUtil.h
Normal 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
src/Common/EKeyInputs.h
Normal file
21
src/Common/EKeyInputs.h
Normal 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
src/Common/EMouseInputs.h
Normal file
15
src/Common/EMouseInputs.h
Normal 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
|
||||
|
||||
43
src/Common/EnumUtil.h
Normal file
43
src/Common/EnumUtil.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#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; \
|
||||
} \
|
||||
inline X operator|(const X& A, const unsigned int B) { \
|
||||
return (X) ((int) A | B); \
|
||||
} \
|
||||
inline void operator|= (X& A, unsigned int B) { \
|
||||
A = A | B; \
|
||||
} \
|
||||
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; \
|
||||
} \
|
||||
inline X operator&(const X& A, const unsigned int B) { \
|
||||
return (X) ((int) A & B); \
|
||||
} \
|
||||
inline void operator&= (X& A, unsigned int B) { \
|
||||
A = A & B; \
|
||||
}
|
||||
|
||||
#endif // ENUMUTIL
|
||||
|
||||
186
src/Common/Math/CAABox.cpp
Normal file
186
src/Common/Math/CAABox.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#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::Size() const
|
||||
{
|
||||
return (mMax - mMin);
|
||||
}
|
||||
|
||||
CVector3f CAABox::Min() const
|
||||
{
|
||||
return mMin;
|
||||
}
|
||||
|
||||
CVector3f CAABox::Max() const
|
||||
{
|
||||
return mMax;
|
||||
}
|
||||
|
||||
void CAABox::SetMin(const CVector3f& min)
|
||||
{
|
||||
mMin = min;
|
||||
}
|
||||
|
||||
void CAABox::SetMax(const CVector3f& max)
|
||||
{
|
||||
mMax = max;
|
||||
}
|
||||
|
||||
bool CAABox::IsNull() const
|
||||
{
|
||||
return (Size() == CVector3f::skZero);
|
||||
}
|
||||
|
||||
bool CAABox::IsInfinite() const
|
||||
{
|
||||
return (Size() == 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);
|
||||
}
|
||||
|
||||
void CAABox::ExpandBy(const CVector3f& amount)
|
||||
{
|
||||
CVector3f halfAmount = amount / 2.f;
|
||||
mMin -= halfAmount;
|
||||
mMax += halfAmount;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
CAABox CAABox::operator+(const CVector3f& translate) const
|
||||
{
|
||||
return CAABox(mMin + translate, mMax + translate);
|
||||
}
|
||||
|
||||
CAABox CAABox::operator*(float scalar) const
|
||||
{
|
||||
return CAABox(mMin * scalar, mMax * scalar);
|
||||
}
|
||||
|
||||
bool CAABox::operator==(const CAABox& Other) const
|
||||
{
|
||||
return ((mMin == Other.mMin) && (mMax == Other.mMax));
|
||||
}
|
||||
|
||||
bool CAABox::operator!=(const CAABox& Other) const
|
||||
{
|
||||
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));
|
||||
56
src/Common/Math/CAABox.h
Normal file
56
src/Common/Math/CAABox.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#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 Size() const;
|
||||
CVector3f Min() const;
|
||||
CVector3f Max() const;
|
||||
void SetMin(const CVector3f& min);
|
||||
void SetMax(const CVector3f& max);
|
||||
bool IsNull() const;
|
||||
bool IsInfinite() const;
|
||||
|
||||
void ExpandBounds(const CVector3f& vtx);
|
||||
void ExpandBounds(const CAABox& AABox);
|
||||
void ExpandBy(const CVector3f& amount);
|
||||
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
|
||||
CAABox operator+(const CVector3f& translate) const;
|
||||
CAABox operator*(float scalar) const;
|
||||
bool operator==(const CAABox& Other) const;
|
||||
bool operator!=(const CAABox& Other) const;
|
||||
|
||||
// Constants
|
||||
static const CAABox skInfinite;
|
||||
static const CAABox skOne;
|
||||
static const CAABox skZero;
|
||||
};
|
||||
|
||||
#endif // CAABOX_H
|
||||
98
src/Common/Math/CFrustumPlanes.cpp
Normal file
98
src/Common/Math/CFrustumPlanes.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "CFrustumPlanes.h"
|
||||
#include <Common/Math.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
CFrustumPlanes::CFrustumPlanes()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CFrustumPlanes::~CFrustumPlanes()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const CPlane& CFrustumPlanes::GetPlane(EFrustumSide side) const
|
||||
{
|
||||
return mPlanes[side];
|
||||
}
|
||||
|
||||
void CFrustumPlanes::SetPlanes(const CVector3f& position, const CVector3f& direction, float fieldOfView, float aspectRatio, float near, float far)
|
||||
{
|
||||
// Calculate up/right vectors
|
||||
CVector3f right = direction.Cross(CVector3f::skUp).Normalized();
|
||||
CVector3f up = right.Cross(direction).Normalized();
|
||||
|
||||
// Calculate dimensions of near plane
|
||||
float nearHeight = 2 * tanf(Math::DegreesToRadians(fieldOfView) / 2.f) * near;
|
||||
float nearWidth = nearHeight * aspectRatio;
|
||||
|
||||
// Define the planes
|
||||
CVector3f nearCenter = position + (direction * near);
|
||||
mPlanes[eNearPlane].Redefine(direction, nearCenter);
|
||||
|
||||
CVector3f farCenter = position + (direction * far);
|
||||
mPlanes[eFarPlane].Redefine(-direction, farCenter);
|
||||
|
||||
CVector3f midRight = nearCenter + (right * (nearWidth / 2.f));
|
||||
CVector3f rightNormal = up.Cross((midRight - position).Normalized());
|
||||
mPlanes[eRightPlane].Redefine(rightNormal, position);
|
||||
|
||||
CVector3f midLeft = nearCenter - (right * (nearWidth / 2.f));
|
||||
CVector3f leftNormal = (midLeft - position).Normalized().Cross(up);
|
||||
mPlanes[eLeftPlane].Redefine(leftNormal, position);
|
||||
|
||||
CVector3f midTop = nearCenter + (up * (nearHeight / 2.f));
|
||||
CVector3f topNormal = (midTop - position).Normalized().Cross(right);
|
||||
mPlanes[eTopPlane].Redefine(topNormal, position);
|
||||
|
||||
CVector3f midBottom = nearCenter - (up * (nearHeight / 2.f));
|
||||
CVector3f bottomNormal = right.Cross((midBottom - position).Normalized());
|
||||
mPlanes[eBottomPlane].Redefine(bottomNormal, position);
|
||||
}
|
||||
|
||||
bool CFrustumPlanes::PointInFrustum(const CVector3f& point) const
|
||||
{
|
||||
for (u32 iPlane = 0; iPlane < 6; iPlane++)
|
||||
{
|
||||
const CPlane& plane = mPlanes[iPlane];
|
||||
|
||||
if (plane.Normal().Dot(point) + plane.Dist() < 0.f)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFrustumPlanes::BoxInFrustum(const CAABox& box) const
|
||||
{
|
||||
CVector3f min = box.Min();
|
||||
CVector3f max = box.Max();
|
||||
|
||||
CVector3f points[8];
|
||||
points[0] = min;
|
||||
points[1] = max;
|
||||
points[2] = CVector3f(min.x, min.y, max.z);
|
||||
points[3] = CVector3f(min.x, max.y, min.z);
|
||||
points[4] = CVector3f(min.x, max.y, max.z);
|
||||
points[5] = CVector3f(max.x, min.y, max.z);
|
||||
points[6] = CVector3f(max.x, max.y, min.z);
|
||||
points[7] = CVector3f(max.x, min.y, min.z);
|
||||
|
||||
for (u32 iPlane = 0; iPlane < 6; iPlane++)
|
||||
{
|
||||
const CPlane& plane = mPlanes[iPlane];
|
||||
int numPoints = 0;
|
||||
|
||||
for (u32 iPoint = 0; iPoint < 8; iPoint++)
|
||||
{
|
||||
if (plane.Normal().Dot(points[iPoint]) + plane.Dist() < 0.f)
|
||||
numPoints++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (numPoints == 8) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
30
src/Common/Math/CFrustumPlanes.h
Normal file
30
src/Common/Math/CFrustumPlanes.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef CFRUSTUMPLANES_H
|
||||
#define CFRUSTUMPLANES_H
|
||||
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/CPlane.h>
|
||||
#include <Common/CVector3f.h>
|
||||
|
||||
class CFrustumPlanes
|
||||
{
|
||||
public:
|
||||
enum EFrustumSide
|
||||
{
|
||||
eNearPlane = 0, eFarPlane = 1,
|
||||
eTopPlane = 2, eBottomPlane = 3,
|
||||
eLeftPlane = 4, eRightPlane = 5
|
||||
};
|
||||
|
||||
private:
|
||||
CPlane mPlanes[6];
|
||||
|
||||
public:
|
||||
CFrustumPlanes();
|
||||
~CFrustumPlanes();
|
||||
const CPlane& GetPlane(EFrustumSide side) const;
|
||||
void SetPlanes(const CVector3f& position, const CVector3f& direction, float fieldOfView, float aspectRatio, float near, float far);
|
||||
bool PointInFrustum(const CVector3f& point) const;
|
||||
bool BoxInFrustum(const CAABox& box) const;
|
||||
};
|
||||
|
||||
#endif // CFRUSTUMPLANES_H
|
||||
241
src/Common/Math/CMatrix4f.cpp
Normal file
241
src/Common/Math/CMatrix4f.cpp
Normal 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
src/Common/Math/CMatrix4f.h
Normal file
50
src/Common/Math/CMatrix4f.h
Normal 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
|
||||
44
src/Common/Math/CPlane.cpp
Normal file
44
src/Common/Math/CPlane.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "CPlane.h"
|
||||
|
||||
CPlane::CPlane()
|
||||
{
|
||||
mNormal = CVector3f::skUp;
|
||||
mDist = 0.f;
|
||||
}
|
||||
|
||||
CPlane::CPlane(const CVector3f& normal, float dist)
|
||||
{
|
||||
mNormal = normal;
|
||||
mDist = dist;
|
||||
}
|
||||
|
||||
CPlane::CPlane(const CVector3f& normal, const CVector3f& origin)
|
||||
{
|
||||
Redefine(normal, origin);
|
||||
}
|
||||
|
||||
void CPlane::Redefine(const CVector3f& normal, const CVector3f& origin)
|
||||
{
|
||||
mNormal = normal;
|
||||
mDist = -normal.Dot(origin);
|
||||
}
|
||||
|
||||
CVector3f CPlane::Normal() const
|
||||
{
|
||||
return mNormal;
|
||||
}
|
||||
|
||||
float CPlane::Dist() const
|
||||
{
|
||||
return mDist;
|
||||
}
|
||||
|
||||
void CPlane::SetNormal(const CVector3f& normal)
|
||||
{
|
||||
mNormal = normal;
|
||||
}
|
||||
|
||||
void CPlane::SetDist(float dist)
|
||||
{
|
||||
mDist = dist;
|
||||
}
|
||||
23
src/Common/Math/CPlane.h
Normal file
23
src/Common/Math/CPlane.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef CPLANE_H
|
||||
#define CPLANE_H
|
||||
|
||||
#include "CVector3f.h"
|
||||
|
||||
class CPlane
|
||||
{
|
||||
CVector3f mNormal;
|
||||
float mDist;
|
||||
|
||||
public:
|
||||
CPlane();
|
||||
CPlane(const CVector3f& normal, float dist);
|
||||
CPlane(const CVector3f& normal, const CVector3f& origin);
|
||||
|
||||
void Redefine(const CVector3f& normal, const CVector3f& origin);
|
||||
CVector3f Normal() const;
|
||||
float Dist() const;
|
||||
void SetNormal(const CVector3f& normal);
|
||||
void SetDist(float dist);
|
||||
};
|
||||
|
||||
#endif // CPLANE_H
|
||||
195
src/Common/Math/CQuaternion.cpp
Normal file
195
src/Common/Math/CQuaternion.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "CQuaternion.h"
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
#include "Math.h"
|
||||
#include "CMatrix4f.h"
|
||||
|
||||
CQuaternion::CQuaternion()
|
||||
{
|
||||
w = 0.f;
|
||||
x = 0.f;
|
||||
y = 0.f;
|
||||
z = 0.f;
|
||||
}
|
||||
|
||||
CQuaternion::CQuaternion(float _w, float _x, float _y, float _z)
|
||||
{
|
||||
w = _w;
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::XAxis()
|
||||
{
|
||||
return (*this * CVector3f::skUnitX);
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::YAxis()
|
||||
{
|
||||
return (*this * CVector3f::skUnitY);
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::ZAxis()
|
||||
{
|
||||
return (*this * CVector3f::skUnitZ);
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::Inverse()
|
||||
{
|
||||
float fNorm = (w * w) + (x * x) + (y * y) + (z * z);
|
||||
|
||||
if (fNorm > 0.f)
|
||||
{
|
||||
float fInvNorm = 1.f / fNorm;
|
||||
return CQuaternion( w * fInvNorm, -x * fInvNorm, -y * fInvNorm, -z * fInvNorm);
|
||||
}
|
||||
else
|
||||
return CQuaternion::skZero;
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::ToEuler()
|
||||
{
|
||||
// There is more than one way to do this conversion, based on rotation order.
|
||||
// But since we only care about the rotation order used in Retro games, which is consistent,
|
||||
// we can just have a single conversion function. Handy!
|
||||
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
|
||||
|
||||
float ex = atan2f(2 * (w*x + y*z), 1 - (2 * (Math::Pow(x,2) + Math::Pow(y,2))));
|
||||
float ey = asinf(2 * (w*y - z*x));
|
||||
float ez = atan2f(2 * (w*z + x*y), 1 - (2 * (Math::Pow(y,2) + Math::Pow(z,2))));
|
||||
return CVector3f(Math::RadiansToDegrees(ex), Math::RadiansToDegrees(ey), Math::RadiansToDegrees(ez));
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
CVector3f CQuaternion::operator*(const CVector3f& vec) const
|
||||
{
|
||||
CVector3f uv, uuv;
|
||||
CVector3f qvec(x, y, z);
|
||||
uv = qvec.Cross(vec);
|
||||
uuv = qvec.Cross(uv);
|
||||
uv *= (2.0f * w);
|
||||
uuv *= 2.0f;
|
||||
|
||||
return vec + uv + uuv;
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::operator*(const CQuaternion& other) const
|
||||
{
|
||||
CQuaternion out;
|
||||
out.w = (-x * other.x) - (y * other.y) - (z * other.z) + (w * other.w);
|
||||
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);
|
||||
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(Math::DegreesToRadians(euler.x), CVector3f(1,0,0));
|
||||
CQuaternion y = CQuaternion::FromAxisAngle(Math::DegreesToRadians(euler.y), CVector3f(0,1,0));
|
||||
CQuaternion z = CQuaternion::FromAxisAngle(Math::DegreesToRadians(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();
|
||||
|
||||
float sa = sinf(angle / 2);
|
||||
quat.w = cosf(angle / 2);
|
||||
quat.x = axis.x * sa;
|
||||
quat.y = axis.y * sa;
|
||||
quat.z = axis.z * sa;
|
||||
return quat;
|
||||
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::FromRotationMatrix(const CMatrix4f& RotMtx)
|
||||
{
|
||||
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
|
||||
CQuaternion out;
|
||||
float trace = RotMtx[0][0] + RotMtx[1][1] + RotMtx[2][2];
|
||||
|
||||
if (trace > 0.f)
|
||||
{
|
||||
float s = Math::Sqrt(trace + 1.f) * 2; // s = 4*w
|
||||
out.w = 0.25f * s;
|
||||
out.x = (RotMtx[2][1] - RotMtx[1][2]) / s;
|
||||
out.y = (RotMtx[0][2] - RotMtx[2][0]) / s;
|
||||
out.z = (RotMtx[1][0] - RotMtx[0][1]) / s;
|
||||
}
|
||||
|
||||
else if ((RotMtx[0][0] > RotMtx[1][1]) && (RotMtx[0][0] > RotMtx[2][2]))
|
||||
{
|
||||
float s = Math::Sqrt(1.f + RotMtx[0][0] - RotMtx[1][1] - RotMtx[2][2]) * 2; // s = 4*x
|
||||
out.w = (RotMtx[2][1] - RotMtx[1][2]) / s;
|
||||
out.x = 0.25f * s;
|
||||
out.y = (RotMtx[0][1] + RotMtx[1][0]) / s;
|
||||
out.z = (RotMtx[0][2] + RotMtx[2][0]) / s;
|
||||
}
|
||||
|
||||
else if (RotMtx[1][1] > RotMtx[2][2]) {
|
||||
float s = Math::Sqrt(1.f + RotMtx[1][1] - RotMtx[0][0] - RotMtx[2][2]) * 2; // s = 4*y
|
||||
out.w = (RotMtx[0][2] - RotMtx[2][0]) / s;
|
||||
out.x = (RotMtx[0][1] + RotMtx[1][0]) / s;
|
||||
out.y = 0.25f * s;
|
||||
out.z = (RotMtx[1][2] + RotMtx[2][1]) / s;
|
||||
}
|
||||
|
||||
else {
|
||||
float s = Math::Sqrt(1.f + RotMtx[2][2] - RotMtx[0][0] - RotMtx[1][1]) * 2; // S=4*qz
|
||||
out.w = (RotMtx[1][0] - RotMtx[0][1]) / s;
|
||||
out.x = (RotMtx[0][2] + RotMtx[2][0]) / s;
|
||||
out.y = (RotMtx[1][2] + RotMtx[2][1]) / s;
|
||||
out.z = 0.25f * s;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::FromAxes(const CVector3f& X, const CVector3f& Y, const CVector3f& Z)
|
||||
{
|
||||
CMatrix4f RotMtx(X.x, Y.x, Z.x, 0.f,
|
||||
X.y, Y.y, Z.y, 0.f,
|
||||
X.z, Y.z, Z.z, 0.f,
|
||||
0.f, 0.f, 0.f, 1.f);
|
||||
|
||||
return CQuaternion::FromRotationMatrix(RotMtx);
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::skIdentity = CQuaternion(1.f, 0.f, 0.f, 0.f);
|
||||
CQuaternion CQuaternion::skZero = CQuaternion(0.f, 0.f, 0.f, 0.f);
|
||||
35
src/Common/Math/CQuaternion.h
Normal file
35
src/Common/Math/CQuaternion.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef CQUATERNION_H
|
||||
#define CQUATERNION_H
|
||||
|
||||
#include "CVector3f.h"
|
||||
|
||||
class CQuaternion
|
||||
{
|
||||
public:
|
||||
float w, x, y, z;
|
||||
|
||||
CQuaternion();
|
||||
CQuaternion(float _w, float _x, float _y, float _z);
|
||||
|
||||
CVector3f XAxis();
|
||||
CVector3f YAxis();
|
||||
CVector3f ZAxis();
|
||||
CQuaternion Inverse();
|
||||
CVector3f ToEuler();
|
||||
|
||||
// Operators
|
||||
CVector3f operator*(const CVector3f& vec) const;
|
||||
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 FromRotationMatrix(const CMatrix4f& RotMtx);
|
||||
static CQuaternion FromAxes(const CVector3f& X, const CVector3f& Y, const CVector3f& Z);
|
||||
|
||||
static CQuaternion skIdentity;
|
||||
static CQuaternion skZero;
|
||||
};
|
||||
|
||||
#endif // CQUATERNION_H
|
||||
43
src/Common/Math/CRay.cpp
Normal file
43
src/Common/Math/CRay.cpp
Normal 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
src/Common/Math/CRay.h
Normal file
35
src/Common/Math/CRay.h
Normal 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
|
||||
309
src/Common/Math/CTransform4f.cpp
Normal file
309
src/Common/Math/CTransform4f.cpp
Normal 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
src/Common/Math/CTransform4f.h
Normal file
70
src/Common/Math/CTransform4f.h
Normal 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
|
||||
186
src/Common/Math/CVector2f.cpp
Normal file
186
src/Common/Math/CVector2f.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
float CVector2f::Magnitude() const
|
||||
{
|
||||
return sqrtf(SquaredMagnitude());
|
||||
}
|
||||
|
||||
float CVector2f::SquaredMagnitude() const
|
||||
{
|
||||
return Dot(*this);
|
||||
}
|
||||
|
||||
CVector2f CVector2f::Normalized() const
|
||||
{
|
||||
return *this / Magnitude();
|
||||
}
|
||||
|
||||
float CVector2f::Dot(const CVector2f& other) const
|
||||
{
|
||||
return ((x * other.x) + (y * other.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));
|
||||
}
|
||||
|
||||
CVector2f CVector2f::operator-() const
|
||||
{
|
||||
return CVector2f(-x, -y);
|
||||
}
|
||||
|
||||
float& CVector2f::operator[](long index)
|
||||
{
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
const float& CVector2f::operator[](long index) const
|
||||
{
|
||||
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);
|
||||
53
src/Common/Math/CVector2f.h
Normal file
53
src/Common/Math/CVector2f.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#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);
|
||||
|
||||
float Magnitude() const;
|
||||
float SquaredMagnitude() const;
|
||||
CVector2f Normalized() const;
|
||||
float Dot(const CVector2f& other) const;
|
||||
|
||||
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;
|
||||
CVector2f operator-() const;
|
||||
float& operator[](long index);
|
||||
const float& operator[](long index) const;
|
||||
|
||||
// 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
src/Common/Math/CVector2i.cpp
Normal file
139
src/Common/Math/CVector2i.cpp
Normal 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
src/Common/Math/CVector2i.h
Normal file
39
src/Common/Math/CVector2i.h
Normal 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
|
||||
309
src/Common/Math/CVector3f.cpp
Normal file
309
src/Common/Math/CVector3f.cpp
Normal file
@@ -0,0 +1,309 @@
|
||||
#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 Dot(*this);
|
||||
}
|
||||
|
||||
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);
|
||||
const CVector3f CVector3f::skUnitX = CVector3f(1.f, 0.f, 0.f);
|
||||
const CVector3f CVector3f::skUnitY = CVector3f(0.f, 1.f, 0.f);
|
||||
const CVector3f CVector3f::skUnitZ = CVector3f(0.f, 0.f, 1.f);
|
||||
const CVector3f CVector3f::skRight = CVector3f::skUnitX;
|
||||
const CVector3f CVector3f::skLeft = -CVector3f::skUnitX;
|
||||
const CVector3f CVector3f::skForward = CVector3f::skUnitY;
|
||||
const CVector3f CVector3f::skBack = -CVector3f::skUnitY;
|
||||
const CVector3f CVector3f::skUp = CVector3f::skUnitZ;
|
||||
const CVector3f CVector3f::skDown = -CVector3f::skUnitZ;
|
||||
|
||||
// ************ 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;
|
||||
}
|
||||
92
src/Common/Math/CVector3f.h
Normal file
92
src/Common/Math/CVector3f.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#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;
|
||||
static const CVector3f skUnitX;
|
||||
static const CVector3f skUnitY;
|
||||
static const CVector3f skUnitZ;
|
||||
static const CVector3f skRight;
|
||||
static const CVector3f skLeft;
|
||||
static const CVector3f skForward;
|
||||
static const CVector3f skBack;
|
||||
static const CVector3f skUp;
|
||||
static const CVector3f skDown;
|
||||
|
||||
// Other
|
||||
friend std::ostream& operator<<(std::ostream& o, const CVector3f& Vector);
|
||||
};
|
||||
|
||||
#endif // CVECTOR3F
|
||||
273
src/Common/Math/CVector4f.cpp
Normal file
273
src/Common/Math/CVector4f.cpp
Normal 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
src/Common/Math/CVector4f.h
Normal file
68
src/Common/Math/CVector4f.h
Normal 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
|
||||
11
src/Common/Math/ETransformSpace.h
Normal file
11
src/Common/Math/ETransformSpace.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef ETRANSFORMSPACE
|
||||
#define ETRANSFORMSPACE
|
||||
|
||||
enum ETransformSpace
|
||||
{
|
||||
eWorldTransform,
|
||||
eLocalTransform
|
||||
};
|
||||
|
||||
#endif // ETRANSFORMSPACE
|
||||
|
||||
352
src/Common/Math/Math.cpp
Normal file
352
src/Common/Math/Math.cpp
Normal file
@@ -0,0 +1,352 @@
|
||||
#include "Math.h"
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <gtc/matrix_transform.hpp>
|
||||
|
||||
namespace Math
|
||||
{
|
||||
|
||||
float Abs(float v)
|
||||
{
|
||||
return fabs(v);
|
||||
}
|
||||
|
||||
float Pow(float Base, float Exponent)
|
||||
{
|
||||
return pow(Base, Exponent);
|
||||
}
|
||||
|
||||
float Sqrt(float v)
|
||||
{
|
||||
return sqrtf(v);
|
||||
}
|
||||
|
||||
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) );
|
||||
}
|
||||
|
||||
float DegreesToRadians(float deg)
|
||||
{
|
||||
return deg * skPi / 180.f;
|
||||
}
|
||||
|
||||
float RadiansToDegrees(float rad)
|
||||
{
|
||||
return rad * 180.f / skPi;
|
||||
}
|
||||
|
||||
std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane)
|
||||
{
|
||||
// Code based on ray/plane intersect code from Ogre
|
||||
// https://bitbucket.org/sinbad/ogre/src/197116fd2ac62c57cdeed1666f9866c3dddd4289/OgreMain/src/OgreMath.cpp?at=default#OgreMath.cpp-350
|
||||
|
||||
// Are ray and plane parallel?
|
||||
float denom = plane.Normal().Dot(ray.Direction());
|
||||
|
||||
if (Abs(denom) < FLT_EPSILON)
|
||||
return std::pair<bool,float>(false, 0.f);
|
||||
|
||||
// Not parallel
|
||||
float nom = plane.Normal().Dot(ray.Origin()) + plane.Dist();
|
||||
float t = -(nom / denom);
|
||||
return std::pair<bool,float>(t >= 0.f, t);
|
||||
}
|
||||
|
||||
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.f);
|
||||
if (Box.IsInfinite()) return std::pair<bool,float>(true, 0.f);
|
||||
|
||||
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.f);
|
||||
}
|
||||
|
||||
// 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> RayLineIntersection(const CRay& ray, const CVector3f& pointA,
|
||||
const CVector3f& pointB, float threshold)
|
||||
{
|
||||
// http://geomalgorithms.com/a07-_distance.html
|
||||
// http://www.gamedev.net/topic/589705-rayline-intersection-in-3d/
|
||||
CVector3f u = ray.Direction();
|
||||
CVector3f v = pointB - pointA;
|
||||
CVector3f w = ray.Origin() - pointA;
|
||||
float a = u.Dot(u);
|
||||
float b = u.Dot(v);
|
||||
float c = v.Dot(v);
|
||||
float d = u.Dot(w);
|
||||
float e = v.Dot(w);
|
||||
float D = a * c - b * b;
|
||||
float sc, sN, sD = D;
|
||||
float tc, tN, tD = D;
|
||||
|
||||
if (D < FLT_EPSILON) {
|
||||
sN = 0.f;
|
||||
sD = 1.f;
|
||||
tN = e;
|
||||
tD = c;
|
||||
}
|
||||
else {
|
||||
sN = b * e - c * d;
|
||||
tN = a * e - b * d;
|
||||
|
||||
if (sN < 0.f) {
|
||||
sN = 0.f;
|
||||
tN = e;
|
||||
tD = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (tN < 0.f) {
|
||||
tN = 0.f;
|
||||
|
||||
if (-d < 0.f)
|
||||
sN = 0.f;
|
||||
else {
|
||||
sN = -d;
|
||||
sD = a;
|
||||
}
|
||||
}
|
||||
else if (tN > tD) {
|
||||
tN = tD;
|
||||
|
||||
if (-d + b < 0.f)
|
||||
sN = 0.f;
|
||||
else {
|
||||
sN = -d + b;
|
||||
sD = a;
|
||||
}
|
||||
}
|
||||
|
||||
sc = (fabs(sN) < FLT_EPSILON ? 0.f : sN / sD);
|
||||
tc = (fabs(tN) < FLT_EPSILON ? 0.f : tN / tD);
|
||||
|
||||
CVector3f dP = w + (u * sc) - (v * tc);
|
||||
bool hit = (dP.Magnitude() <= threshold);
|
||||
return std::pair<bool,float>(hit, sc);
|
||||
}
|
||||
|
||||
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.f);
|
||||
}
|
||||
else if (denom >= - std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
// Parallel or triangle area is close to zero when
|
||||
// the plane normal not normalised.
|
||||
return std::pair<bool,float>(false, 0.f);
|
||||
}
|
||||
|
||||
t = FaceNormal.Dot(vtxA - Ray.Origin()) / denom;
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
// Intersection is behind origin
|
||||
return std::pair<bool,float>(false, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
|
||||
return std::pair<bool,float>(false, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<bool,float>(true, t);
|
||||
}
|
||||
|
||||
CMatrix4f PerspectiveMatrix(float fov, float aspect, float near, float far)
|
||||
{
|
||||
// todo: don't use glm
|
||||
return CMatrix4f::FromGlmMat4(glm::perspective(fov, aspect, near, far)).Transpose();
|
||||
}
|
||||
|
||||
CMatrix4f OrthographicMatrix(float left, float right, float bottom, float top, float near, float far)
|
||||
{
|
||||
return CMatrix4f::FromGlmMat4(glm::ortho(left, right, bottom, top, near, far)).Transpose();
|
||||
}
|
||||
|
||||
} // End namespace
|
||||
47
src/Common/Math/Math.h
Normal file
47
src/Common/Math/Math.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef MATH
|
||||
#define MATH
|
||||
|
||||
#include "CAABox.h"
|
||||
#include "CRay.h"
|
||||
#include "CPlane.h"
|
||||
#include "CVector3f.h"
|
||||
#include "SRayIntersection.h"
|
||||
#include <utility>
|
||||
|
||||
namespace Math
|
||||
{
|
||||
|
||||
float Abs(float v);
|
||||
|
||||
float Pow(float Base, float Exponent);
|
||||
|
||||
float Sqrt(float v);
|
||||
|
||||
float Distance(const CVector3f& A, const CVector3f& B);
|
||||
|
||||
float DegreesToRadians(float deg);
|
||||
|
||||
float RadiansToDegrees(float rad);
|
||||
|
||||
std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane);
|
||||
|
||||
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box);
|
||||
|
||||
std::pair<bool,float> RayLineIntersection(const CRay& ray, const CVector3f& pointA,
|
||||
const CVector3f& pointB, float threshold = 0.02f);
|
||||
|
||||
std::pair<bool,float> RayTriangleIntersection(const CRay& Ray, const CVector3f& PointA,
|
||||
const CVector3f& PointB, const CVector3f& PointC,
|
||||
bool AllowBackfaces = false);
|
||||
|
||||
CMatrix4f PerspectiveMatrix(float fov, float aspect, float near, float far);
|
||||
|
||||
CMatrix4f OrthographicMatrix(float left, float right, float bottom, float top, float near, float far);
|
||||
|
||||
// Constants
|
||||
static const float skPi = 3.14159265358979323846f;
|
||||
static const float skHalfPi = skPi / 2.f;
|
||||
}
|
||||
|
||||
#endif // MATH
|
||||
|
||||
115
src/Common/TString.cpp
Normal file
115
src/Common/TString.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "TString.h"
|
||||
#include <FileIO/IOUtil.h>
|
||||
|
||||
// ************ TString ************
|
||||
TString::TString(const wchar_t* pkText)
|
||||
{
|
||||
*this = TWideString(pkText).ToUTF8();
|
||||
}
|
||||
|
||||
TString::TString(const std::wstring& rkText)
|
||||
{
|
||||
*this = TWideString(rkText).ToUTF8();
|
||||
}
|
||||
|
||||
TString::TString(const TWideString& rkText)
|
||||
{
|
||||
*this = rkText.ToUTF8();
|
||||
}
|
||||
|
||||
TWideString TString::ToUTF16() const
|
||||
{
|
||||
TWideString out;
|
||||
const char *pkCStr = CString();
|
||||
|
||||
while (pkCStr[0])
|
||||
{
|
||||
// Step 1: decode UTF-8 code point
|
||||
wchar_t CodePoint;
|
||||
|
||||
// One byte
|
||||
if ((pkCStr[0] & 0x80) == 0)
|
||||
{
|
||||
CodePoint = pkCStr[0] & 0x7FFFFFFF;
|
||||
pkCStr++;
|
||||
}
|
||||
|
||||
// Two bytes
|
||||
else if ((pkCStr[0] & 0xE0) == 0xC0)
|
||||
{
|
||||
CodePoint = (((pkCStr[0] & 0x1F) << 6) |
|
||||
(pkCStr[1] & 0x3F));
|
||||
pkCStr += 2;
|
||||
}
|
||||
|
||||
// Three bytes
|
||||
else if ((pkCStr[0] & 0xF0) == 0xE0)
|
||||
{
|
||||
CodePoint = (((pkCStr[0] & 0xF) << 12) |
|
||||
((pkCStr[1] & 0x3F) << 6) |
|
||||
(pkCStr[2] & 0x3F));
|
||||
pkCStr += 3;
|
||||
}
|
||||
|
||||
// Four bytes
|
||||
else if ((pkCStr[0] & 0xF8) == 0xF0)
|
||||
{
|
||||
CodePoint = (((pkCStr[0] & 0x7) << 18) |
|
||||
((pkCStr[1] & 0x3F) << 12) |
|
||||
((pkCStr[2] & 0x3F) << 6) |
|
||||
(pkCStr[3] & 0x3F));
|
||||
pkCStr += 4;
|
||||
}
|
||||
|
||||
// Five bytes
|
||||
else if ((pkCStr[0] & 0xFC) == 0xF8)
|
||||
{
|
||||
CodePoint = (((pkCStr[0] & 0x3) << 24) |
|
||||
((pkCStr[1] & 0x3F) << 18) |
|
||||
((pkCStr[2] & 0x3F) << 12) |
|
||||
((pkCStr[3] & 0x3F) << 6) |
|
||||
(pkCStr[4] & 0x3F));
|
||||
pkCStr += 5;
|
||||
}
|
||||
|
||||
// Six bytes
|
||||
else if ((pkCStr[0] & 0xFE) == 0xFC)
|
||||
{
|
||||
CodePoint = (((pkCStr[0] & 0x1) << 30) |
|
||||
((pkCStr[1] & 0x3F) << 24) |
|
||||
((pkCStr[2] & 0x3F) << 18) |
|
||||
((pkCStr[3] & 0x3F) << 12) |
|
||||
((pkCStr[4] & 0x3F) << 6) |
|
||||
(pkCStr[5] & 0x3F));
|
||||
pkCStr += 6;
|
||||
}
|
||||
|
||||
// Step 2: Append to output string
|
||||
if ( ((CodePoint >= 0) && (CodePoint <= 0xD7FF)) ||
|
||||
((CodePoint >= 0xE000) && (CodePoint <= 0xFFFF)) )
|
||||
out.Append((wchar_t) (CodePoint & 0xFFFF));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// ************ TWideString ************
|
||||
TWideString::TWideString(const char* pkText)
|
||||
{
|
||||
*this = TString(pkText).ToUTF16();
|
||||
}
|
||||
|
||||
TWideString::TWideString(const std::string& rkText)
|
||||
{
|
||||
*this = TString(rkText).ToUTF16();
|
||||
}
|
||||
|
||||
TWideString::TWideString(const TString& rkText)
|
||||
{
|
||||
*this = rkText.ToUTF16();
|
||||
}
|
||||
|
||||
TString TWideString::ToUTF8() const
|
||||
{
|
||||
return "UTF16 to UTF8 currently unsupported";
|
||||
}
|
||||
821
src/Common/TString.h
Normal file
821
src/Common/TString.h
Normal file
@@ -0,0 +1,821 @@
|
||||
#ifndef TSTRING_H
|
||||
#define TSTRING_H
|
||||
|
||||
#include "types.h"
|
||||
#include <FileIO/IOUtil.h>
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
/* This is a string class which is essentially a wrapper around std::basic_string.
|
||||
* The reason for this is because there are a lot of string functions I use very
|
||||
* frequently that std::string is missing and this is more convenient than creating
|
||||
* all these functions externally. I've chosen to remove access to the default
|
||||
* std::basic_string functions and replace them with a custom API for consistency.
|
||||
*
|
||||
* Most of the file contains an implementation for a template base class, TBasicString.
|
||||
* Afterwards we define the following subclasses/typedefs:
|
||||
*
|
||||
* - TBasicString<char> - TString
|
||||
* - TBasicString<wchar_t> - TWideString
|
||||
* - std::list<TString> - TStringList
|
||||
* - std::list<TWideString> - TWideStringList
|
||||
*
|
||||
* TString and TWideString have functions for converting between each other. For these
|
||||
* functions, TString is expected to be encoded in UTF-8 and TWideString is expected to
|
||||
* be encoded in UTF-16.
|
||||
*/
|
||||
|
||||
// ************ TBasicString ************
|
||||
template<class CharType>
|
||||
class TBasicString
|
||||
{
|
||||
typedef TBasicString<CharType> _TString;
|
||||
typedef std::basic_string<CharType> _TStdString;
|
||||
typedef std::list<_TString> _TStringList;
|
||||
|
||||
protected:
|
||||
_TStdString mInternalString;
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
TBasicString()
|
||||
: mInternalString()
|
||||
{
|
||||
}
|
||||
|
||||
TBasicString(u32 size)
|
||||
: mInternalString(size, 0)
|
||||
{
|
||||
}
|
||||
|
||||
TBasicString(u32 size, CharType fill)
|
||||
: mInternalString(size, fill)
|
||||
{
|
||||
}
|
||||
|
||||
TBasicString(const CharType* pkText)
|
||||
: mInternalString(pkText)
|
||||
{
|
||||
}
|
||||
|
||||
TBasicString(const CharType* pkText, u32 length)
|
||||
: mInternalString(pkText, length)
|
||||
{
|
||||
}
|
||||
|
||||
TBasicString(const _TStdString& rkText)
|
||||
: mInternalString(rkText)
|
||||
{
|
||||
}
|
||||
|
||||
// Data Accessors
|
||||
inline const CharType* CString() const
|
||||
{
|
||||
return mInternalString.c_str();
|
||||
}
|
||||
|
||||
inline const CharType* Data() const
|
||||
{
|
||||
return mInternalString.data();
|
||||
}
|
||||
|
||||
inline CharType At(u32 pos) const
|
||||
{
|
||||
#if _DEBUG
|
||||
if (Size() <= pos)
|
||||
throw std::out_of_range("Invalid position passed to TBasicString::At()");
|
||||
#endif
|
||||
return mInternalString.at(pos);
|
||||
}
|
||||
|
||||
inline CharType Front() const
|
||||
{
|
||||
return (Size() > 0 ? mInternalString[0] : 0);
|
||||
}
|
||||
|
||||
inline CharType Back() const
|
||||
{
|
||||
return (Size() > 0 ? mInternalString[Size() - 1] : 0);
|
||||
}
|
||||
|
||||
inline u32 Size() const
|
||||
{
|
||||
return mInternalString.size();
|
||||
}
|
||||
|
||||
inline u32 Length() const
|
||||
{
|
||||
return Size();
|
||||
}
|
||||
|
||||
inline u32 IndexOf(const CharType* pkCharacters) const
|
||||
{
|
||||
size_t pos = mInternalString.find_first_of(pkCharacters);
|
||||
|
||||
if (pos == _TStdString::npos)
|
||||
return -1;
|
||||
else
|
||||
return (u32) pos;
|
||||
}
|
||||
|
||||
inline u32 LastIndexOf(const CharType* pkCharacters) const
|
||||
{
|
||||
size_t pos = mInternalString.find_last_of(pkCharacters);
|
||||
|
||||
if (pos == _TStdString::npos)
|
||||
return -1;
|
||||
else
|
||||
return (u32) pos;
|
||||
}
|
||||
|
||||
// Modify String
|
||||
inline _TString SubString(int startPos, int length) const
|
||||
{
|
||||
return mInternalString.substr(startPos, length);
|
||||
}
|
||||
|
||||
inline void Insert(u32 pos, CharType c)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (Size() < pos)
|
||||
throw std::out_of_range("Invalid pos passed to TBasicString::Insert(CharType)");
|
||||
#endif
|
||||
mInternalString.insert(pos, 1, c);
|
||||
}
|
||||
|
||||
inline void Insert(u32 pos, const CharType* pkStr)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (Size() < pos)
|
||||
throw std::out_of_range("Invalid pos passed to TBasicString::Insert(const CharType*)");
|
||||
#endif
|
||||
mInternalString.insert(pos, pkStr);
|
||||
}
|
||||
|
||||
inline void Insert(u32 pos, const _TString& rkStr)
|
||||
{
|
||||
Insert(pos, rkStr.CString());
|
||||
}
|
||||
|
||||
inline void Append(CharType c)
|
||||
{
|
||||
mInternalString.append(1, c);
|
||||
}
|
||||
|
||||
inline void Append(const CharType* pkText)
|
||||
{
|
||||
mInternalString.append(pkText);
|
||||
}
|
||||
|
||||
inline void Append(const _TString& rkStr)
|
||||
{
|
||||
mInternalString.append(rkStr.CString());
|
||||
}
|
||||
|
||||
inline void Prepend(CharType c)
|
||||
{
|
||||
Insert(0, c);
|
||||
}
|
||||
|
||||
inline void Prepend(const CharType* pkText)
|
||||
{
|
||||
Insert(0, pkText);
|
||||
}
|
||||
|
||||
inline void Prepend(const _TString& rkStr)
|
||||
{
|
||||
Insert(0, rkStr);
|
||||
}
|
||||
|
||||
_TString ToUpper() const
|
||||
{
|
||||
// todo: doesn't handle accented characters
|
||||
_TString out(Size());
|
||||
|
||||
for (u32 iChar = 0; iChar < Size(); iChar++)
|
||||
{
|
||||
CharType c = At(iChar);
|
||||
|
||||
if (c >= 'a' && c <= 'z')
|
||||
out[iChar] = c - 0x20;
|
||||
else
|
||||
out[iChar] = c;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
_TString ToLower() const
|
||||
{
|
||||
// todo: doesn't handle accented characters
|
||||
_TString out(Size());
|
||||
|
||||
for (u32 iChar = 0; iChar < Size(); iChar++)
|
||||
{
|
||||
CharType c = At(iChar);
|
||||
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
out[iChar] = c + 0x20;
|
||||
else
|
||||
out[iChar] = c;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
_TString Trimmed() const
|
||||
{
|
||||
int start, end;
|
||||
|
||||
for (u32 iChar = 0; iChar < Size(); iChar++)
|
||||
{
|
||||
if (!IsWhitespace(mInternalString[iChar]))
|
||||
{
|
||||
start = iChar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int iChar = Size() - 1; iChar >= 0; iChar--)
|
||||
{
|
||||
if (!IsWhitespace(mInternalString[iChar]))
|
||||
{
|
||||
end = iChar + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SubString(start, end - start);
|
||||
}
|
||||
|
||||
inline _TString Truncate(u32 amount) const
|
||||
{
|
||||
return SubString(0, amount);
|
||||
}
|
||||
|
||||
inline _TString ChopFront(u32 amount) const
|
||||
{
|
||||
return SubString(amount, Size() - amount);
|
||||
}
|
||||
|
||||
inline _TString ChopBack(u32 amount) const
|
||||
{
|
||||
return SubString(0, Size() - amount);
|
||||
}
|
||||
|
||||
u32 Hash32() const
|
||||
{
|
||||
u32 hash = 0;
|
||||
|
||||
for (u32 iChar = 0; iChar < Size(); iChar++)
|
||||
{
|
||||
hash += At(iChar);
|
||||
hash *= 101;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
u64 Hash64() const
|
||||
{
|
||||
u64 hash = 0;
|
||||
|
||||
for (u32 iChar = 0; iChar < Size(); iChar++)
|
||||
{
|
||||
hash += At(iChar);
|
||||
hash *= 101;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
inline u32 ToInt32(int base = 16) const
|
||||
{
|
||||
return std::stoul(mInternalString, nullptr, base);
|
||||
}
|
||||
|
||||
inline u64 ToInt64(int base = 16) const
|
||||
{
|
||||
return std::stoull(mInternalString, nullptr, base);
|
||||
}
|
||||
|
||||
void ToInt128(CharType* pOut, int base = 16) const
|
||||
{
|
||||
// TODO: only works in base 16
|
||||
u64 part1 = std::stoull(mInternalString.substr(0, 16), nullptr, base);
|
||||
u64 part2 = std::stoull(mInternalString.substr(16, 16), nullptr, base);
|
||||
|
||||
if (IOUtil::SystemEndianness == IOUtil::LittleEndian)
|
||||
{
|
||||
IOUtil::SwapBytes(part1);
|
||||
IOUtil::SwapBytes(part2);
|
||||
}
|
||||
|
||||
memcpy(pOut, &part1, 8);
|
||||
memcpy(pOut + 8, &part2, 8);
|
||||
}
|
||||
|
||||
inline _TStdString ToStdString() const
|
||||
{
|
||||
return mInternalString;
|
||||
}
|
||||
|
||||
_TStringList Split(const CharType* pkTokens) const
|
||||
{
|
||||
_TStringList out;
|
||||
u32 lastSplit = 0;
|
||||
|
||||
// Iterate over all characters in the input string
|
||||
for (u32 iChr = 0; iChr < Length(); iChr++)
|
||||
{
|
||||
// Check whether this character is one of the user-provided tokens
|
||||
for (u32 iTok = 0; true; iTok++)
|
||||
{
|
||||
if (!pkTokens[iTok]) break;
|
||||
|
||||
if (mInternalString[iChr] == pkTokens[iTok])
|
||||
{
|
||||
// Token found - split string
|
||||
if (iChr > lastSplit)
|
||||
out.push_back(SubString(lastSplit, iChr - lastSplit));
|
||||
|
||||
lastSplit = iChr + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add final string
|
||||
if (lastSplit != Length())
|
||||
out.push_back(SubString(lastSplit, Length() - lastSplit));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void EnsureEndsWith(CharType chr)
|
||||
{
|
||||
if (Back() != chr)
|
||||
Append(chr);
|
||||
}
|
||||
|
||||
void EnsureEndsWith(const CharType* pkText)
|
||||
{
|
||||
if (!EndsWith(pkText))
|
||||
Append(pkText);
|
||||
}
|
||||
|
||||
// Check String
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (Size() == 0);
|
||||
}
|
||||
|
||||
bool StartsWith(const _TString& str) const
|
||||
{
|
||||
if (Size() < str.Size())
|
||||
return false;
|
||||
|
||||
return (SubString(0, str.Size()) == str);
|
||||
}
|
||||
|
||||
bool EndsWith(const _TString& str) const
|
||||
{
|
||||
if (Size() < str.Size())
|
||||
return false;
|
||||
|
||||
return (SubString(Size() - str.Size(), str.Size()) == str);
|
||||
}
|
||||
|
||||
bool Contains(_TString str, bool caseSensitive = true) const
|
||||
{
|
||||
if (Size() < str.Size()) return false;
|
||||
|
||||
_TString checkStr(caseSensitive ? *this : ToUpper());
|
||||
if (!caseSensitive) str = str.ToUpper();
|
||||
|
||||
int latestPossibleStart = Size() - str.Size();
|
||||
int match = 0;
|
||||
|
||||
for (int iChr = 0; iChr < latestPossibleStart; iChr++)
|
||||
{
|
||||
// If the current character matches, increment match
|
||||
if (checkStr.At(iChr) == str.At(match))
|
||||
match++;
|
||||
|
||||
// Otherwise...
|
||||
else
|
||||
{
|
||||
// We need to also compare this character to the first
|
||||
// character of the string (unless we just did that)
|
||||
if (match > 0)
|
||||
iChr--;
|
||||
|
||||
match = 0;
|
||||
}
|
||||
|
||||
// If we've matched the entire string, then we can return true
|
||||
if (match == str.Size()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsHexString(bool requirePrefix = false, u32 width = -1) const
|
||||
{
|
||||
_TString str(*this);
|
||||
bool hasPrefix = str.StartsWith("0x");
|
||||
|
||||
// If we're required to match the prefix and prefix is missing, return false
|
||||
if (requirePrefix && !hasPrefix)
|
||||
return false;
|
||||
|
||||
if (width == -1)
|
||||
{
|
||||
// If the string has the 0x prefix, remove it
|
||||
if (hasPrefix)
|
||||
str = str.ChopFront(2);
|
||||
|
||||
// If we have a variable width then assign the width value to the string size
|
||||
width = str.Size();
|
||||
}
|
||||
|
||||
// If the string starts with the prefix and the length matches the string, remove the prefix
|
||||
else if ((str.Size() == width + 2) && (hasPrefix))
|
||||
str = str.ChopFront(2);
|
||||
|
||||
// By this point, the string size and the width should match. If they don't, return false.
|
||||
if (str.Size() != width) return false;
|
||||
|
||||
// Now we can finally check the actual string and make sure all the characters are valid hex characters.
|
||||
for (u32 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;
|
||||
}
|
||||
|
||||
inline bool CaseInsensitiveCompare(const _TString& rkOther) const
|
||||
{
|
||||
return (ToUpper() == rkOther.ToUpper());
|
||||
}
|
||||
|
||||
// Get Filename Components
|
||||
_TString GetFileDirectory() const
|
||||
{
|
||||
size_t endPath = mInternalString.find_last_of("\\/");
|
||||
return SubString(0, endPath + 1);
|
||||
}
|
||||
|
||||
_TString GetFileName(bool withExtension = true) const
|
||||
{
|
||||
size_t endPath = mInternalString.find_last_of("\\/") + 1;
|
||||
|
||||
if (withExtension)
|
||||
{
|
||||
return SubString(endPath, Size() - endPath);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
size_t endName = mInternalString.find_last_of(".");
|
||||
return SubString(endPath, endName - endPath);
|
||||
}
|
||||
}
|
||||
|
||||
_TString GetFileExtension() const
|
||||
{
|
||||
size_t endName = mInternalString.find_last_of(".");
|
||||
return SubString(endName + 1, Size() - endName);
|
||||
}
|
||||
|
||||
_TString GetFilePathWithoutExtension() const
|
||||
{
|
||||
size_t endName = mInternalString.find_last_of(".");
|
||||
return SubString(0, endName);
|
||||
}
|
||||
|
||||
// Operators
|
||||
inline _TString& operator=(const CharType* pkText)
|
||||
{
|
||||
mInternalString = pkText;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline _TString& operator=(const _TString& rkText)
|
||||
{
|
||||
mInternalString = rkText.mInternalString;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CharType& operator[](int pos)
|
||||
{
|
||||
return mInternalString[pos];
|
||||
}
|
||||
|
||||
inline const CharType& operator[](int pos) const
|
||||
{
|
||||
return mInternalString[pos];
|
||||
}
|
||||
|
||||
inline const CharType* operator*() const
|
||||
{
|
||||
return CString();
|
||||
}
|
||||
|
||||
_TString operator+(const CharType* pkOther) const
|
||||
{
|
||||
u32 len = CStringLength(pkOther);
|
||||
|
||||
_TString out(len + Size());
|
||||
memcpy(&out[0], mInternalString.data(), Size() * sizeof(CharType));
|
||||
memcpy(&out[Size()], pkOther, len * sizeof(CharType));
|
||||
return out;
|
||||
}
|
||||
|
||||
inline _TString operator+(const _TString& other) const
|
||||
{
|
||||
return (*this + other.CString());
|
||||
}
|
||||
|
||||
inline void operator+=(const CharType* pkOther)
|
||||
{
|
||||
*this = *this + pkOther;
|
||||
}
|
||||
|
||||
inline void operator+=(const _TString& rkOther)
|
||||
{
|
||||
*this = *this + rkOther;
|
||||
}
|
||||
|
||||
inline friend _TString operator+(const CharType* pkLeft, const _TString& rkRight)
|
||||
{
|
||||
u32 len = CStringLength(pkLeft);
|
||||
|
||||
_TString out(len + rkRight.Size());
|
||||
memcpy(&out[0], pkLeft, len * sizeof(CharType));
|
||||
memcpy(&out[len], rkRight.CString(), rkRight.Size() * sizeof(CharType));
|
||||
return out;
|
||||
}
|
||||
|
||||
inline friend _TString operator+(const _TStdString& rkLeft, const _TString& rkRight)
|
||||
{
|
||||
_TString out(rkLeft.size() + rkRight.Size());
|
||||
memcpy(&out[0], rkLeft.data(), rkLeft.size() * sizeof(CharType));
|
||||
memcpy(&out[rkLeft.size()], rkRight.Data(), rkRight.Size() * sizeof(CharType));
|
||||
return out;
|
||||
}
|
||||
|
||||
inline bool operator==(const CharType *pkText) const
|
||||
{
|
||||
return CompareCStrings(pkText, CString());
|
||||
}
|
||||
|
||||
inline bool operator==(const _TString& rkOther) const
|
||||
{
|
||||
return (mInternalString == rkOther.mInternalString);
|
||||
}
|
||||
|
||||
inline friend bool operator==(const CharType *pkText, const _TString& rkString)
|
||||
{
|
||||
return (rkString == pkText);
|
||||
}
|
||||
|
||||
inline friend bool operator==(const _TStdString& rkStringA, const _TString& rkStringB)
|
||||
{
|
||||
return (rkStringB == rkStringA);
|
||||
}
|
||||
|
||||
inline bool operator!=(const CharType *pkText) const
|
||||
{
|
||||
return (!(*this == pkText));
|
||||
}
|
||||
|
||||
inline bool operator!=(const _TString& rkOther) const
|
||||
{
|
||||
return (!(*this == rkOther));
|
||||
}
|
||||
|
||||
inline friend bool operator!=(const CharType *pkText, const _TString& rkString)
|
||||
{
|
||||
return (rkString != pkText);
|
||||
}
|
||||
|
||||
inline friend bool operator!=(const _TStdString& rkStringA, const _TString& rkStringB)
|
||||
{
|
||||
return (rkStringB != rkStringA);
|
||||
}
|
||||
|
||||
inline bool operator<(const CharType* pkText) const
|
||||
{
|
||||
return (mInternalString < pkText);
|
||||
}
|
||||
|
||||
inline bool operator<(const _TString& rkOther) const
|
||||
{
|
||||
return (mInternalString < rkOther.mInternalString);
|
||||
}
|
||||
|
||||
inline friend bool operator<(const CharType* pkText, const _TString& rkString)
|
||||
{
|
||||
return (rkString > pkText);
|
||||
}
|
||||
|
||||
inline friend bool operator<(const _TStdString& rkStringA, const _TString& rkStringB)
|
||||
{
|
||||
return (rkStringB > rkStringA);
|
||||
}
|
||||
|
||||
inline bool operator<=(const CharType* pkText) const
|
||||
{
|
||||
return (mInternalString <= pkText);
|
||||
}
|
||||
|
||||
inline bool operator<=(const _TString& rkOther) const
|
||||
{
|
||||
return (mInternalString <= rkOther.mInternalString);
|
||||
}
|
||||
|
||||
inline friend bool operator<=(const CharType* pkText, const _TString& rkString)
|
||||
{
|
||||
return (rkString >= pkText);
|
||||
}
|
||||
|
||||
inline friend bool operator<=(const _TStdString& rkStringA, const _TString& rkStringB)
|
||||
{
|
||||
return (rkStringB >= rkStringA);
|
||||
}
|
||||
|
||||
inline bool operator>(const CharType* pkText) const
|
||||
{
|
||||
return (mInternalString > pkText);
|
||||
}
|
||||
|
||||
inline bool operator>(const _TString& rkOther) const
|
||||
{
|
||||
return (mInternalString > rkOther.mInternalString);
|
||||
}
|
||||
|
||||
inline friend bool operator>(const CharType* pkText, const _TString& rkString)
|
||||
{
|
||||
return (rkString < pkText);
|
||||
}
|
||||
|
||||
inline friend bool operator>(const _TStdString& rkStringA, const _TString& rkStringB)
|
||||
{
|
||||
return (rkStringB < rkStringA);
|
||||
}
|
||||
|
||||
inline bool operator>=(const CharType* pkText) const
|
||||
{
|
||||
return (mInternalString >= pkText);
|
||||
}
|
||||
|
||||
inline bool operator>=(const _TString& rkOther) const
|
||||
{
|
||||
return (mInternalString >= rkOther.mInternalString);
|
||||
}
|
||||
|
||||
inline friend bool operator>=(const CharType* pkText, const _TString& rkString)
|
||||
{
|
||||
return (rkString <= pkText);
|
||||
}
|
||||
|
||||
inline friend bool operator>=(const _TStdString& rkStringA, const _TString& rkStringB)
|
||||
{
|
||||
return (rkStringB <= rkStringA);
|
||||
}
|
||||
|
||||
inline friend std::ostream& operator<<(std::ostream& rStream, const _TString& rkString)
|
||||
{
|
||||
rStream << rkString.mInternalString;
|
||||
return rStream;
|
||||
}
|
||||
|
||||
inline friend std::istream& operator>>(std::istream& rStream, const _TString& rkString)
|
||||
{
|
||||
rStream >> rkString.mInternalString;
|
||||
return rStream;
|
||||
}
|
||||
|
||||
// Static
|
||||
static TBasicString<CharType> FromInt32(u32 value, int width = 0, int base = 16)
|
||||
{
|
||||
std::basic_stringstream<CharType> sstream;
|
||||
sstream << std::setbase(base) << std::setw(width) << std::setfill('0') << value;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
static TBasicString<CharType> FromInt64(u64 value, int width = 0, int base = 16)
|
||||
{
|
||||
std::basic_stringstream<CharType> sstream;
|
||||
sstream << std::setbase(base) << std::setw(width) << std::setfill('0') << value;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
static TBasicString<CharType> HexString(unsigned char num, bool addPrefix = true, bool uppercase = false, int width = 0)
|
||||
{
|
||||
return HexString((unsigned long) num, addPrefix, uppercase, width);
|
||||
}
|
||||
|
||||
static TBasicString<CharType> HexString(unsigned short num, bool addPrefix = true, bool uppercase = false, int width = 0)
|
||||
{
|
||||
return HexString((unsigned long) num, addPrefix, uppercase, width);
|
||||
}
|
||||
|
||||
static TBasicString<CharType> HexString(unsigned long num, bool addPrefix = true, bool uppercase = false, int width = 0)
|
||||
{
|
||||
std::basic_stringstream<CharType> sstream;
|
||||
sstream << std::hex << std::setw(width) << std::setfill('0') << num;
|
||||
|
||||
_TString str = sstream.str();
|
||||
if (uppercase) str = str.ToUpper();
|
||||
if (addPrefix) str.Prepend("0x");
|
||||
return str;
|
||||
}
|
||||
|
||||
static bool CompareCStrings(const CharType* pkA, const CharType* pkB)
|
||||
{
|
||||
// Replacement for strcmp so we can compare any CharType
|
||||
while (true)
|
||||
{
|
||||
if (*pkA != *pkB) return false;
|
||||
if ((*pkA == 0) || (*pkB == 0)) return true;
|
||||
pkA++;
|
||||
pkB++;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 CStringLength(const CharType* pkStr)
|
||||
{
|
||||
// Replacement for strlen so we can measure any CharType
|
||||
u32 out = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (*pkStr == 0) return out;
|
||||
out++;
|
||||
pkStr++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsWhitespace(CharType c)
|
||||
{
|
||||
return ( (c == '\t') ||
|
||||
(c == '\n') ||
|
||||
(c == '\v') ||
|
||||
(c == '\f') ||
|
||||
(c == '\r') ||
|
||||
(c == ' ') );
|
||||
}
|
||||
};
|
||||
|
||||
// ************ TString ************
|
||||
class TString : public TBasicString<char>
|
||||
{
|
||||
public:
|
||||
TString() : TBasicString<char>() {}
|
||||
TString(size_t size) : TBasicString<char>(size) {}
|
||||
TString(size_t size, char fill) : TBasicString<char>(size, fill) {}
|
||||
TString(const char* pkText) : TBasicString<char>(pkText) {}
|
||||
TString(const char* pkText, u32 length) : TBasicString<char>(pkText, length) {}
|
||||
TString(const std::string& rkText) : TBasicString<char>(rkText) {}
|
||||
TString(const TBasicString<char>& rkStr) : TBasicString<char>(rkStr) {}
|
||||
TString(const wchar_t* pkText);
|
||||
TString(const std::wstring& rkText);
|
||||
TString(const class TWideString& rkText);
|
||||
|
||||
class TWideString ToUTF16() const;
|
||||
};
|
||||
|
||||
// ************ TWideString ************
|
||||
class TWideString : public TBasicString<wchar_t>
|
||||
{
|
||||
public:
|
||||
TWideString() : TBasicString<wchar_t>() {}
|
||||
TWideString(u32 size) : TBasicString<wchar_t>(size) {}
|
||||
TWideString(u32 size, wchar_t fill) : TBasicString<wchar_t>(size, fill) {}
|
||||
TWideString(const wchar_t* pkText) : TBasicString<wchar_t>(pkText) {}
|
||||
TWideString(const wchar_t* pkText, u32 length) : TBasicString<wchar_t>(pkText, length) {}
|
||||
TWideString(const std::wstring& rkText) : TBasicString<wchar_t>(rkText) {}
|
||||
TWideString(const TBasicString<wchar_t>& rkStr) : TBasicString<wchar_t>(rkStr) {}
|
||||
TWideString(const char* pkText);
|
||||
TWideString(const std::string& rkText);
|
||||
TWideString(const TString& rkText);
|
||||
|
||||
class TString ToUTF8() const;
|
||||
};
|
||||
|
||||
// ************ Typedefs ************
|
||||
typedef std::list<TBasicString<char>> TStringList;
|
||||
typedef std::list<TBasicString<wchar_t>> TWideStringList;
|
||||
|
||||
#endif // TSTRING_H
|
||||
15
src/Common/types.h
Normal file
15
src/Common/types.h
Normal 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
|
||||
54
src/Core/CAreaAttributes.cpp
Normal file
54
src/Core/CAreaAttributes.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#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:
|
||||
case eCorruption:
|
||||
return static_cast<CBoolProperty*>(pBaseStruct->PropertyByIndex(1))->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().RawPointer();
|
||||
case eCorruption:
|
||||
return (CModel*) static_cast<CFileProperty*>(pBaseStruct->PropertyByIndex(8))->Get().RawPointer();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
20
src/Core/CAreaAttributes.h
Normal file
20
src/Core/CAreaAttributes.h
Normal 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
|
||||
25
src/Core/CLightParameters.cpp
Normal file
25
src/Core/CLightParameters.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "CLightParameters.h"
|
||||
|
||||
CLightParameters::CLightParameters(CPropertyStruct *pStruct, EGame game)
|
||||
: mpStruct(pStruct), mGame(game)
|
||||
{
|
||||
}
|
||||
|
||||
CLightParameters::~CLightParameters()
|
||||
{
|
||||
}
|
||||
|
||||
int CLightParameters::LightLayerIndex()
|
||||
{
|
||||
if (!mpStruct) return 0;
|
||||
|
||||
CLongProperty *pParam;
|
||||
|
||||
if (mGame <= ePrime)
|
||||
pParam = (CLongProperty*) mpStruct->PropertyByIndex(0xD);
|
||||
else
|
||||
pParam = (CLongProperty*) mpStruct->PropertyByID(0x1F715FD3);
|
||||
|
||||
if (!pParam) return 0;
|
||||
else return pParam->Get();
|
||||
}
|
||||
18
src/Core/CLightParameters.h
Normal file
18
src/Core/CLightParameters.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CLIGHTPARAMETERS_H
|
||||
#define CLIGHTPARAMETERS_H
|
||||
|
||||
#include <Resource/CGameArea.h>
|
||||
#include <Resource/script/CProperty.h>
|
||||
|
||||
class CLightParameters
|
||||
{
|
||||
CPropertyStruct *mpStruct;
|
||||
EGame mGame;
|
||||
|
||||
public:
|
||||
CLightParameters(CPropertyStruct *pStruct, EGame game);
|
||||
~CLightParameters();
|
||||
int LightLayerIndex();
|
||||
};
|
||||
|
||||
#endif // CLIGHTPARAMETERS_H
|
||||
68
src/Core/CRayCollisionTester.cpp
Normal file
68
src/Core/CRayCollisionTester.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "CRayCollisionTester.h"
|
||||
#include <Scene/CSceneNode.h>
|
||||
|
||||
CRayCollisionTester::CRayCollisionTester(const CRay& Ray)
|
||||
: mRay(Ray)
|
||||
{
|
||||
}
|
||||
|
||||
CRayCollisionTester::~CRayCollisionTester()
|
||||
{
|
||||
}
|
||||
|
||||
void CRayCollisionTester::AddNode(CSceneNode *pNode, u32 ComponentIndex, float Distance)
|
||||
{
|
||||
mBoxIntersectList.emplace_back(SRayIntersection());
|
||||
SRayIntersection& Intersection = mBoxIntersectList.back();
|
||||
Intersection.pNode = pNode;
|
||||
Intersection.ComponentIndex = ComponentIndex;
|
||||
Intersection.Distance = Distance;
|
||||
}
|
||||
|
||||
void CRayCollisionTester::AddNodeModel(CSceneNode *pNode, CBasicModel *pModel)
|
||||
{
|
||||
// Check each of the model's surfaces and queue them for further testing if they hit
|
||||
for (u32 iSurf = 0; iSurf < pModel->GetSurfaceCount(); iSurf++)
|
||||
{
|
||||
std::pair<bool,float> SurfResult = pModel->GetSurfaceAABox(iSurf).Transformed(pNode->Transform()).IntersectsRay(mRay);
|
||||
|
||||
if (SurfResult.first)
|
||||
AddNode(pNode, iSurf, SurfResult.second);
|
||||
}
|
||||
}
|
||||
|
||||
SRayIntersection CRayCollisionTester::TestNodes(const SViewInfo& ViewInfo)
|
||||
{
|
||||
// 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.ComponentIndex, ViewInfo);
|
||||
|
||||
if (MidResult.Hit)
|
||||
{
|
||||
if ((!Result.Hit) || (MidResult.Distance < Result.Distance))
|
||||
Result = MidResult;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
35
src/Core/CRayCollisionTester.h
Normal file
35
src/Core/CRayCollisionTester.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef CRAYCOLLISIONHELPER_H
|
||||
#define CRAYCOLLISIONHELPER_H
|
||||
|
||||
#include "CAABox.h"
|
||||
#include "CRay.h"
|
||||
#include "CVector3f.h"
|
||||
#include "SRayIntersection.h"
|
||||
#include "types.h"
|
||||
#include <Core/SViewInfo.h>
|
||||
#include <Resource/model/CBasicModel.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);
|
||||
void AddNodeModel(CSceneNode *pNode, CBasicModel *pModel);
|
||||
SRayIntersection TestNodes(const SViewInfo& ViewInfo);
|
||||
};
|
||||
|
||||
inline const CRay& CRayCollisionTester::Ray() const
|
||||
{
|
||||
return mRay;
|
||||
}
|
||||
|
||||
#endif // CRAYCOLLISIONHELPER_H
|
||||
245
src/Core/Core.pro
Normal file
245
src/Core/Core.pro
Normal file
@@ -0,0 +1,245 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2015-12-13T15:31:43
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT -= core gui
|
||||
|
||||
CONFIG += staticlib
|
||||
TEMPLATE = lib
|
||||
DESTDIR = $$PWD/../../build/Core
|
||||
DEFINES += GLEW_STATIC
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
CONFIG (debug, debug|release) {
|
||||
# Debug Config
|
||||
OBJECTS_DIR = $$PWD/../../build/Core/debug
|
||||
TARGET = Cored
|
||||
|
||||
# Debug Libs
|
||||
LIBS += -L$$PWD/../../build/Common/ -lCommond \
|
||||
-L$$PWD/../../externals/assimp/lib/ -lassimp-vc120-mtd \
|
||||
-L$$PWD/../../externals/boost_1_56_0/lib32-msvc-12.0 -llibboost_filesystem-vc120-mt-gd-1_56 \
|
||||
-L$$PWD/../../externals/FileIO/lib/ -lFileIOd \
|
||||
-L$$PWD/../../externals/tinyxml2/lib/ -ltinyxml2d
|
||||
|
||||
}
|
||||
|
||||
CONFIG (release, debug|release) {
|
||||
# Release Config
|
||||
OBJECTS_DIR = $$PWD/../../build/Core/release
|
||||
TARGET = Core
|
||||
|
||||
# Release Libs
|
||||
LIBS += -L$$PWD/../../build/Common/ -lCommon \
|
||||
-L$$PWD/../../externals/assimp/lib/ -lassimp-vc120-mt \
|
||||
-L$$PWD/../../externals/boost_1_56_0/lib32-msvc-12.0 -llibboost_filesystem-vc120-mt-1_56 \
|
||||
-L$$PWD/../../externals/FileIO/lib/ -lFileIO \
|
||||
-L$$PWD/../../externals/tinyxml2/lib/ -ltinyxml2
|
||||
}
|
||||
|
||||
# Debug/Release Libs
|
||||
LIBS += -L$$PWD/../../externals/glew-1.9.0/lib/ -lglew32s \
|
||||
-L$$PWD/../../externals/lzo-2.08/lib -llzo-2.08 \
|
||||
-L$$PWD/../../externals/zlib/lib -lzdll
|
||||
|
||||
# Include Paths
|
||||
INCLUDEPATH += $$PWD/../ \
|
||||
$$PWD/../../externals/assimp/include \
|
||||
$$PWD/../../externals/boost_1_56_0 \
|
||||
$$PWD/../../externals/FileIO/include \
|
||||
$$PWD/../../externals/glew-1.9.0/include \
|
||||
$$PWD/../../externals/glm/glm \
|
||||
$$PWD/../../externals/lzo-2.08/include \
|
||||
$$PWD/../../externals/tinyxml2/include \
|
||||
$$PWD/../../externals/zlib/include
|
||||
|
||||
# Source Files
|
||||
HEADERS += \
|
||||
Render/CCamera.h \
|
||||
Render/CDrawUtil.h \
|
||||
Render/CGraphics.h \
|
||||
Render/CRenderBucket.h \
|
||||
Render/CRenderer.h \
|
||||
Render/ERenderCommand.h \
|
||||
Render/ERenderOptions.h \
|
||||
Render/IRenderable.h \
|
||||
Render/SRenderablePtr.h \
|
||||
Render/SViewInfo.h \
|
||||
Resource/Cooker/CMaterialCooker.h \
|
||||
Resource/Cooker/CModelCooker.h \
|
||||
Resource/Cooker/CSectionMgrOut.h \
|
||||
Resource/Cooker/CTemplateWriter.h \
|
||||
Resource/Cooker/CTextureEncoder.h \
|
||||
Resource/Cooker/CWorldCooker.h \
|
||||
Resource/Factory/CAnimSetLoader.h \
|
||||
Resource/Factory/CAreaLoader.h \
|
||||
Resource/Factory/CBlockMgrIn.h \
|
||||
Resource/Factory/CCollisionLoader.h \
|
||||
Resource/Factory/CFontLoader.h \
|
||||
Resource/Factory/CMaterialLoader.h \
|
||||
Resource/Factory/CModelLoader.h \
|
||||
Resource/Factory/CScanLoader.h \
|
||||
Resource/Factory/CScriptLoader.h \
|
||||
Resource/Factory/CStringLoader.h \
|
||||
Resource/Factory/CTemplateLoader.h \
|
||||
Resource/Factory/CTextureDecoder.h \
|
||||
Resource/Factory/CWorldLoader.h \
|
||||
Resource/Model/CBasicModel.h \
|
||||
Resource/Model/CModel.h \
|
||||
Resource/Model/CStaticModel.h \
|
||||
Resource/Model/CVertex.h \
|
||||
Resource/Model/EVertexDescription.h \
|
||||
Resource/Model/SSurface.h \
|
||||
Resource/Script/CMasterTemplate.h \
|
||||
Resource/Script/CProperty.h \
|
||||
Resource/Script/CPropertyTemplate.h \
|
||||
Resource/Script/CScriptLayer.h \
|
||||
Resource/Script/CScriptObject.h \
|
||||
Resource/Script/CScriptTemplate.h \
|
||||
Resource/Script/EObjectType.h \
|
||||
Resource/Script/EPropertyType.h \
|
||||
Resource/Script/EVolumeShape.h \
|
||||
Resource/Script/SConnection.h \
|
||||
Resource/CAnimationParameters.h \
|
||||
Resource/CAnimSet.h \
|
||||
Resource/CCollisionMesh.h \
|
||||
Resource/CCollisionMeshGroup.h \
|
||||
Resource/CFont.h \
|
||||
Resource/CGameArea.h \
|
||||
Resource/CLight.h \
|
||||
Resource/CMaterial.h \
|
||||
Resource/CMaterialPass.h \
|
||||
Resource/CMaterialSet.h \
|
||||
Resource/CPakFile.h \
|
||||
Resource/CResCache.h \
|
||||
Resource/CResource.h \
|
||||
Resource/CScan.h \
|
||||
Resource/CStringTable.h \
|
||||
Resource/CTexture.h \
|
||||
Resource/CWorld.h \
|
||||
Resource/EFormatVersion.h \
|
||||
Resource/EResType.h \
|
||||
Resource/ETevEnums.h \
|
||||
Resource/ETexelFormat.h \
|
||||
Resource/SDependency.h \
|
||||
Resource/SNamedResource.h \
|
||||
Resource/SResInfo.h \
|
||||
Resource/TResPtr.h \
|
||||
Scene/CCollisionNode.h \
|
||||
Scene/CLightNode.h \
|
||||
Scene/CModelNode.h \
|
||||
Scene/CRootNode.h \
|
||||
Scene/CSceneManager.h \
|
||||
Scene/CSceneNode.h \
|
||||
Scene/CScriptNode.h \
|
||||
Scene/CStaticNode.h \
|
||||
Scene/ENodeType.h \
|
||||
ScriptExtra/CDamageableTriggerExtra.h \
|
||||
ScriptExtra/CDoorExtra.h \
|
||||
ScriptExtra/CPointOfInterestExtra.h \
|
||||
ScriptExtra/CScriptExtra.h \
|
||||
ScriptExtra/CSpacePirateExtra.h \
|
||||
ScriptExtra/CWaypointExtra.h \
|
||||
CAreaAttributes.h \
|
||||
CLightParameters.h \
|
||||
CRayCollisionTester.h \
|
||||
Log.h \
|
||||
SRayIntersection.h \
|
||||
OpenGL/CDynamicVertexBuffer.h \
|
||||
OpenGL/CFramebuffer.h \
|
||||
OpenGL/CGL.h \
|
||||
OpenGL/CIndexBuffer.h \
|
||||
OpenGL/CRenderbuffer.h \
|
||||
OpenGL/CShader.h \
|
||||
OpenGL/CShaderGenerator.h \
|
||||
OpenGL/CUniformBuffer.h \
|
||||
OpenGL/CVertexArrayManager.h \
|
||||
OpenGL/CVertexBuffer.h \
|
||||
OpenGL/GLCommon.h
|
||||
|
||||
SOURCES += \
|
||||
Render/CCamera.cpp \
|
||||
Render/CDrawUtil.cpp \
|
||||
Render/CGraphics.cpp \
|
||||
Render/CRenderBucket.cpp \
|
||||
Render/CRenderer.cpp \
|
||||
Resource/Cooker/CMaterialCooker.cpp \
|
||||
Resource/Cooker/CModelCooker.cpp \
|
||||
Resource/Cooker/CSectionMgrOut.cpp \
|
||||
Resource/Cooker/CTemplateWriter.cpp \
|
||||
Resource/Cooker/CTextureEncoder.cpp \
|
||||
Resource/Cooker/CWorldCooker.cpp \
|
||||
Resource/Factory/CAnimSetLoader.cpp \
|
||||
Resource/Factory/CAreaLoader.cpp \
|
||||
Resource/Factory/CBlockMgr.cpp \
|
||||
Resource/Factory/CCollisionLoader.cpp \
|
||||
Resource/Factory/CFontLoader.cpp \
|
||||
Resource/Factory/CMaterialLoader.cpp \
|
||||
Resource/Factory/CModelLoader.cpp \
|
||||
Resource/Factory/CScanLoader.cpp \
|
||||
Resource/Factory/CScriptLoader.cpp \
|
||||
Resource/Factory/CStringLoader.cpp \
|
||||
Resource/Factory/CTemplateLoader.cpp \
|
||||
Resource/Factory/CTextureDecoder.cpp \
|
||||
Resource/Factory/CWorldLoader.cpp \
|
||||
Resource/Model/CBasicModel.cpp \
|
||||
Resource/Model/CModel.cpp \
|
||||
Resource/Model/CStaticModel.cpp \
|
||||
Resource/Model/SSurface.cpp \
|
||||
Resource/Script/CMasterTemplate.cpp \
|
||||
Resource/Script/CProperty.cpp \
|
||||
Resource/Script/CPropertyTemplate.cpp \
|
||||
Resource/Script/CScriptLayer.cpp \
|
||||
Resource/Script/CScriptObject.cpp \
|
||||
Resource/Script/CScriptTemplate.cpp \
|
||||
Resource/CAnimationParameters.cpp \
|
||||
Resource/CAnimSet.cpp \
|
||||
Resource/CCollisionMesh.cpp \
|
||||
Resource/CCollisionMeshGroup.cpp \
|
||||
Resource/CFont.cpp \
|
||||
Resource/CGameArea.cpp \
|
||||
Resource/CLight.cpp \
|
||||
Resource/CMaterial.cpp \
|
||||
Resource/CMaterialPass.cpp \
|
||||
Resource/CMaterialSet.cpp \
|
||||
Resource/CPakFile.cpp \
|
||||
Resource/CResCache.cpp \
|
||||
Resource/CResource.cpp \
|
||||
Resource/CScan.cpp \
|
||||
Resource/CStringTable.cpp \
|
||||
Resource/CTexture.cpp \
|
||||
Resource/CWorld.cpp \
|
||||
Scene/CCollisionNode.cpp \
|
||||
Scene/CLightNode.cpp \
|
||||
Scene/CModelNode.cpp \
|
||||
Scene/CSceneManager.cpp \
|
||||
Scene/CSceneNode.cpp \
|
||||
Scene/CScriptNode.cpp \
|
||||
Scene/CStaticNode.cpp \
|
||||
ScriptExtra/CDamageableTriggerExtra.cpp \
|
||||
ScriptExtra/CDoorExtra.cpp \
|
||||
ScriptExtra/CPointOfInterestExtra.cpp \
|
||||
ScriptExtra/CScriptExtra.cpp \
|
||||
ScriptExtra/CSpacePirateExtra.cpp \
|
||||
ScriptExtra/CWaypointExtra.cpp \
|
||||
CAreaAttributes.cpp \
|
||||
CLightParameters.cpp \
|
||||
CRayCollisionTester.cpp \
|
||||
Log.cpp \
|
||||
OpenGL/CDynamicVertexBuffer.cpp \
|
||||
OpenGL/CFramebuffer.cpp \
|
||||
OpenGL/CGL.cpp \
|
||||
OpenGL/CIndexBuffer.cpp \
|
||||
OpenGL/CRenderbuffer.cpp \
|
||||
OpenGL/CShader.cpp \
|
||||
OpenGL/CShaderGenerator.cpp \
|
||||
OpenGL/CUniformBuffer.cpp \
|
||||
OpenGL/CVertexArrayManager.cpp \
|
||||
OpenGL/CVertexBuffer.cpp \
|
||||
OpenGL/GLCommon.cpp
|
||||
76
src/Core/Log.cpp
Normal file
76
src/Core/Log.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <Common/TString.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace Log
|
||||
{
|
||||
|
||||
static const TString gskLogFilename = "primeworldeditor.log";
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996) // Can't use fopen_s here without creating a separate init function for the log
|
||||
FILE *gpLogFile = fopen(*gskLogFilename, "w");
|
||||
#pragma warning(pop)
|
||||
|
||||
void Write(const TString& message)
|
||||
{
|
||||
if (gpLogFile)
|
||||
{
|
||||
time_t RawTime;
|
||||
time(&RawTime);
|
||||
|
||||
tm pTimeInfo;
|
||||
localtime_s(&pTimeInfo, &RawTime);
|
||||
|
||||
char Buffer[80];
|
||||
strftime(Buffer, 80, "[%H:%M:%S]", &pTimeInfo);
|
||||
|
||||
fprintf(gpLogFile, "%s %s\n", Buffer, *message);
|
||||
fflush(gpLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Error(const TString& message)
|
||||
{
|
||||
Write("ERROR: " + message);
|
||||
std::cout << "ERROR: " << message << "\n";
|
||||
}
|
||||
|
||||
void Warning(const TString& message)
|
||||
{
|
||||
Write("Warning: " + message);
|
||||
std::cout << "Warning: " << message << "\n";
|
||||
}
|
||||
|
||||
void FileWrite(const TString& filename, const TString& message)
|
||||
{
|
||||
Write(filename + " : " + message);
|
||||
}
|
||||
|
||||
void FileWrite(const TString& filename, unsigned long offset, const TString& message)
|
||||
{
|
||||
Write(filename + " : " + TString::HexString(offset) + " - " + message);
|
||||
}
|
||||
|
||||
void FileError(const TString& filename, const TString& message)
|
||||
{
|
||||
Error(filename + " : " + message);
|
||||
}
|
||||
|
||||
void FileError(const TString& filename, unsigned long offset, const TString& message)
|
||||
{
|
||||
Error(filename + " : " + TString::HexString(offset) + " - " + message);
|
||||
}
|
||||
|
||||
void FileWarning(const TString& filename, const TString& message)
|
||||
{
|
||||
Warning(filename + " : " + message);
|
||||
}
|
||||
|
||||
void FileWarning(const TString& filename, unsigned long offset, const TString& message)
|
||||
{
|
||||
Warning(filename + " : " + TString::HexString(offset) + " - " + message);
|
||||
}
|
||||
|
||||
}
|
||||
22
src/Core/Log.h
Normal file
22
src/Core/Log.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef INFO
|
||||
#define INFO
|
||||
|
||||
#include <Common/TString.h>
|
||||
|
||||
namespace Log
|
||||
{
|
||||
|
||||
void Write(const TString& message);
|
||||
void Error(const TString& message);
|
||||
void Warning(const TString& message);
|
||||
void FileWrite(const TString& filename, const TString& message);
|
||||
void FileWrite(const TString& filename, unsigned long offset, const TString& message);
|
||||
void FileError(const TString& filename, const TString& message);
|
||||
void FileError(const TString& filename, unsigned long offset, const TString& message);
|
||||
void FileWarning(const TString& filename, const TString& message);
|
||||
void FileWarning(const TString& filename, unsigned long offset, const TString& message);
|
||||
|
||||
}
|
||||
|
||||
#endif // INFO
|
||||
|
||||
136
src/Core/OpenGL/CDynamicVertexBuffer.cpp
Normal file
136
src/Core/OpenGL/CDynamicVertexBuffer.cpp
Normal 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++)
|
||||
{
|
||||
int 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;
|
||||
}
|
||||
32
src/Core/OpenGL/CDynamicVertexBuffer.h
Normal file
32
src/Core/OpenGL/CDynamicVertexBuffer.h
Normal 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
src/Core/OpenGL/CFramebuffer.cpp
Normal file
111
src/Core/OpenGL/CFramebuffer.cpp
Normal 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
src/Core/OpenGL/CFramebuffer.h
Normal file
32
src/Core/OpenGL/CFramebuffer.h
Normal 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
src/Core/OpenGL/CGL.cpp
Normal file
41
src/Core/OpenGL/CGL.cpp
Normal 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;
|
||||
26
src/Core/OpenGL/CGL.h
Normal file
26
src/Core/OpenGL/CGL.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CGL_H
|
||||
#define CGL_H
|
||||
|
||||
#include "GLCommon.h"
|
||||
#include <Common/types.h>
|
||||
#include <GL/glew.h>
|
||||
|
||||
class CGL
|
||||
{
|
||||
public:
|
||||
void SetBlendMode(EBlendFactor Source, EBlendFactor Dest);
|
||||
void SetOpaqueBlend();
|
||||
void SetAlphaBlend();
|
||||
void SetAdditiveBlend();
|
||||
|
||||
private:
|
||||
static void Init();
|
||||
|
||||
static bool mInitialized;
|
||||
static EBlendFactor mBlendSrcFac, mBlendDstFac;
|
||||
static u8 mColorMask;
|
||||
static bool mDepthMask;
|
||||
static bool mStencilMask;
|
||||
};
|
||||
|
||||
#endif // CGL_H
|
||||
156
src/Core/OpenGL/CIndexBuffer.cpp
Normal file
156
src/Core/OpenGL/CIndexBuffer.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "CIndexBuffer.h"
|
||||
|
||||
CIndexBuffer::CIndexBuffer()
|
||||
{
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
CIndexBuffer::CIndexBuffer(GLenum type)
|
||||
{
|
||||
mPrimitiveType = type;
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
CIndexBuffer::~CIndexBuffer()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(1, &mIndexBuffer);
|
||||
}
|
||||
|
||||
void CIndexBuffer::AddIndex(u16 idx)
|
||||
{
|
||||
mIndices.push_back(idx);
|
||||
}
|
||||
|
||||
void CIndexBuffer::AddIndices(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve(count);
|
||||
for (u32 i = 0; i < count; i++)
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
}
|
||||
|
||||
void CIndexBuffer::Reserve(u32 size)
|
||||
{
|
||||
mIndices.reserve(mIndices.size() + size);
|
||||
}
|
||||
|
||||
void CIndexBuffer::Clear()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(1, &mIndexBuffer);
|
||||
|
||||
mBuffered = false;
|
||||
mIndices.clear();
|
||||
}
|
||||
|
||||
void CIndexBuffer::Buffer()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(1, &mIndexBuffer);
|
||||
|
||||
glGenBuffers(1, &mIndexBuffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndices.size() * sizeof(u16), mIndices.data(), GL_STATIC_DRAW);
|
||||
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CIndexBuffer::Bind()
|
||||
{
|
||||
if (!mBuffered) Buffer();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
|
||||
}
|
||||
|
||||
void CIndexBuffer::Unbind()
|
||||
{
|
||||
}
|
||||
|
||||
void CIndexBuffer::DrawElements()
|
||||
{
|
||||
Bind();
|
||||
glDrawElements(mPrimitiveType, mIndices.size(), GL_UNSIGNED_SHORT, (void*) 0);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CIndexBuffer::DrawElements(u32 Offset, u32 Size)
|
||||
{
|
||||
Bind();
|
||||
glDrawElements(mPrimitiveType, Size, GL_UNSIGNED_SHORT, (void*) (Offset * 2));
|
||||
Unbind();
|
||||
}
|
||||
|
||||
bool CIndexBuffer::IsBuffered()
|
||||
{
|
||||
return mBuffered;
|
||||
}
|
||||
|
||||
u32 CIndexBuffer::GetSize()
|
||||
{
|
||||
return mIndices.size();
|
||||
}
|
||||
|
||||
GLenum CIndexBuffer::GetPrimitiveType()
|
||||
{
|
||||
return mPrimitiveType;
|
||||
}
|
||||
|
||||
void CIndexBuffer::SetPrimitiveType(GLenum type)
|
||||
{
|
||||
mPrimitiveType = type;
|
||||
}
|
||||
|
||||
void CIndexBuffer::TrianglesToStrips(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve(count + (count / 3));
|
||||
|
||||
for (u32 i = 0; i < count; i += 3)
|
||||
{
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
void CIndexBuffer::FansToStrips(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve(count);
|
||||
u16 FirstIndex = *indicesPtr;
|
||||
|
||||
for (u32 i = 2; i < count; i += 3)
|
||||
{
|
||||
mIndices.push_back(indicesPtr[i - 1]);
|
||||
mIndices.push_back(indicesPtr[i]);
|
||||
mIndices.push_back(FirstIndex);
|
||||
if (i + 1 < count)
|
||||
mIndices.push_back(indicesPtr[i + 1]);
|
||||
if (i + 2 < count)
|
||||
mIndices.push_back(indicesPtr[i + 2]);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
void CIndexBuffer::QuadsToStrips(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve((u32) (count * 1.25));
|
||||
|
||||
u32 i = 3;
|
||||
for (; i < count; i += 4)
|
||||
{
|
||||
mIndices.push_back(indicesPtr[i - 2]);
|
||||
mIndices.push_back(indicesPtr[i - 1]);
|
||||
mIndices.push_back(indicesPtr[i - 3]);
|
||||
mIndices.push_back(indicesPtr[i]);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
|
||||
// if there's three indices present that indicates a single triangle
|
||||
if (i == count)
|
||||
{
|
||||
mIndices.push_back(indicesPtr[i - 3]);
|
||||
mIndices.push_back(indicesPtr[i - 2]);
|
||||
mIndices.push_back(indicesPtr[i - 1]);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
|
||||
}
|
||||
39
src/Core/OpenGL/CIndexBuffer.h
Normal file
39
src/Core/OpenGL/CIndexBuffer.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef CINDEXBUFFER_H
|
||||
#define CINDEXBUFFER_H
|
||||
|
||||
#include <Common/types.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <gl/glew.h>
|
||||
|
||||
class CIndexBuffer
|
||||
{
|
||||
GLuint mIndexBuffer;
|
||||
std::vector<u16> mIndices;
|
||||
GLenum mPrimitiveType;
|
||||
bool mBuffered;
|
||||
|
||||
public:
|
||||
CIndexBuffer();
|
||||
CIndexBuffer(GLenum type);
|
||||
~CIndexBuffer();
|
||||
void AddIndex(u16 idx);
|
||||
void AddIndices(u16 *indicesPtr, u32 count);
|
||||
void Reserve(u32 size);
|
||||
void Clear();
|
||||
void Buffer();
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void DrawElements();
|
||||
void DrawElements(u32 Offset, u32 Size);
|
||||
bool IsBuffered();
|
||||
|
||||
u32 GetSize();
|
||||
GLenum GetPrimitiveType();
|
||||
void SetPrimitiveType(GLenum type);
|
||||
|
||||
void TrianglesToStrips(u16 *indicesPtr, u32 count);
|
||||
void FansToStrips(u16 *indicesPtr, u32 count);
|
||||
void QuadsToStrips(u16 *indicesPtr, u32 count);
|
||||
};
|
||||
|
||||
#endif // CINDEXBUFFER_H
|
||||
52
src/Core/OpenGL/CRenderbuffer.cpp
Normal file
52
src/Core/OpenGL/CRenderbuffer.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "CRenderbuffer.h"
|
||||
|
||||
CRenderbuffer::CRenderbuffer()
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
|
||||
CRenderbuffer::CRenderbuffer(u32 Width, u32 Height)
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
}
|
||||
|
||||
CRenderbuffer::~CRenderbuffer()
|
||||
{
|
||||
if (mInitialized)
|
||||
glDeleteRenderbuffers(1, &mRenderbuffer);
|
||||
}
|
||||
|
||||
void CRenderbuffer::Init()
|
||||
{
|
||||
glGenRenderbuffers(1, &mRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
void CRenderbuffer::Resize(u32 Width, u32 Height)
|
||||
{
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
|
||||
if (mInitialized)
|
||||
{
|
||||
Bind();
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderbuffer::Bind()
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
|
||||
}
|
||||
|
||||
void CRenderbuffer::Unbind()
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
31
src/Core/OpenGL/CRenderbuffer.h
Normal file
31
src/Core/OpenGL/CRenderbuffer.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef CRENDERBUFFER_H
|
||||
#define CRENDERBUFFER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
class CRenderbuffer
|
||||
{
|
||||
GLuint mRenderbuffer;
|
||||
u32 mWidth, mHeight;
|
||||
bool mInitialized;
|
||||
|
||||
public:
|
||||
CRenderbuffer();
|
||||
CRenderbuffer(u32 Width, u32 Height);
|
||||
~CRenderbuffer();
|
||||
void Init();
|
||||
void Resize(u32 Width, u32 Height);
|
||||
void Bind();
|
||||
void Unbind();
|
||||
|
||||
// Getters
|
||||
GLuint BufferID();
|
||||
};
|
||||
|
||||
inline GLuint CRenderbuffer::BufferID()
|
||||
{
|
||||
return mRenderbuffer;
|
||||
}
|
||||
|
||||
#endif // CRENDERBUFFER_H
|
||||
263
src/Core/OpenGL/CShader.cpp
Normal file
263
src/Core/OpenGL/CShader.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
#include "CShader.h"
|
||||
#include <Common/types.h>
|
||||
#include <Core/CGraphics.h>
|
||||
#include <FileIO/CTextInStream.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
bool gDebugDumpShaders = false;
|
||||
u64 gFailedCompileCount = 0;
|
||||
u64 gSuccessfulCompileCount = 0;
|
||||
|
||||
CShader* CShader::spCurrentShader = nullptr;
|
||||
|
||||
CShader::CShader()
|
||||
{
|
||||
mVertexShaderExists = false;
|
||||
mPixelShaderExists = false;
|
||||
mProgramExists = false;
|
||||
}
|
||||
|
||||
CShader::CShader(const char *kpVertexSource, const char *kpPixelSource)
|
||||
{
|
||||
mVertexShaderExists = false;
|
||||
mPixelShaderExists = false;
|
||||
mProgramExists = false;
|
||||
|
||||
CompileVertexSource(kpVertexSource);
|
||||
CompilePixelSource(kpPixelSource);
|
||||
LinkShaders();
|
||||
}
|
||||
|
||||
CShader::~CShader()
|
||||
{
|
||||
if (mVertexShaderExists) glDeleteShader(mVertexShader);
|
||||
if (mPixelShaderExists) glDeleteShader(mPixelShader);
|
||||
if (mProgramExists) glDeleteProgram(mProgram);
|
||||
|
||||
if (spCurrentShader == this) spCurrentShader = 0;
|
||||
}
|
||||
|
||||
bool CShader::CompileVertexSource(const char* kpSource)
|
||||
{
|
||||
mVertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(mVertexShader, 1, (const GLchar**) &kpSource, NULL);
|
||||
glCompileShader(mVertexShader);
|
||||
|
||||
// Shader should be compiled - check for errors
|
||||
GLint CompileStatus;
|
||||
glGetShaderiv(mVertexShader, GL_COMPILE_STATUS, &CompileStatus);
|
||||
|
||||
if (CompileStatus == GL_FALSE)
|
||||
{
|
||||
TString Out = "dump/BadVS_" + std::to_string(gFailedCompileCount) + ".txt";
|
||||
std::cout << "ERROR: Unable to compile vertex shader; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mVertexShader, Out);
|
||||
|
||||
gFailedCompileCount++;
|
||||
glDeleteShader(mVertexShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Debug dump
|
||||
else if (gDebugDumpShaders == true)
|
||||
{
|
||||
TString Out = "dump/VS_" + TString::FromInt64(gSuccessfulCompileCount, 8, 10) + ".txt";
|
||||
std::cout << "Debug shader dumping enabled; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mVertexShader, Out);
|
||||
|
||||
gSuccessfulCompileCount++;
|
||||
}
|
||||
|
||||
mVertexShaderExists = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShader::CompilePixelSource(const char* kpSource)
|
||||
{
|
||||
mPixelShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(mPixelShader, 1, (const GLchar**) &kpSource, NULL);
|
||||
glCompileShader(mPixelShader);
|
||||
|
||||
// Shader should be compiled - check for errors
|
||||
GLint CompileStatus;
|
||||
glGetShaderiv(mPixelShader, GL_COMPILE_STATUS, &CompileStatus);
|
||||
|
||||
if (CompileStatus == GL_FALSE)
|
||||
{
|
||||
TString Out = "dump/BadPS_" + TString::FromInt64(gFailedCompileCount, 8, 10) + ".txt";
|
||||
std::cout << "ERROR: Unable to compile pixel shader; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mPixelShader, Out);
|
||||
|
||||
gFailedCompileCount++;
|
||||
glDeleteShader(mPixelShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Debug dump
|
||||
else if (gDebugDumpShaders == true)
|
||||
{
|
||||
TString Out = "dump/PS_" + TString::FromInt64(gSuccessfulCompileCount, 8, 10) + ".txt";
|
||||
std::cout << "Debug shader dumping enabled; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mPixelShader, Out);
|
||||
|
||||
gSuccessfulCompileCount++;
|
||||
}
|
||||
|
||||
mPixelShaderExists = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShader::LinkShaders()
|
||||
{
|
||||
if ((!mVertexShaderExists) || (!mPixelShaderExists)) return false;
|
||||
|
||||
mProgram = glCreateProgram();
|
||||
glAttachShader(mProgram, mVertexShader);
|
||||
glAttachShader(mProgram, mPixelShader);
|
||||
glLinkProgram(mProgram);
|
||||
|
||||
glDeleteShader(mVertexShader);
|
||||
glDeleteShader(mPixelShader);
|
||||
mVertexShaderExists = false;
|
||||
mPixelShaderExists = false;
|
||||
|
||||
// Shader should be linked - check for errors
|
||||
GLint LinkStatus;
|
||||
glGetProgramiv(mProgram, GL_LINK_STATUS, &LinkStatus);
|
||||
|
||||
if (LinkStatus == GL_FALSE)
|
||||
{
|
||||
TString Out = "dump/BadLink_" + TString::FromInt64(gFailedCompileCount, 8, 10) + ".txt";
|
||||
std::cout << "ERROR: Unable to link shaders. Dumped error log to " << Out << "\n";
|
||||
|
||||
GLint LogLen;
|
||||
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &LogLen);
|
||||
GLchar *InfoLog = new GLchar[LogLen];
|
||||
glGetProgramInfoLog(mProgram, LogLen, NULL, InfoLog);
|
||||
|
||||
std::ofstream LinkOut;
|
||||
LinkOut.open(*Out);
|
||||
|
||||
if (LogLen > 0)
|
||||
LinkOut << InfoLog;
|
||||
|
||||
LinkOut.close();
|
||||
delete[] InfoLog;
|
||||
|
||||
gFailedCompileCount++;
|
||||
glDeleteProgram(mProgram);
|
||||
return false;
|
||||
}
|
||||
|
||||
mMVPBlockIndex = GetUniformBlockIndex("MVPBlock");
|
||||
mVertexBlockIndex = GetUniformBlockIndex("VertexBlock");
|
||||
mPixelBlockIndex = GetUniformBlockIndex("PixelBlock");
|
||||
mLightBlockIndex = GetUniformBlockIndex("LightBlock");
|
||||
|
||||
mProgramExists = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShader::IsValidProgram()
|
||||
{
|
||||
return mProgramExists;
|
||||
}
|
||||
|
||||
GLuint CShader::GetProgramID()
|
||||
{
|
||||
return mProgram;
|
||||
}
|
||||
|
||||
GLuint CShader::GetUniformLocation(const char* Uniform)
|
||||
{
|
||||
return glGetUniformLocation(mProgram, Uniform);
|
||||
}
|
||||
|
||||
GLuint CShader::GetUniformBlockIndex(const char* UniformBlock)
|
||||
{
|
||||
return glGetUniformBlockIndex(mProgram, UniformBlock);
|
||||
}
|
||||
|
||||
void CShader::SetCurrent()
|
||||
{
|
||||
if (spCurrentShader != this)
|
||||
{
|
||||
glUseProgram(mProgram);
|
||||
spCurrentShader = this;
|
||||
|
||||
glUniformBlockBinding(mProgram, mMVPBlockIndex, CGraphics::MVPBlockBindingPoint());
|
||||
glUniformBlockBinding(mProgram, mVertexBlockIndex, CGraphics::VertexBlockBindingPoint());
|
||||
glUniformBlockBinding(mProgram, mPixelBlockIndex, CGraphics::PixelBlockBindingPoint());
|
||||
glUniformBlockBinding(mProgram, mLightBlockIndex, CGraphics::LightBlockBindingPoint());
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CShader* CShader::FromResourceFile(const TString& ShaderName)
|
||||
{
|
||||
TString VertexShaderFilename = "../resources/shaders/" + ShaderName + ".vs";
|
||||
TString PixelShaderFilename = "../resources/shaders/" + ShaderName + ".ps";
|
||||
CTextInStream VertexShaderFile(VertexShaderFilename.ToStdString());
|
||||
CTextInStream PixelShaderFile(PixelShaderFilename.ToStdString());
|
||||
|
||||
if (!VertexShaderFile.IsValid())
|
||||
std::cout << "Error: Couldn't load vertex shader file for " << ShaderName << "\n";
|
||||
if (!PixelShaderFile.IsValid())
|
||||
std::cout << "Error: Couldn't load pixel shader file for " << ShaderName << "\n";
|
||||
if ((!VertexShaderFile.IsValid()) || (!PixelShaderFile.IsValid())) return nullptr;
|
||||
|
||||
std::stringstream VertexShader;
|
||||
while (!VertexShaderFile.EoF())
|
||||
VertexShader << VertexShaderFile.GetString();
|
||||
|
||||
std::stringstream PixelShader;
|
||||
while (!PixelShaderFile.EoF())
|
||||
PixelShader << PixelShaderFile.GetString();
|
||||
|
||||
CShader *pShader = new CShader();
|
||||
pShader->CompileVertexSource(VertexShader.str().c_str());
|
||||
pShader->CompilePixelSource(PixelShader.str().c_str());
|
||||
pShader->LinkShaders();
|
||||
return pShader;
|
||||
}
|
||||
|
||||
CShader* CShader::CurrentShader()
|
||||
{
|
||||
return spCurrentShader;
|
||||
}
|
||||
|
||||
void CShader::KillCachedShader()
|
||||
{
|
||||
spCurrentShader = 0;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CShader::DumpShaderSource(GLuint Shader, const TString& Out)
|
||||
{
|
||||
GLint SourceLen;
|
||||
glGetShaderiv(Shader, GL_SHADER_SOURCE_LENGTH, &SourceLen);
|
||||
GLchar *Source = new GLchar[SourceLen];
|
||||
glGetShaderSource(Shader, SourceLen, NULL, Source);
|
||||
|
||||
GLint LogLen;
|
||||
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &LogLen);
|
||||
GLchar *InfoLog = new GLchar[LogLen];
|
||||
glGetShaderInfoLog(Shader, LogLen, NULL, InfoLog);
|
||||
|
||||
std::ofstream ShaderOut;
|
||||
ShaderOut.open(*Out);
|
||||
|
||||
if (SourceLen > 0)
|
||||
ShaderOut << Source;
|
||||
if (LogLen > 0)
|
||||
ShaderOut << InfoLog;
|
||||
|
||||
ShaderOut.close();
|
||||
|
||||
delete[] Source;
|
||||
delete[] InfoLog;
|
||||
}
|
||||
45
src/Core/OpenGL/CShader.h
Normal file
45
src/Core/OpenGL/CShader.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef CSHADER_H
|
||||
#define CSHADER_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
#include <Common/TString.h>
|
||||
|
||||
class CShader
|
||||
{
|
||||
bool mVertexShaderExists;
|
||||
bool mPixelShaderExists;
|
||||
bool mProgramExists;
|
||||
GLuint mVertexShader;
|
||||
GLuint mPixelShader;
|
||||
GLuint mProgram;
|
||||
|
||||
GLuint mMVPBlockIndex;
|
||||
GLuint mVertexBlockIndex;
|
||||
GLuint mPixelBlockIndex;
|
||||
GLuint mLightBlockIndex;
|
||||
|
||||
static CShader* spCurrentShader;
|
||||
|
||||
public:
|
||||
CShader();
|
||||
CShader(const char* kpVertexSource, const char* kpPixelSource);
|
||||
~CShader();
|
||||
bool CompileVertexSource(const char* kpSource);
|
||||
bool CompilePixelSource(const char* kpSource);
|
||||
bool LinkShaders();
|
||||
bool IsValidProgram();
|
||||
GLuint GetProgramID();
|
||||
GLuint GetUniformLocation(const char* kpUniform);
|
||||
GLuint GetUniformBlockIndex(const char* kpUniformBlock);
|
||||
void SetCurrent();
|
||||
|
||||
// Static
|
||||
static CShader* FromResourceFile(const TString& ShaderName);
|
||||
static CShader* CurrentShader();
|
||||
static void KillCachedShader();
|
||||
|
||||
private:
|
||||
void DumpShaderSource(GLuint Shader, const TString& Out);
|
||||
};
|
||||
|
||||
#endif // CSHADER_H
|
||||
443
src/Core/OpenGL/CShaderGenerator.cpp
Normal file
443
src/Core/OpenGL/CShaderGenerator.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <gl/glew.h>
|
||||
#include "CShaderGenerator.h"
|
||||
|
||||
const TString gkCoordSrc[] = {
|
||||
"RawPosition.xyz",
|
||||
"RawNormal.xyz",
|
||||
"0.0, 0.0, 0.0",
|
||||
"0.0, 0.0, 0.0",
|
||||
"RawTex0.xy, 1.0",
|
||||
"RawTex1.xy, 1.0",
|
||||
"RawTex2.xy, 1.0",
|
||||
"RawTex3.xy, 1.0",
|
||||
"RawTex4.xy, 1.0",
|
||||
"RawTex5.xy, 1.0",
|
||||
"RawTex6.xy, 1.0",
|
||||
"RawTex7.xy, 1.0"
|
||||
};
|
||||
|
||||
const TString gkRasSel[] = {
|
||||
"vec4(COLOR0A0.rgb, 1.0)",
|
||||
"vec4(COLOR1A1.rgb, 1.0)",
|
||||
"vec4(0.0, 0.0, 0.0, COLOR0A0.a)",
|
||||
"vec4(0.0, 0.0, 0.0, COLOR1A1.a)",
|
||||
"COLOR0A0",
|
||||
"COLOR1A1",
|
||||
"vec4(0.0, 0.0, 0.0, 0.0)"
|
||||
};
|
||||
|
||||
const TString gkKonstColor[] = {
|
||||
"1.0, 1.0, 1.0",
|
||||
"0.875, 0.875, 0.875",
|
||||
"0.75, 0.75, 0.75",
|
||||
"0.625, 0.625, 0.625",
|
||||
"0.5, 0.5, 0.5",
|
||||
"0.375, 0.375, 0.375",
|
||||
"0.25, 0.25, 0.25",
|
||||
"0.125, 0.125, 0.125",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"KonstColors[0].rgb",
|
||||
"KonstColors[1].rgb",
|
||||
"KonstColors[2].rgb",
|
||||
"KonstColors[3].rgb",
|
||||
"KonstColors[0].rrr",
|
||||
"KonstColors[1].rrr",
|
||||
"KonstColors[2].rrr",
|
||||
"KonstColors[3].rrr",
|
||||
"KonstColors[0].ggg",
|
||||
"KonstColors[1].ggg",
|
||||
"KonstColors[2].ggg",
|
||||
"KonstColors[3].ggg",
|
||||
"KonstColors[0].bbb",
|
||||
"KonstColors[1].bbb",
|
||||
"KonstColors[2].bbb",
|
||||
"KonstColors[3].bbb",
|
||||
"KonstColors[0].aaa",
|
||||
"KonstColors[1].aaa",
|
||||
"KonstColors[2].aaa",
|
||||
"KonstColors[3].aaa"
|
||||
};
|
||||
|
||||
const TString gkKonstAlpha[] = {
|
||||
"1.0",
|
||||
"0.875",
|
||||
"0.75",
|
||||
"0.625",
|
||||
"0.5",
|
||||
"0.375",
|
||||
"0.25",
|
||||
"0.125",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"KonstColors[0].r",
|
||||
"KonstColors[1].r",
|
||||
"KonstColors[2].r",
|
||||
"KonstColors[3].r",
|
||||
"KonstColors[0].g",
|
||||
"KonstColors[1].g",
|
||||
"KonstColors[2].g",
|
||||
"KonstColors[3].g",
|
||||
"KonstColors[0].b",
|
||||
"KonstColors[1].b",
|
||||
"KonstColors[2].b",
|
||||
"KonstColors[3].b",
|
||||
"KonstColors[0].a",
|
||||
"KonstColors[1].a",
|
||||
"KonstColors[2].a",
|
||||
"KonstColors[3].a"
|
||||
};
|
||||
|
||||
const TString gkTevColor[] = {
|
||||
"Prev.rgb",
|
||||
"Prev.aaa",
|
||||
"C0.rgb",
|
||||
"C0.aaa",
|
||||
"C1.rgb",
|
||||
"C1.aaa",
|
||||
"C2.rgb",
|
||||
"C2.aaa",
|
||||
"Tex.rgb",
|
||||
"Tex.aaa",
|
||||
"Ras.rgb",
|
||||
"Ras.aaa",
|
||||
"1.0, 1.0, 1.0",
|
||||
"0.5, 0.5, 0.5",
|
||||
"Konst.rgb",
|
||||
"0.0, 0.0, 0.0"
|
||||
};
|
||||
|
||||
const TString gkTevAlpha[] = {
|
||||
"Prev.a",
|
||||
"C0.a",
|
||||
"C1.a",
|
||||
"C2.a",
|
||||
"Tex.a",
|
||||
"Ras.a",
|
||||
"Konst.a",
|
||||
"0.0"
|
||||
};
|
||||
|
||||
const TString gkTevRigid[] = {
|
||||
"Prev",
|
||||
"C0",
|
||||
"C1",
|
||||
"C2"
|
||||
};
|
||||
|
||||
CShaderGenerator::CShaderGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
CShaderGenerator::~CShaderGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
bool CShaderGenerator::CreateVertexShader(const CMaterial& Mat)
|
||||
{
|
||||
std::stringstream ShaderCode;
|
||||
|
||||
ShaderCode << "#version 330 core\n"
|
||||
<< "\n";
|
||||
|
||||
// Input
|
||||
ShaderCode << "// Input\n";
|
||||
EVertexDescription VtxDesc = Mat.VtxDesc();
|
||||
if (VtxDesc & ePosition) ShaderCode << "layout(location = 0) in vec3 RawPosition;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "layout(location = 1) in vec3 RawNormal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "layout(location = 2) in vec4 RawColor0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "layout(location = 3) in vec4 RawColor1;\n";
|
||||
if (VtxDesc & eTex0) ShaderCode << "layout(location = 4) in vec2 RawTex0;\n";
|
||||
if (VtxDesc & eTex1) ShaderCode << "layout(location = 5) in vec2 RawTex1;\n";
|
||||
if (VtxDesc & eTex2) ShaderCode << "layout(location = 6) in vec2 RawTex2;\n";
|
||||
if (VtxDesc & eTex3) ShaderCode << "layout(location = 7) in vec2 RawTex3;\n";
|
||||
if (VtxDesc & eTex4) ShaderCode << "layout(location = 8) in vec2 RawTex4;\n";
|
||||
if (VtxDesc & eTex5) ShaderCode << "layout(location = 9) in vec2 RawTex5;\n";
|
||||
if (VtxDesc & eTex6) ShaderCode << "layout(location = 10) in vec2 RawTex6;\n";
|
||||
ShaderCode << "\n";
|
||||
|
||||
// Output
|
||||
ShaderCode << "// Output\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "out vec3 Normal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "out vec4 Color0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "out vec4 Color1;\n";
|
||||
|
||||
for (u32 iPass = 0; iPass < Mat.PassCount(); iPass++)
|
||||
if (Mat.Pass(iPass)->TexCoordSource() != 0xFF)
|
||||
ShaderCode << "out vec3 Tex" << iPass << ";\n";
|
||||
|
||||
ShaderCode << "out vec4 COLOR0A0;\n"
|
||||
<< "out vec4 COLOR1A1;\n";
|
||||
ShaderCode << "\n";
|
||||
|
||||
// Uniforms
|
||||
ShaderCode << "// Uniforms\n"
|
||||
<< "layout(std140) uniform MVPBlock\n"
|
||||
<< "{\n"
|
||||
<< " mat4 ModelMtx;\n"
|
||||
<< " mat4 ViewMtx;\n"
|
||||
<< " mat4 ProjMtx;\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "layout(std140) uniform VertexBlock\n"
|
||||
<< "{\n"
|
||||
<< " mat4 TexMtx[10];\n"
|
||||
<< " mat4 PostMtx[20];\n"
|
||||
<< " vec4 COLOR0_Amb;\n"
|
||||
<< " vec4 COLOR0_Mat;\n"
|
||||
<< " vec4 COLOR1_Amb;\n"
|
||||
<< " vec4 COLOR1_Mat;\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "struct GXLight\n"
|
||||
<< "{\n"
|
||||
<< " vec4 Position;\n"
|
||||
<< " vec4 Direction;\n"
|
||||
<< " vec4 Color;\n"
|
||||
<< " vec4 DistAtten;\n"
|
||||
<< " vec4 AngleAtten;\n"
|
||||
<< "};\n"
|
||||
<< "layout(std140) uniform LightBlock {\n"
|
||||
<< " GXLight Lights[8];\n"
|
||||
<< "};\n"
|
||||
<< "uniform int NumLights;\n"
|
||||
<< "\n";
|
||||
|
||||
// Main
|
||||
ShaderCode << "// Main\n"
|
||||
<< "void main()\n"
|
||||
<< "{\n"
|
||||
<< " mat4 MV = ModelMtx * ViewMtx;\n"
|
||||
<< " mat4 MVP = MV * ProjMtx;\n";
|
||||
|
||||
if (VtxDesc & ePosition) ShaderCode << " gl_Position = vec4(RawPosition, 1) * MVP;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << " Normal = normalize(RawNormal.xyz * inverse(transpose(mat3(MV))));\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << " Color0 = RawColor0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << " Color1 = RawColor1;\n";
|
||||
|
||||
// Per-vertex lighting
|
||||
ShaderCode << "\n"
|
||||
<< " // Dynamic Lighting\n";
|
||||
|
||||
// This bit could do with some cleaning up
|
||||
// It took a lot of experimentation to get dynamic lights working and I never went back and cleaned it up after
|
||||
if (Mat.IsLightingEnabled())
|
||||
{
|
||||
ShaderCode << " vec4 Illum = vec4(0.0);\n"
|
||||
<< " vec3 PositionMV = vec3(vec4(RawPosition, 1.0) * MV);\n"
|
||||
<< " \n"
|
||||
<< " for (int iLight = 0; iLight < NumLights; iLight++)\n"
|
||||
<< " {\n"
|
||||
<< " vec3 LightPosMV = vec3(Lights[iLight].Position * ViewMtx);\n"
|
||||
<< " vec3 LightDirMV = normalize(Lights[iLight].Direction.xyz * inverse(transpose(mat3(ViewMtx))));\n"
|
||||
<< " vec3 LightDist = LightPosMV.xyz - PositionMV.xyz;\n"
|
||||
<< " float DistSquared = dot(LightDist, LightDist);\n"
|
||||
<< " float Dist = sqrt(DistSquared);\n"
|
||||
<< " LightDist /= Dist;\n"
|
||||
<< " vec3 AngleAtten = Lights[iLight].AngleAtten.xyz;\n"
|
||||
<< " AngleAtten = vec3(AngleAtten.x, AngleAtten.y, AngleAtten.z);\n"
|
||||
<< " float Atten = max(0, dot(LightDist, LightDirMV.xyz));\n"
|
||||
<< " Atten = max(0, dot(AngleAtten, vec3(1.0, Atten, Atten * Atten))) / dot(Lights[iLight].DistAtten.xyz, vec3(1.0, Dist, DistSquared));\n"
|
||||
<< " float DiffuseAtten = max(0, dot(Normal, LightDist));\n"
|
||||
<< " Illum += (Atten * DiffuseAtten * Lights[iLight].Color);\n"
|
||||
<< " }\n"
|
||||
<< " COLOR0A0 = COLOR0_Mat * (Illum + COLOR0_Amb);\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat * (Illum + COLOR1_Amb);\n"
|
||||
<< " \n";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ShaderCode << " COLOR0A0 = COLOR0_Mat;\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat;\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Texture coordinate generation
|
||||
ShaderCode << " \n"
|
||||
<< " // TexGen\n";
|
||||
|
||||
u32 PassCount = Mat.PassCount();
|
||||
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
{
|
||||
CMaterialPass *pPass = Mat.Pass(iPass);
|
||||
if (pPass->TexCoordSource() == 0xFF) continue;
|
||||
|
||||
EUVAnimMode AnimMode = pPass->AnimMode();
|
||||
|
||||
if (AnimMode == eNoUVAnim) // No animation
|
||||
ShaderCode << " Tex" << iPass << " = vec3(" << gkCoordSrc[pPass->TexCoordSource()] << ");\n";
|
||||
|
||||
else // Animation used - texture matrix at least, possibly normalize/post-transform
|
||||
{
|
||||
// Texture Matrix
|
||||
ShaderCode << " Tex" << iPass << " = vec3(vec4(" << gkCoordSrc[pPass->TexCoordSource()] << ", 1.0) * TexMtx[" << iPass << "]).xyz;\n";
|
||||
|
||||
if ((AnimMode < 2) || (AnimMode > 5))
|
||||
{
|
||||
// Normalization + Post-Transform
|
||||
ShaderCode << " Tex" << iPass << " = normalize(Tex" << iPass << ");\n";
|
||||
ShaderCode << " Tex" << iPass << " = vec3(vec4(Tex" << iPass << ", 1.0) * PostMtx[" << iPass << "]).xyz;\n";
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCode << "\n";
|
||||
}
|
||||
ShaderCode << "}\n\n";
|
||||
|
||||
|
||||
// Done!
|
||||
return mShader->CompileVertexSource(ShaderCode.str().c_str());
|
||||
}
|
||||
|
||||
bool CShaderGenerator::CreatePixelShader(const CMaterial& Mat)
|
||||
{
|
||||
std::stringstream ShaderCode;
|
||||
ShaderCode << "#version 330 core\n"
|
||||
<< "\n";
|
||||
|
||||
EVertexDescription VtxDesc = Mat.VtxDesc();
|
||||
if (VtxDesc & ePosition) ShaderCode << "in vec3 Position;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "in vec3 Normal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "in vec4 Color0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "in vec4 Color1;\n";
|
||||
|
||||
u32 PassCount = Mat.PassCount();
|
||||
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
if (Mat.Pass(iPass)->TexCoordSource() != 0xFF)
|
||||
ShaderCode << "in vec3 Tex" << iPass << ";\n";
|
||||
|
||||
ShaderCode << "in vec4 COLOR0A0;\n"
|
||||
<< "in vec4 COLOR1A1;\n"
|
||||
<< "\n"
|
||||
<< "out vec4 PixelColor;\n"
|
||||
<< "\n"
|
||||
<< "layout(std140) uniform PixelBlock {\n"
|
||||
<< " vec4 KonstColors[4];\n"
|
||||
<< " vec4 TevColor;\n"
|
||||
<< " vec4 TintColor;\n"
|
||||
<< "};\n\n";
|
||||
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
if (Mat.Pass(iPass)->Texture() != nullptr)
|
||||
ShaderCode << "uniform sampler2D Texture" << iPass << ";\n";
|
||||
|
||||
ShaderCode <<"\n";
|
||||
|
||||
ShaderCode << "void main()\n"
|
||||
<< "{\n"
|
||||
<< " vec4 TevInA = vec4(0, 0, 0, 0), TevInB = vec4(0, 0, 0, 0), TevInC = vec4(0, 0, 0, 0), TevInD = vec4(0, 0, 0, 0);\n"
|
||||
<< " vec4 Prev = vec4(0, 0, 0, 0), C0 = TevColor, C1 = C0, C2 = C0;\n"
|
||||
<< " vec4 Ras = vec4(0, 0, 0, 1), Tex = vec4(0, 0, 0, 0);\n"
|
||||
<< " vec4 Konst = vec4(1, 1, 1, 1);\n";
|
||||
|
||||
ShaderCode << " vec2 TevCoord = vec2(0, 0);\n"
|
||||
<< " \n";
|
||||
|
||||
bool Lightmap = false;
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
{
|
||||
const CMaterialPass *pPass = Mat.Pass(iPass);
|
||||
CFourCC PassType = pPass->Type();
|
||||
|
||||
ShaderCode << " // TEV Stage " << iPass << " - " << PassType.ToString() << "\n";
|
||||
if (pPass->Type() == "DIFF") Lightmap = true;
|
||||
|
||||
if (!pPass->IsEnabled())
|
||||
{
|
||||
ShaderCode << " // Pass is disabled\n\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pPass->TexCoordSource() != 0xFF)
|
||||
ShaderCode << " TevCoord = (Tex" << iPass << ".z == 0.0 ? Tex" << iPass << ".xy : Tex" << iPass << ".xy / Tex" << iPass << ".z);\n";
|
||||
|
||||
if (pPass->Texture() != nullptr)
|
||||
ShaderCode << " Tex = texture(Texture" << iPass << ", TevCoord)";
|
||||
|
||||
// A couple pass types require special swizzles to access different texture color channels as alpha
|
||||
if ((PassType == "TRAN") || (PassType == "INCA") || (PassType == "BLOI"))
|
||||
ShaderCode << ".rgbr";
|
||||
else if (PassType == "BLOL")
|
||||
ShaderCode << ".rgbg";
|
||||
|
||||
ShaderCode << ";\n";
|
||||
|
||||
ShaderCode << " Konst = vec4(" << gkKonstColor[pPass->KColorSel()] << ", " << gkKonstAlpha[pPass->KAlphaSel()] << ");\n";
|
||||
|
||||
if (pPass->RasSel() != eRasColorNull)
|
||||
ShaderCode << " Ras = " << gkRasSel[pPass->RasSel()] << ";\n";
|
||||
|
||||
for (u8 iInput = 0; iInput < 4; iInput++)
|
||||
{
|
||||
char TevChar = iInput + 0x41; // the current stage number represented as an ASCII letter; eg 0 is 'A'
|
||||
|
||||
ShaderCode << " TevIn" << TevChar << " = vec4("
|
||||
<< gkTevColor[pPass->ColorInput(iInput) & 0xF]
|
||||
<< ", "
|
||||
<< gkTevAlpha[pPass->AlphaInput(iInput) & 0x7]
|
||||
<< ");\n";
|
||||
}
|
||||
|
||||
ShaderCode << " // RGB Combine\n"
|
||||
<< " "
|
||||
<< gkTevRigid[pPass->ColorOutput()]
|
||||
<< ".rgb = ";
|
||||
|
||||
ShaderCode << "clamp(vec3(TevInD.rgb + ((1.0 - TevInC.rgb) * TevInA.rgb + TevInC.rgb * TevInB.rgb))";
|
||||
if ((PassType == "CLR ") && (Lightmap)) ShaderCode << "* 2.0"; // Apply tevscale 2.0 on the color pass if lightmap is present
|
||||
ShaderCode << ", vec3(0, 0, 0), vec3(1.0, 1.0, 1.0));\n";
|
||||
|
||||
ShaderCode << " // Alpha Combine\n"
|
||||
<< " "
|
||||
<< gkTevRigid[pPass->AlphaOutput()]
|
||||
<< ".a = ";
|
||||
|
||||
ShaderCode << "clamp(TevInD.a + ((1.0 - TevInC.a) * TevInA.a + TevInC.a * TevInB.a), 0.0, 1.0);\n\n";
|
||||
}
|
||||
|
||||
if (Mat.Options() & CMaterial::ePunchthrough)
|
||||
{
|
||||
if (Mat.Version() < eCorruptionProto)
|
||||
{
|
||||
ShaderCode << " if (Prev.a <= 0.25) discard;\n"
|
||||
<< " else Prev.a = 1.0;\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderCode << " if (Prev.a <= 0.75) discard;\n"
|
||||
" else Prev.a = 0.0;\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCode << " PixelColor = Prev.rgba * TintColor;\n"
|
||||
<< "}\n\n";
|
||||
|
||||
// Done!
|
||||
return mShader->CompilePixelSource(ShaderCode.str().c_str());
|
||||
}
|
||||
|
||||
CShader* CShaderGenerator::GenerateShader(const CMaterial& Mat)
|
||||
{
|
||||
CShaderGenerator Generator;
|
||||
Generator.mShader = new CShader();
|
||||
|
||||
bool Success = Generator.CreateVertexShader(Mat);
|
||||
if (Success) Success = Generator.CreatePixelShader(Mat);
|
||||
|
||||
Generator.mShader->LinkShaders();
|
||||
return Generator.mShader;
|
||||
}
|
||||
22
src/Core/OpenGL/CShaderGenerator.h
Normal file
22
src/Core/OpenGL/CShaderGenerator.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef SHADERGEN_H
|
||||
#define SHADERGEN_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
|
||||
#include "CShader.h"
|
||||
#include <Resource/CMaterial.h>
|
||||
|
||||
class CShaderGenerator
|
||||
{
|
||||
CShader *mShader;
|
||||
|
||||
CShaderGenerator();
|
||||
~CShaderGenerator();
|
||||
bool CreateVertexShader(const CMaterial& Mat);
|
||||
bool CreatePixelShader(const CMaterial& Mat);
|
||||
|
||||
public:
|
||||
static CShader* GenerateShader(const CMaterial& Mat);
|
||||
};
|
||||
|
||||
#endif // SHADERGEN_H
|
||||
60
src/Core/OpenGL/CUniformBuffer.cpp
Normal file
60
src/Core/OpenGL/CUniformBuffer.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "CUniformBuffer.h"
|
||||
|
||||
CUniformBuffer::CUniformBuffer()
|
||||
{
|
||||
glGenBuffers(1, &mUniformBuffer);
|
||||
SetBufferSize(0);
|
||||
}
|
||||
|
||||
CUniformBuffer::CUniformBuffer(u32 Size)
|
||||
{
|
||||
glGenBuffers(1, &mUniformBuffer);
|
||||
SetBufferSize(Size);
|
||||
}
|
||||
|
||||
CUniformBuffer::~CUniformBuffer()
|
||||
{
|
||||
glDeleteBuffers(1, &mUniformBuffer);
|
||||
}
|
||||
|
||||
void CUniformBuffer::InitializeBuffer()
|
||||
{
|
||||
Bind();
|
||||
glBufferData(GL_UNIFORM_BUFFER, mBufferSize, 0, GL_DYNAMIC_DRAW);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CUniformBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
|
||||
}
|
||||
|
||||
void CUniformBuffer::Unbind()
|
||||
{
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
void CUniformBuffer::BindBase(GLuint index)
|
||||
{
|
||||
Bind();
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, index, mUniformBuffer);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CUniformBuffer::Buffer(void *pData)
|
||||
{
|
||||
Bind();
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, mBufferSize, pData);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CUniformBuffer::SetBufferSize(u32 Size)
|
||||
{
|
||||
mBufferSize = Size;
|
||||
InitializeBuffer();
|
||||
}
|
||||
|
||||
u32 CUniformBuffer::GetBufferSize()
|
||||
{
|
||||
return mBufferSize;
|
||||
}
|
||||
28
src/Core/OpenGL/CUniformBuffer.h
Normal file
28
src/Core/OpenGL/CUniformBuffer.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CUNIFORMBUFFER_H
|
||||
#define CUNIFORMBUFFER_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
class CUniformBuffer
|
||||
{
|
||||
GLuint mUniformBuffer;
|
||||
u32 mBufferSize;
|
||||
|
||||
public:
|
||||
CUniformBuffer();
|
||||
CUniformBuffer(u32 Size);
|
||||
~CUniformBuffer();
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void BindBase(GLuint index);
|
||||
void Buffer(void *pData);
|
||||
|
||||
void SetBufferSize(u32 Size);
|
||||
u32 GetBufferSize();
|
||||
|
||||
private:
|
||||
void InitializeBuffer();
|
||||
};
|
||||
|
||||
#endif // CUNIFORMBUFFER_H
|
||||
105
src/Core/OpenGL/CVertexArrayManager.cpp
Normal file
105
src/Core/OpenGL/CVertexArrayManager.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "CVertexArrayManager.h"
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
std::vector<CVertexArrayManager*> CVertexArrayManager::sVAManagers;
|
||||
CVertexArrayManager *CVertexArrayManager::spCurrentManager;
|
||||
|
||||
// ************ CONSTRUCTORS/DESTRUCTORS ************
|
||||
CVertexArrayManager::CVertexArrayManager()
|
||||
{
|
||||
mVectorIndex = sVAManagers.size();
|
||||
sVAManagers.push_back(this);
|
||||
}
|
||||
|
||||
CVertexArrayManager::~CVertexArrayManager()
|
||||
{
|
||||
for (auto it = mVBOMap.begin(); it != mVBOMap.end(); it = mVBOMap.begin())
|
||||
DeleteVAO(it->first);
|
||||
|
||||
for (auto it = mDynamicVBOMap.begin(); it != mDynamicVBOMap.end(); it = mDynamicVBOMap.begin())
|
||||
DeleteVAO(it->first);
|
||||
|
||||
sVAManagers.erase(sVAManagers.begin() + mVectorIndex);
|
||||
|
||||
if (sVAManagers.size() > mVectorIndex)
|
||||
for (auto it = sVAManagers.begin() + mVectorIndex; it != sVAManagers.end(); it++)
|
||||
(*it)->mVectorIndex--;
|
||||
}
|
||||
|
||||
// ************ PUBLIC ************
|
||||
void CVertexArrayManager::SetCurrent()
|
||||
{
|
||||
spCurrentManager = this;
|
||||
}
|
||||
|
||||
void CVertexArrayManager::BindVAO(CVertexBuffer *pVBO)
|
||||
{
|
||||
auto it = mVBOMap.find(pVBO);
|
||||
|
||||
if (it != mVBOMap.end())
|
||||
glBindVertexArray(it->second);
|
||||
|
||||
else
|
||||
{
|
||||
GLuint VAO = pVBO->CreateVAO();
|
||||
mVBOMap[pVBO] = VAO;
|
||||
glBindVertexArray(VAO);
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexArrayManager::BindVAO(CDynamicVertexBuffer *pVBO)
|
||||
{
|
||||
// Overload for CDynamicVertexBuffer
|
||||
auto it = mDynamicVBOMap.find(pVBO);
|
||||
|
||||
if (it != mDynamicVBOMap.end())
|
||||
glBindVertexArray(it->second);
|
||||
|
||||
else
|
||||
{
|
||||
GLuint VAO = pVBO->CreateVAO();
|
||||
mDynamicVBOMap[pVBO] = VAO;
|
||||
glBindVertexArray(VAO);
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteVAO(CVertexBuffer *pVBO)
|
||||
{
|
||||
auto it = mVBOMap.find(pVBO);
|
||||
|
||||
if (it != mVBOMap.end())
|
||||
{
|
||||
glDeleteVertexArrays(1, &it->second);
|
||||
mVBOMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteVAO(CDynamicVertexBuffer *pVBO)
|
||||
{
|
||||
// Overload for CDynamicVertexBuffer
|
||||
auto it = mDynamicVBOMap.find(pVBO);
|
||||
|
||||
if (it != mDynamicVBOMap.end())
|
||||
{
|
||||
glDeleteVertexArrays(1, &it->second);
|
||||
mDynamicVBOMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CVertexArrayManager* CVertexArrayManager::Current()
|
||||
{
|
||||
return spCurrentManager;
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteAllArraysForVBO(CVertexBuffer *pVBO)
|
||||
{
|
||||
for (u32 iVAM = 0; iVAM < sVAManagers.size(); iVAM++)
|
||||
sVAManagers[iVAM]->DeleteVAO(pVBO);
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteAllArraysForVBO(CDynamicVertexBuffer *pVBO)
|
||||
{
|
||||
for (u32 iVAM = 0; iVAM < sVAManagers.size(); iVAM++)
|
||||
sVAManagers[iVAM]->DeleteVAO(pVBO);
|
||||
}
|
||||
34
src/Core/OpenGL/CVertexArrayManager.h
Normal file
34
src/Core/OpenGL/CVertexArrayManager.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CVERTEXARRAYMANAGER_H
|
||||
#define CVERTEXARRAYMANAGER_H
|
||||
|
||||
#include "CDynamicVertexBuffer.h"
|
||||
#include "CVertexBuffer.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <GL/glew.h>
|
||||
|
||||
class CVertexArrayManager
|
||||
{
|
||||
std::unordered_map<CVertexBuffer*, GLuint> mVBOMap;
|
||||
std::unordered_map<CDynamicVertexBuffer*, GLuint> mDynamicVBOMap;
|
||||
u32 mVectorIndex;
|
||||
|
||||
static std::vector<CVertexArrayManager*> sVAManagers;
|
||||
static CVertexArrayManager *spCurrentManager;
|
||||
|
||||
public:
|
||||
CVertexArrayManager();
|
||||
~CVertexArrayManager();
|
||||
void SetCurrent();
|
||||
void BindVAO(CVertexBuffer *pVBO);
|
||||
void BindVAO(CDynamicVertexBuffer *pVBO);
|
||||
void DeleteVAO(CVertexBuffer *pVBO);
|
||||
void DeleteVAO(CDynamicVertexBuffer *pVBO);
|
||||
|
||||
static CVertexArrayManager* Current();
|
||||
static void DeleteAllArraysForVBO(CVertexBuffer *pVBO);
|
||||
static void DeleteAllArraysForVBO(CDynamicVertexBuffer *pVBO);
|
||||
};
|
||||
|
||||
#endif // CVERTEXARRAYMANAGER_H
|
||||
230
src/Core/OpenGL/CVertexBuffer.cpp
Normal file
230
src/Core/OpenGL/CVertexBuffer.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#include "CVertexBuffer.h"
|
||||
#include "CVertexArrayManager.h"
|
||||
#include <Core/CGraphics.h>
|
||||
|
||||
CVertexBuffer::CVertexBuffer()
|
||||
{
|
||||
mBuffered = false;
|
||||
SetVertexDesc(ePosition | eNormal | eTex0 | eTex1 | eTex2 | eTex3 | eTex4 | eTex5 | eTex6 | eTex7);
|
||||
}
|
||||
|
||||
CVertexBuffer::CVertexBuffer(EVertexDescription Desc)
|
||||
{
|
||||
mBuffered = false;
|
||||
SetVertexDesc(Desc);
|
||||
}
|
||||
|
||||
CVertexBuffer::~CVertexBuffer()
|
||||
{
|
||||
CVertexArrayManager::DeleteAllArraysForVBO(this);
|
||||
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(12, mAttribBuffers);
|
||||
}
|
||||
|
||||
u16 CVertexBuffer::AddVertex(const CVertex& Vert)
|
||||
{
|
||||
if (mPositions.size() == 0xFFFF) throw std::overflow_error("VBO contains too many vertices");
|
||||
|
||||
if (mVtxDesc & ePosition) mPositions.push_back(Vert.Position);
|
||||
if (mVtxDesc & eNormal) mNormals.push_back(Vert.Normal);
|
||||
if (mVtxDesc & eColor0) mColors[0].push_back(Vert.Color[0]);
|
||||
if (mVtxDesc & eColor1) mColors[1].push_back(Vert.Color[1]);
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
if (mVtxDesc & (eTex0 << (iTex * 2))) mTexCoords[iTex].push_back(Vert.Tex[iTex]);
|
||||
|
||||
for (u32 iMtx = 0; iMtx < 8; iMtx++)
|
||||
if (mVtxDesc & (ePosMtx << iMtx)) mTexCoords[iMtx].push_back(Vert.MatrixIndices[iMtx]);
|
||||
|
||||
return (mPositions.size() - 1);
|
||||
}
|
||||
|
||||
u16 CVertexBuffer::AddIfUnique(const CVertex& Vert, u16 Start)
|
||||
{
|
||||
if (Start < mPositions.size())
|
||||
{
|
||||
for (u16 iVert = Start; iVert < mPositions.size(); iVert++)
|
||||
{
|
||||
// I use a bool because "continue" doesn't work properly within the iTex loop
|
||||
bool Unique = false;
|
||||
|
||||
if (mVtxDesc & ePosition)
|
||||
if (Vert.Position != mPositions[iVert]) Unique = true;
|
||||
|
||||
if ((!Unique) && (mVtxDesc & eNormal))
|
||||
if (Vert.Normal != mNormals[iVert]) Unique = true;
|
||||
|
||||
if ((!Unique) && (mVtxDesc & eColor0))
|
||||
if (Vert.Color[0] != mColors[0][iVert]) Unique = true;
|
||||
|
||||
if ((!Unique) && (mVtxDesc & eColor1))
|
||||
if (Vert.Color[1] != mColors[1][iVert]) Unique = true;
|
||||
|
||||
if (!Unique)
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
if ((mVtxDesc & (eTex0 << (iTex * 2))))
|
||||
if (Vert.Tex[iTex] != mTexCoords[iTex][iVert])
|
||||
{
|
||||
Unique = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Unique) return iVert;
|
||||
}
|
||||
}
|
||||
|
||||
return AddVertex(Vert);
|
||||
}
|
||||
|
||||
void CVertexBuffer::Reserve(u16 size)
|
||||
{
|
||||
u32 ReserveSize = mPositions.size() + size;
|
||||
|
||||
if (mVtxDesc & ePosition)
|
||||
mPositions.reserve(ReserveSize);
|
||||
|
||||
if (mVtxDesc & eNormal)
|
||||
mNormals.reserve(ReserveSize);
|
||||
|
||||
if (mVtxDesc & eColor0)
|
||||
mColors[0].reserve(ReserveSize);
|
||||
|
||||
if (mVtxDesc & eColor1)
|
||||
mColors[1].reserve(ReserveSize);
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
if (mVtxDesc & (eTex0 << (iTex * 2)))
|
||||
mTexCoords[iTex].reserve(ReserveSize);
|
||||
}
|
||||
|
||||
void CVertexBuffer::Clear()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(12, mAttribBuffers);
|
||||
|
||||
mBuffered = false;
|
||||
mPositions.clear();
|
||||
mNormals.clear();
|
||||
mColors[0].clear();
|
||||
mColors[1].clear();
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
mTexCoords[iTex].clear();
|
||||
}
|
||||
|
||||
void CVertexBuffer::Buffer()
|
||||
{
|
||||
// Make sure we don't end up with two buffers for the same data...
|
||||
if (mBuffered)
|
||||
{
|
||||
glDeleteBuffers(12, mAttribBuffers);
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
// Generate buffers
|
||||
glGenBuffers(12, mAttribBuffers);
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
int Attrib = (ePosition << (iAttrib * 2));
|
||||
bool HasAttrib = ((mVtxDesc & Attrib) != 0);
|
||||
if (!HasAttrib) continue;
|
||||
|
||||
if (iAttrib < 2)
|
||||
{
|
||||
std::vector<CVector3f> *pBuffer = (iAttrib == 0) ? &mPositions : &mNormals;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, pBuffer->size() * sizeof(CVector3f), pBuffer->data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
else if (iAttrib < 4)
|
||||
{
|
||||
u8 idx = (u8) (iAttrib - 2);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, mColors[idx].size() * sizeof(CColor), mColors[idx].data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
u8 idx = (u8) (iAttrib - 4);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, mTexCoords[idx].size() * sizeof(CVector2f), mTexCoords[idx].data(), GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CVertexBuffer::Bind()
|
||||
{
|
||||
if (!mBuffered) Buffer();
|
||||
CVertexArrayManager::Current()->BindVAO(this);
|
||||
}
|
||||
|
||||
void CVertexBuffer::Unbind()
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
bool CVertexBuffer::IsBuffered()
|
||||
{
|
||||
return mBuffered;
|
||||
}
|
||||
|
||||
EVertexDescription CVertexBuffer::VertexDesc()
|
||||
{
|
||||
return mVtxDesc;
|
||||
}
|
||||
|
||||
void CVertexBuffer::SetVertexDesc(EVertexDescription Desc)
|
||||
{
|
||||
Clear();
|
||||
mVtxDesc = Desc;
|
||||
}
|
||||
|
||||
u32 CVertexBuffer::Size()
|
||||
{
|
||||
return mPositions.size();
|
||||
}
|
||||
|
||||
GLuint CVertexBuffer::CreateVAO()
|
||||
{
|
||||
GLuint VertexArray;
|
||||
glGenVertexArrays(1, &VertexArray);
|
||||
glBindVertexArray(VertexArray);
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
int Attrib = (ePosition << (iAttrib * 2));
|
||||
bool HasAttrib = ((mVtxDesc & Attrib) != 0);
|
||||
if (!HasAttrib) continue;
|
||||
|
||||
if (iAttrib < 2)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glVertexAttribPointer(iAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(CVector3f), (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
|
||||
else if (iAttrib < 4)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glVertexAttribPointer(iAttrib, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(CColor), (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glVertexAttribPointer(iAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(CVector2f), (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
return VertexArray;
|
||||
}
|
||||
37
src/Core/OpenGL/CVertexBuffer.h
Normal file
37
src/Core/OpenGL/CVertexBuffer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef CVERTEXBUFFER_H
|
||||
#define CVERTEXBUFFER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Resource/model/CVertex.h>
|
||||
#include <Resource/model/EVertexDescription.h>
|
||||
#include <vector>
|
||||
|
||||
class CVertexBuffer
|
||||
{
|
||||
EVertexDescription mVtxDesc; // Flags that indicate what vertex attributes are enabled on this vertex buffer
|
||||
GLuint mAttribBuffers[12]; // Separate GL buffer for each attribute to allow not tracking unused attribs. No support for matrix indices currently.
|
||||
std::vector<CVector3f> mPositions; // Vector of vertex positions
|
||||
std::vector<CVector3f> mNormals; // Vector of vertex normals
|
||||
std::vector<CColor> mColors[2]; // Vectors of vertex colors
|
||||
std::vector<CVector2f> mTexCoords[8]; // Vectors of texture coordinates
|
||||
bool mBuffered; // Bool value that indicates whether the attributes have been buffered.
|
||||
|
||||
public:
|
||||
CVertexBuffer();
|
||||
CVertexBuffer(EVertexDescription Desc);
|
||||
~CVertexBuffer();
|
||||
u16 AddVertex(const CVertex& vtx);
|
||||
u16 AddIfUnique(const CVertex& vtx, u16 start);
|
||||
void Reserve(u16 size);
|
||||
void Clear();
|
||||
void Buffer();
|
||||
void Bind();
|
||||
void Unbind();
|
||||
bool IsBuffered();
|
||||
EVertexDescription VertexDesc();
|
||||
void SetVertexDesc(EVertexDescription Desc);
|
||||
u32 Size();
|
||||
GLuint CreateVAO();
|
||||
};
|
||||
|
||||
#endif // CVERTEXBUFFER_H
|
||||
37
src/Core/OpenGL/GLCommon.cpp
Normal file
37
src/Core/OpenGL/GLCommon.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "GLCommon.h"
|
||||
#include <stdexcept>
|
||||
|
||||
GLenum glBlendFactor[] = {
|
||||
GL_ZERO, // GX_BL_ZERO
|
||||
GL_ONE, // GX_BL_ONE
|
||||
GL_SRC_COLOR, // GX_BL_SRCCLR / GX_BL_DSTCLR
|
||||
GL_ONE_MINUS_SRC_COLOR, // GX_BL_INVSRCCLR / GX_BL_INVDSTCLR
|
||||
GL_SRC_ALPHA, // GX_BL_SRCALPHA
|
||||
GL_ONE_MINUS_SRC_ALPHA, // GX_BL_INVSRCALPHA
|
||||
GL_DST_ALPHA, // GX_BL_DSTALPHA
|
||||
GL_ONE_MINUS_DST_ALPHA // GX_BL_INVDSTALPHA
|
||||
};
|
||||
|
||||
|
||||
GLenum glZMode[] = {
|
||||
GL_NEVER, // GX_NEVER
|
||||
GL_LESS, // GX_LESS
|
||||
GL_EQUAL, // GX_EQUAL
|
||||
GL_LEQUAL, // GX_LEQUAL
|
||||
GL_GREATER, // GX_GREATER
|
||||
GL_NOTEQUAL, // GX_NEQUAL
|
||||
GL_ALWAYS // GX_ALWAYS
|
||||
};
|
||||
|
||||
GLenum GXPrimToGLPrim(EGXPrimitiveType t) {
|
||||
switch (t) {
|
||||
case eGX_Quads: return GL_TRIANGLE_STRIP; // Quads are converted to strips
|
||||
case eGX_Triangles: return GL_TRIANGLE_STRIP; // Triangles are converted to strips
|
||||
case eGX_TriangleStrip: return GL_TRIANGLE_STRIP;
|
||||
case eGX_TriangleFan: return GL_TRIANGLE_STRIP; // Fans are converted to strips
|
||||
case eGX_Lines: return GL_LINES;
|
||||
case eGX_LineStrip: return GL_LINE_STRIP;
|
||||
case eGX_Points: return GL_POINTS;
|
||||
default: throw std::invalid_argument("Invalid GX primitive type");
|
||||
}
|
||||
}
|
||||
34
src/Core/OpenGL/GLCommon.h
Normal file
34
src/Core/OpenGL/GLCommon.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef GLCOMMON_H
|
||||
#define GLCOMMON_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
enum EBlendFactor
|
||||
{
|
||||
eBlendZero = GL_ZERO,
|
||||
eBlendOne = GL_ONE,
|
||||
eBlendSrcColor = GL_SRC_COLOR,
|
||||
eBlendInvSrcColor = GL_ONE_MINUS_SRC_COLOR,
|
||||
eBlendSrcAlpha = GL_SRC_ALPHA,
|
||||
eBlendInvSrcAlpha = GL_ONE_MINUS_SRC_ALPHA,
|
||||
eBlendDstAlpha = GL_DST_ALPHA,
|
||||
eBlendInvDstAlpha = GL_ONE_MINUS_DST_ALPHA
|
||||
};
|
||||
|
||||
enum EGXPrimitiveType
|
||||
{
|
||||
eGX_Quads = 0x80,
|
||||
eGX_Triangles = 0x90,
|
||||
eGX_TriangleStrip = 0x98,
|
||||
eGX_TriangleFan = 0xA0,
|
||||
eGX_Lines = 0xA8,
|
||||
eGX_LineStrip = 0xB0,
|
||||
eGX_Points = 0xB8
|
||||
};
|
||||
|
||||
extern GLenum glBlendFactor[];
|
||||
extern GLenum glZMode[];
|
||||
GLenum GXPrimToGLPrim(EGXPrimitiveType t);
|
||||
|
||||
#endif // GLCOMMON_H
|
||||
370
src/Core/Render/CCamera.cpp
Normal file
370
src/Core/Render/CCamera.cpp
Normal file
@@ -0,0 +1,370 @@
|
||||
#include "CCamera.h"
|
||||
#include "CGraphics.h"
|
||||
#include <Common/CQuaternion.h>
|
||||
#include <Common/Math.h>
|
||||
#include <gtc/matrix_transform.hpp>
|
||||
|
||||
CCamera::CCamera()
|
||||
{
|
||||
mMode = eFreeCamera;
|
||||
mPosition = CVector3f(0);
|
||||
mAspectRatio = 1.7777777f;
|
||||
|
||||
mYaw = -Math::skHalfPi;
|
||||
mPitch = 0.0f;
|
||||
SetOrbit(CVector3f(0), 5.f);
|
||||
|
||||
mMoveSpeed = 1.f;
|
||||
mLookSpeed = 1.f;
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mProjectionDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
|
||||
CCamera::CCamera(CVector3f Position, CVector3f /*Target*/)
|
||||
{
|
||||
// todo: make it actually look at the target!
|
||||
// don't actually use this constructor, it's unfinished and won't work properly
|
||||
mMode = eFreeCamera;
|
||||
mMoveSpeed = 1.f;
|
||||
mLookSpeed = 1.f;
|
||||
mPosition = Position;
|
||||
mYaw = -Math::skHalfPi;
|
||||
mPitch = 0.0f;
|
||||
}
|
||||
|
||||
void CCamera::Pan(float XAmount, float YAmount)
|
||||
{
|
||||
if (mMode == eFreeCamera)
|
||||
{
|
||||
mPosition += mRightVector * (XAmount * mMoveSpeed);
|
||||
mPosition += mUpVector * (YAmount * mMoveSpeed);
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
|
||||
else
|
||||
Rotate(-XAmount * 0.3f, YAmount * 0.3f);
|
||||
}
|
||||
|
||||
void CCamera::Rotate(float XAmount, float YAmount)
|
||||
{
|
||||
mYaw -= (XAmount * mLookSpeed * 0.3f);
|
||||
mPitch -= (YAmount * mLookSpeed * 0.3f);
|
||||
ValidatePitch();
|
||||
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
|
||||
void CCamera::Zoom(float Amount)
|
||||
{
|
||||
if (mMode == eFreeCamera)
|
||||
mPosition += mDirection * (Amount * mMoveSpeed);
|
||||
|
||||
else
|
||||
{
|
||||
mOrbitDistance -= Amount * mMoveSpeed;
|
||||
mTransformDirty = true;
|
||||
}
|
||||
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
|
||||
void CCamera::Snap(CVector3f Position)
|
||||
{
|
||||
mPosition = Position;
|
||||
mYaw = -Math::skHalfPi;
|
||||
mPitch = 0.0f;
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
|
||||
void CCamera::ProcessKeyInput(EKeyInputs KeyFlags, double DeltaTime)
|
||||
{
|
||||
float FDeltaTime = (float) DeltaTime;
|
||||
|
||||
if (KeyFlags & eWKey) Zoom(FDeltaTime * 25.f);
|
||||
if (KeyFlags & eSKey) Zoom(-FDeltaTime * 25.f);
|
||||
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) || (MouseFlags & eRightButton))
|
||||
Pan(-XMovement, YMovement);
|
||||
}
|
||||
}
|
||||
|
||||
CRay CCamera::CastRay(CVector2f DeviceCoords) const
|
||||
{
|
||||
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::SetMoveMode(ECameraMoveMode Mode)
|
||||
{
|
||||
mMode = Mode;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
|
||||
if (mMode == eOrbitCamera)
|
||||
mTransformDirty = true;
|
||||
}
|
||||
|
||||
void CCamera::SetOrbit(const CVector3f& OrbitTarget, float Distance)
|
||||
{
|
||||
mOrbitTarget = OrbitTarget;
|
||||
mOrbitDistance = Distance;
|
||||
|
||||
if (mMode == eOrbitCamera)
|
||||
{
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::SetOrbit(const CAABox& OrbitTarget, float DistScale /*= 4.f*/)
|
||||
{
|
||||
CVector3f Min = OrbitTarget.Min();
|
||||
CVector3f Max = OrbitTarget.Max();
|
||||
|
||||
mOrbitTarget = OrbitTarget.Center();
|
||||
|
||||
// Find largest extent
|
||||
CVector3f Extent = (Max - Min) / 2.f;
|
||||
float Dist = 0.f;
|
||||
|
||||
if (Extent.x >= Extent.y && Extent.x >= Extent.z) Dist = Extent.x;
|
||||
else if (Extent.y >= Extent.x && Extent.y >= Extent.z) Dist = Extent.y;
|
||||
else Dist = Extent.z;
|
||||
|
||||
mOrbitDistance = Dist * DistScale;
|
||||
|
||||
if (mMode == eOrbitCamera)
|
||||
{
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::SetOrbitDistance(float Distance)
|
||||
{
|
||||
mOrbitDistance = Distance;
|
||||
|
||||
if (mMode == eOrbitCamera)
|
||||
{
|
||||
mTransformDirty = true;
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::LoadMatrices() const
|
||||
{
|
||||
CGraphics::sMVPBlock.ViewMatrix = ViewMatrix();
|
||||
CGraphics::sMVPBlock.ProjectionMatrix = ProjectionMatrix();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
CVector3f CCamera::Position() const
|
||||
{
|
||||
UpdateTransform();
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
CVector3f CCamera::Direction() const
|
||||
{
|
||||
UpdateTransform();
|
||||
return mDirection;
|
||||
}
|
||||
|
||||
CVector3f CCamera::UpVector() const
|
||||
{
|
||||
UpdateTransform();
|
||||
return mUpVector;
|
||||
}
|
||||
|
||||
CVector3f CCamera::RightVector() const
|
||||
{
|
||||
UpdateTransform();
|
||||
return mRightVector;
|
||||
}
|
||||
|
||||
float CCamera::Yaw() const
|
||||
{
|
||||
return mYaw;
|
||||
}
|
||||
|
||||
float CCamera::Pitch() const
|
||||
{
|
||||
return mPitch;
|
||||
}
|
||||
|
||||
float CCamera::FieldOfView() const
|
||||
{
|
||||
return 55.f;
|
||||
}
|
||||
|
||||
ECameraMoveMode CCamera::MoveMode() const
|
||||
{
|
||||
return mMode;
|
||||
}
|
||||
|
||||
const CMatrix4f& CCamera::ViewMatrix() const
|
||||
{
|
||||
UpdateView();
|
||||
return mViewMatrix;
|
||||
}
|
||||
|
||||
const CMatrix4f& CCamera::ProjectionMatrix() const
|
||||
{
|
||||
UpdateProjection();
|
||||
return mProjectionMatrix;
|
||||
}
|
||||
|
||||
const CFrustumPlanes& CCamera::FrustumPlanes() const
|
||||
{
|
||||
UpdateFrustum();
|
||||
return mFrustumPlanes;
|
||||
}
|
||||
|
||||
// ************ SETTERS ************
|
||||
void CCamera::SetYaw(float Yaw)
|
||||
{
|
||||
mYaw = Yaw;
|
||||
mTransformDirty = true;
|
||||
}
|
||||
|
||||
void CCamera::SetPitch(float Pitch)
|
||||
{
|
||||
mPitch = Pitch;
|
||||
ValidatePitch();
|
||||
mTransformDirty = true;
|
||||
}
|
||||
|
||||
void CCamera::SetMoveSpeed(float MoveSpeed)
|
||||
{
|
||||
mMoveSpeed = MoveSpeed;
|
||||
}
|
||||
|
||||
void CCamera::SetLookSpeed(float LookSpeed)
|
||||
{
|
||||
mLookSpeed = LookSpeed;
|
||||
}
|
||||
|
||||
void CCamera::SetAspectRatio(float AspectRatio)
|
||||
{
|
||||
mAspectRatio = AspectRatio;
|
||||
mProjectionDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CCamera::ValidatePitch()
|
||||
{
|
||||
// This function mainly just exists to ensure the camera doesn't flip upside down
|
||||
if (mPitch > Math::skHalfPi) mPitch = Math::skHalfPi;
|
||||
if (mPitch < -Math::skHalfPi) mPitch = -Math::skHalfPi;
|
||||
}
|
||||
|
||||
void CCamera::UpdateTransform() const
|
||||
{
|
||||
// Transform should be marked dirty when pitch, yaw, or orbit target/distance are changed
|
||||
if (mTransformDirty)
|
||||
{
|
||||
mDirection = CVector3f(
|
||||
cos(mPitch) * cos(mYaw),
|
||||
cos(mPitch) * sin(mYaw),
|
||||
sin(mPitch)
|
||||
);
|
||||
|
||||
mRightVector = CVector3f(
|
||||
cos(mYaw - Math::skHalfPi),
|
||||
sin(mYaw - Math::skHalfPi),
|
||||
0
|
||||
);
|
||||
|
||||
mUpVector = mRightVector.Cross(mDirection);
|
||||
|
||||
// Update position
|
||||
if (mMode == eOrbitCamera)
|
||||
{
|
||||
if (mOrbitDistance < 1.f) mOrbitDistance = 1.f;
|
||||
mPosition = mOrbitTarget + (mDirection * -mOrbitDistance);
|
||||
}
|
||||
|
||||
mViewDirty = true;
|
||||
mFrustumPlanesDirty = true;
|
||||
mTransformDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::UpdateView() const
|
||||
{
|
||||
// todo: don't use glm
|
||||
UpdateTransform();
|
||||
|
||||
if (mViewDirty)
|
||||
{
|
||||
glm::vec3 glmpos(mPosition.x, mPosition.y, mPosition.z);
|
||||
glm::vec3 glmdir(mDirection.x, mDirection.y, mDirection.z);
|
||||
glm::vec3 glmup(mUpVector.x, mUpVector.y, mUpVector.z);
|
||||
mViewMatrix = CMatrix4f::FromGlmMat4(glm::lookAt(glmpos, glmpos + glmdir, glmup)).Transpose();
|
||||
mViewDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::UpdateProjection() const
|
||||
{
|
||||
if (mProjectionDirty)
|
||||
{
|
||||
mProjectionMatrix = Math::PerspectiveMatrix(55.f, mAspectRatio, 0.1f, 4096.f);
|
||||
mProjectionDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CCamera::UpdateFrustum() const
|
||||
{
|
||||
UpdateTransform();
|
||||
|
||||
if (mFrustumPlanesDirty)
|
||||
{
|
||||
mFrustumPlanes.SetPlanes(mPosition, mDirection, 55.f, mAspectRatio, 0.1f, 4096.f);
|
||||
mFrustumPlanesDirty = false;
|
||||
}
|
||||
}
|
||||
99
src/Core/Render/CCamera.h
Normal file
99
src/Core/Render/CCamera.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef CCAMERA_H
|
||||
#define CCAMERA_H
|
||||
|
||||
#include "CFrustumPlanes.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
|
||||
};
|
||||
|
||||
/* This class uses a lot of mutable members as an optimization so that they can
|
||||
* be updated as infrequently as possible (eg only when the values are requested
|
||||
* the next time after changes are made) while still always returning the correct
|
||||
* value via the const get functions. They are not modified in const functions
|
||||
* beyond ensuring that all data is valid and synced with everything else (eg
|
||||
* mPosition is only modified to ensure it's correct in orbit mode given the
|
||||
* target/distance/pitch/yaw; it won't be modified as a camera snap in a const
|
||||
* function). */
|
||||
class CCamera
|
||||
{
|
||||
ECameraMoveMode mMode;
|
||||
mutable CVector3f mPosition;
|
||||
mutable CVector3f mDirection;
|
||||
mutable CVector3f mRightVector;
|
||||
mutable CVector3f mUpVector;
|
||||
float mAspectRatio;
|
||||
|
||||
float mYaw;
|
||||
float mPitch;
|
||||
CVector3f mOrbitTarget;
|
||||
mutable float mOrbitDistance;
|
||||
float mMoveSpeed;
|
||||
float mLookSpeed;
|
||||
|
||||
mutable CMatrix4f mViewMatrix;
|
||||
mutable CMatrix4f mProjectionMatrix;
|
||||
mutable CFrustumPlanes mFrustumPlanes;
|
||||
|
||||
mutable bool mTransformDirty;
|
||||
mutable bool mViewDirty;
|
||||
mutable bool mProjectionDirty;
|
||||
mutable bool mFrustumPlanesDirty;
|
||||
|
||||
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) const;
|
||||
void LoadMatrices() const;
|
||||
|
||||
void SetMoveMode(ECameraMoveMode Mode);
|
||||
void SetOrbit(const CVector3f& OrbitTarget, float Distance);
|
||||
void SetOrbit(const CAABox& OrbitTarget, float DistScale = 4.f);
|
||||
void SetOrbitDistance(float Distance);
|
||||
|
||||
// Getters
|
||||
CVector3f Position() const;
|
||||
CVector3f Direction() const;
|
||||
CVector3f UpVector() const;
|
||||
CVector3f RightVector() const;
|
||||
float Yaw() const;
|
||||
float Pitch() const;
|
||||
float FieldOfView() const;
|
||||
ECameraMoveMode MoveMode() const;
|
||||
const CMatrix4f& ViewMatrix() const;
|
||||
const CMatrix4f& ProjectionMatrix() const;
|
||||
const CFrustumPlanes& FrustumPlanes() const;
|
||||
|
||||
// Setters
|
||||
void SetYaw(float Yaw);
|
||||
void SetPitch(float Pitch);
|
||||
void SetMoveSpeed(float MoveSpeed);
|
||||
void SetLookSpeed(float LookSpeed);
|
||||
void SetAspectRatio(float AspectRatio);
|
||||
|
||||
// Private
|
||||
private:
|
||||
void ValidatePitch();
|
||||
void UpdateTransform() const;
|
||||
void UpdateView() const;
|
||||
void UpdateProjection() const;
|
||||
void UpdateFrustum() const;
|
||||
};
|
||||
|
||||
#endif // CCAMERA_H
|
||||
578
src/Core/Render/CDrawUtil.cpp
Normal file
578
src/Core/Render/CDrawUtil.cpp
Normal file
@@ -0,0 +1,578 @@
|
||||
#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;
|
||||
|
||||
TResPtr<CModel> CDrawUtil::mpCubeModel;
|
||||
|
||||
CVertexBuffer CDrawUtil::mWireCubeVertices;
|
||||
CIndexBuffer CDrawUtil::mWireCubeIndices;
|
||||
|
||||
TResPtr<CModel> CDrawUtil::mpSphereModel;
|
||||
TResPtr<CModel> CDrawUtil::mpDoubleSidedSphereModel;
|
||||
|
||||
TResPtr<CModel> CDrawUtil::mpWireSphereModel;
|
||||
|
||||
CShader *CDrawUtil::mpColorShader;
|
||||
CShader *CDrawUtil::mpColorShaderLighting;
|
||||
CShader *CDrawUtil::mpBillboardShader;
|
||||
CShader *CDrawUtil::mpLightBillboardShader;
|
||||
CShader *CDrawUtil::mpTextureShader;
|
||||
CShader *CDrawUtil::mpCollisionShader;
|
||||
CShader *CDrawUtil::mpTextShader;
|
||||
|
||||
TResPtr<CTexture> CDrawUtil::mpCheckerTexture;
|
||||
|
||||
TResPtr<CTexture> CDrawUtil::mpLightTextures[4];
|
||||
TResPtr<CTexture> CDrawUtil::mpLightMasks[4];
|
||||
|
||||
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 CVector2f& PointA, const CVector2f& PointB)
|
||||
{
|
||||
// Overload for 2D lines
|
||||
DrawLine(CVector3f(PointA.x, PointA.y, 0.f), CVector3f(PointB.x, PointB.y, 0.f), CColor::skWhite);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawLine(const CVector3f& PointA, const CVector3f& PointB, const CColor& LineColor)
|
||||
{
|
||||
Init();
|
||||
|
||||
// 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::DrawLine(const CVector2f& PointA, const CVector2f& PointB, const CColor& LineColor)
|
||||
{
|
||||
// Overload for 2D lines
|
||||
DrawLine(CVector3f(PointA.x, PointA.y, 0.f), CVector3f(PointB.x, PointB.y, 0.f), LineColor);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawCube()
|
||||
{
|
||||
Init();
|
||||
mpCubeModel->Draw(eNoMaterialSetup, 0);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawCube(const CColor& Color)
|
||||
{
|
||||
Init();
|
||||
UseColorShader(Color);
|
||||
DrawCube();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawCube(const CVector3f& Position, const CColor& Color)
|
||||
{
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Position).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
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.Size());
|
||||
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::DrawWireSphere(const CVector3f& Position, float Radius, const CColor& Color /*= CColor::skWhite*/)
|
||||
{
|
||||
Init();
|
||||
|
||||
// Create model matrix
|
||||
CTransform4f Transform;
|
||||
Transform.Scale(Radius);
|
||||
Transform.Translate(Position);
|
||||
CGraphics::sMVPBlock.ModelMatrix = Transform.ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Set other render params
|
||||
UseColorShader(Color);
|
||||
CMaterial::KillCachedMaterial();
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// Draw
|
||||
mpWireSphereModel->Draw(eNoMaterialSetup, 0);
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawBillboard(CTexture* pTexture, const CVector3f& Position, const CVector2f& Scale /*= CVector2f::skOne*/, const CColor& Tint /*= CColor::skWhite*/)
|
||||
{
|
||||
Init();
|
||||
|
||||
// Create translation-only model matrix
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Position).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Set uniforms
|
||||
mpBillboardShader->SetCurrent();
|
||||
|
||||
GLuint ScaleLoc = mpBillboardShader->GetUniformLocation("BillboardScale");
|
||||
glUniform2f(ScaleLoc, Scale.x, Scale.y);
|
||||
|
||||
GLuint TintLoc = mpBillboardShader->GetUniformLocation("TintColor");
|
||||
CVector4f Tint4f = Tint.ToVector4f();
|
||||
glUniform4f(TintLoc, Tint4f.x, Tint4f.y, Tint4f.z, Tint4f.w);
|
||||
|
||||
pTexture->Bind(0);
|
||||
|
||||
// Set other properties
|
||||
CMaterial::KillCachedMaterial();
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// Draw
|
||||
DrawSquare();
|
||||
}
|
||||
|
||||
void CDrawUtil::DrawLightBillboard(ELightType Type, const CColor& LightColor, const CVector3f& Position, const CVector2f& Scale /*= CVector2f::skOne*/, const CColor& Tint /*= CColor::skWhite*/)
|
||||
{
|
||||
Init();
|
||||
|
||||
// Create translation-only model matrix
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Position).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Set uniforms
|
||||
mpLightBillboardShader->SetCurrent();
|
||||
|
||||
GLuint ScaleLoc = mpLightBillboardShader->GetUniformLocation("BillboardScale");
|
||||
glUniform2f(ScaleLoc, Scale.x, Scale.y);
|
||||
|
||||
GLuint ColorLoc = mpLightBillboardShader->GetUniformLocation("LightColor");
|
||||
CVector4f Color4f = LightColor.ToVector4f();
|
||||
glUniform4f(ColorLoc, Color4f.x, Color4f.y, Color4f.z, Color4f.w);
|
||||
|
||||
GLuint TintLoc = mpLightBillboardShader->GetUniformLocation("TintColor");
|
||||
CVector4f Tint4f = Tint.ToVector4f();
|
||||
glUniform4f(TintLoc, Tint4f.x, Tint4f.y, Tint4f.z, Tint4f.w);
|
||||
|
||||
CTexture *pTexA = GetLightTexture(Type);
|
||||
CTexture *pTexB = GetLightMask(Type);
|
||||
pTexA->Bind(0);
|
||||
pTexB->Bind(1);
|
||||
|
||||
GLuint TextureLoc = mpLightBillboardShader->GetUniformLocation("Texture");
|
||||
GLuint MaskLoc = mpLightBillboardShader->GetUniformLocation("LightMask");
|
||||
glUniform1i(TextureLoc, 0);
|
||||
glUniform1i(MaskLoc, 1);
|
||||
|
||||
// Set other properties
|
||||
CMaterial::KillCachedMaterial();
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// Draw
|
||||
DrawSquare();
|
||||
|
||||
}
|
||||
|
||||
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(const CColor& TintColor /*= CColor::skWhite*/)
|
||||
{
|
||||
Init();
|
||||
mpCollisionShader->SetCurrent();
|
||||
LoadCheckerboardTexture(0);
|
||||
|
||||
GLuint TintColorLoc = mpCollisionShader->GetUniformLocation("TintColor");
|
||||
CVector4f Tint4f = TintColor.ToVector4f();
|
||||
glUniform4f(TintColorLoc, Tint4f.x, Tint4f.y, Tint4f.z, Tint4f.w);
|
||||
|
||||
CMaterial::KillCachedMaterial();
|
||||
}
|
||||
|
||||
CShader* CDrawUtil::GetTextShader()
|
||||
{
|
||||
Init();
|
||||
return mpTextShader;
|
||||
}
|
||||
|
||||
void CDrawUtil::LoadCheckerboardTexture(u32 GLTextureUnit)
|
||||
{
|
||||
Init();
|
||||
mpCheckerTexture->Bind(GLTextureUnit);
|
||||
}
|
||||
|
||||
CTexture* CDrawUtil::GetLightTexture(ELightType Type)
|
||||
{
|
||||
Init();
|
||||
return mpLightTextures[Type];
|
||||
}
|
||||
|
||||
CTexture* CDrawUtil::GetLightMask(ELightType Type)
|
||||
{
|
||||
Init();
|
||||
return mpLightMasks[Type];
|
||||
}
|
||||
|
||||
CModel* CDrawUtil::GetCubeModel()
|
||||
{
|
||||
Init();
|
||||
return mpCubeModel;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
CDrawUtil::CDrawUtil()
|
||||
{
|
||||
}
|
||||
|
||||
void CDrawUtil::Init()
|
||||
{
|
||||
if (!mDrawUtilInitialized)
|
||||
{
|
||||
Log::Write("Initializing CDrawUtil");
|
||||
InitGrid();
|
||||
InitSquare();
|
||||
InitLine();
|
||||
InitCube();
|
||||
InitWireCube();
|
||||
InitSphere();
|
||||
InitWireSphere();
|
||||
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 = gResCache.GetResource("../resources/Cube.cmdl");
|
||||
}
|
||||
|
||||
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 = gResCache.GetResource("../resources/Sphere.cmdl");
|
||||
mpDoubleSidedSphereModel = gResCache.GetResource("../resources/SphereDoubleSided.cmdl");
|
||||
}
|
||||
|
||||
void CDrawUtil::InitWireSphere()
|
||||
{
|
||||
Log::Write("Creating wire sphere");
|
||||
mpWireSphereModel = gResCache.GetResource("../resources/WireSphere.cmdl");
|
||||
}
|
||||
|
||||
void CDrawUtil::InitShaders()
|
||||
{
|
||||
Log::Write("Creating shaders");
|
||||
mpColorShader = CShader::FromResourceFile("ColorShader");
|
||||
mpColorShaderLighting = CShader::FromResourceFile("ColorShaderLighting");
|
||||
mpBillboardShader = CShader::FromResourceFile("BillboardShader");
|
||||
mpLightBillboardShader = CShader::FromResourceFile("LightBillboardShader");
|
||||
mpTextureShader = CShader::FromResourceFile("TextureShader");
|
||||
mpCollisionShader = CShader::FromResourceFile("CollisionShader");
|
||||
mpTextShader = CShader::FromResourceFile("TextShader");
|
||||
}
|
||||
|
||||
void CDrawUtil::InitTextures()
|
||||
{
|
||||
Log::Write("Loading textures");
|
||||
mpCheckerTexture = gResCache.GetResource("../resources/Checkerboard.txtr");
|
||||
|
||||
mpLightTextures[0] = gResCache.GetResource("../resources/LightAmbient.txtr");
|
||||
mpLightTextures[1] = gResCache.GetResource("../resources/LightDirectional.txtr");
|
||||
mpLightTextures[2] = gResCache.GetResource("../resources/LightCustom.txtr");
|
||||
mpLightTextures[3] = gResCache.GetResource("../resources/LightSpot.txtr");
|
||||
|
||||
mpLightMasks[0] = gResCache.GetResource("../resources/LightAmbientMask.txtr");
|
||||
mpLightMasks[1] = gResCache.GetResource("../resources/LightDirectionalMask.txtr");
|
||||
mpLightMasks[2] = gResCache.GetResource("../resources/LightCustomMask.txtr");
|
||||
mpLightMasks[3] = gResCache.GetResource("../resources/LightSpotMask.txtr");
|
||||
}
|
||||
|
||||
void CDrawUtil::Shutdown()
|
||||
{
|
||||
if (mDrawUtilInitialized)
|
||||
{
|
||||
Log::Write("Shutting down");
|
||||
delete mpColorShader;
|
||||
delete mpColorShaderLighting;
|
||||
delete mpTextureShader;
|
||||
delete mpCollisionShader;
|
||||
delete mpTextShader;
|
||||
mDrawUtilInitialized = false;
|
||||
}
|
||||
}
|
||||
118
src/Core/Render/CDrawUtil.h
Normal file
118
src/Core/Render/CDrawUtil.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef CDRAWUTIL
|
||||
#define CDRAWUTIL
|
||||
|
||||
#include <OpenGL/CVertexBuffer.h>
|
||||
#include <OpenGL/CDynamicVertexBuffer.h>
|
||||
#include <OpenGL/CIndexBuffer.h>
|
||||
#include <Resource/model/CModel.h>
|
||||
#include <Resource/CLight.h>
|
||||
|
||||
// todo: CDrawUtil should work with CRenderer to queue primitives for rendering
|
||||
// rather than trying to draw them straight away, so that CDrawUtil functions can
|
||||
// be called from anywhere in the codebase and still function correctly
|
||||
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 TResPtr<CModel> mpCubeModel;
|
||||
|
||||
// Wire Cube
|
||||
static CVertexBuffer mWireCubeVertices;
|
||||
static CIndexBuffer mWireCubeIndices;
|
||||
|
||||
// Sphere
|
||||
static TResPtr<CModel> mpSphereModel;
|
||||
static TResPtr<CModel> mpDoubleSidedSphereModel;
|
||||
|
||||
// Wire Sphere
|
||||
static TResPtr<CModel> mpWireSphereModel;
|
||||
|
||||
// Shaders
|
||||
static CShader *mpColorShader;
|
||||
static CShader *mpColorShaderLighting;
|
||||
static CShader *mpBillboardShader;
|
||||
static CShader *mpLightBillboardShader;
|
||||
static CShader *mpTextureShader;
|
||||
static CShader *mpCollisionShader;
|
||||
static CShader *mpTextShader;
|
||||
|
||||
// Textures
|
||||
static TResPtr<CTexture> mpCheckerTexture;
|
||||
|
||||
static TResPtr<CTexture> mpLightTextures[4];
|
||||
static TResPtr<CTexture> mpLightMasks[4];
|
||||
|
||||
// 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 CVector2f& PointA, const CVector2f& PointB);
|
||||
static void DrawLine(const CVector3f& PointA, const CVector3f& PointB, const CColor& LineColor);
|
||||
static void DrawLine(const CVector2f& PointA, const CVector2f& PointB, const CColor& LineColor);
|
||||
|
||||
static void DrawCube();
|
||||
static void DrawCube(const CColor& Color);
|
||||
static void DrawCube(const CVector3f& Position, 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 DrawWireSphere(const CVector3f& Position, float Radius, const CColor& Color = CColor::skWhite);
|
||||
|
||||
static void DrawBillboard(CTexture* pTexture, const CVector3f& Position, const CVector2f& Scale = CVector2f::skOne, const CColor& Tint = CColor::skWhite);
|
||||
|
||||
static void DrawLightBillboard(ELightType Type, const CColor& LightColor, const CVector3f& Position, const CVector2f& Scale = CVector2f::skOne, const CColor& Tint = CColor::skWhite);
|
||||
|
||||
static void UseColorShader(const CColor& Color);
|
||||
static void UseColorShaderLighting(const CColor& Color);
|
||||
static void UseTextureShader();
|
||||
static void UseTextureShader(const CColor& TintColor);
|
||||
static void UseCollisionShader(const CColor& TintColor = CColor::skWhite);
|
||||
|
||||
static CShader* GetTextShader();
|
||||
static void LoadCheckerboardTexture(u32 GLTextureUnit);
|
||||
static CTexture* GetLightTexture(ELightType Type);
|
||||
static CTexture* GetLightMask(ELightType Type);
|
||||
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 InitWireSphere();
|
||||
static void InitShaders();
|
||||
static void InitTextures();
|
||||
|
||||
public:
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
#endif // CDRAWUTIL
|
||||
|
||||
178
src/Core/Render/CGraphics.cpp
Normal file
178
src/Core/Render/CGraphics.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#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 = eWorldLighting;
|
||||
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();
|
||||
UpdateLightBlock();
|
||||
|
||||
sVertexBlock.COLOR0_Amb = CColor::skGray.ToVector4f();
|
||||
UpdateVertexBlock();
|
||||
}
|
||||
|
||||
void CGraphics::SetupAmbientColor()
|
||||
{
|
||||
if (sLightMode == eWorldLighting)
|
||||
sVertexBlock.COLOR0_Amb = sAreaAmbientColor.ToVector4f() * sWorldLightMultiplier;
|
||||
else
|
||||
sVertexBlock.COLOR0_Amb = skDefaultAmbientColor.ToVector4f();
|
||||
}
|
||||
|
||||
void CGraphics::SetIdentityMVP()
|
||||
{
|
||||
sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||
sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
|
||||
sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
|
||||
}
|
||||
99
src/Core/Render/CGraphics.h
Normal file
99
src/Core/Render/CGraphics.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#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 { eNoLighting, eBasicLighting, eWorldLighting };
|
||||
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();
|
||||
static void SetupAmbientColor();
|
||||
static void SetIdentityMVP();
|
||||
};
|
||||
|
||||
#endif // CGRAPHICS_H
|
||||
89
src/Core/Render/CRenderBucket.cpp
Normal file
89
src/Core/Render/CRenderBucket.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "CRenderBucket.h"
|
||||
#include <algorithm>
|
||||
#include "CDrawUtil.h"
|
||||
#include "CGraphics.h"
|
||||
#include "CRenderer.h"
|
||||
|
||||
CRenderBucket::CRenderBucket()
|
||||
{
|
||||
mEstSize = 0;
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
void CRenderBucket::SetSortType(ESortType Type)
|
||||
{
|
||||
mSortType = Type;
|
||||
}
|
||||
|
||||
void CRenderBucket::Add(const SRenderablePtr& ptr)
|
||||
{
|
||||
if (mSize >= mEstSize)
|
||||
mRenderables.push_back(ptr);
|
||||
else
|
||||
mRenderables[mSize] = ptr;
|
||||
|
||||
mSize++;
|
||||
}
|
||||
|
||||
void CRenderBucket::Sort(CCamera* pCamera)
|
||||
{
|
||||
struct {
|
||||
CCamera *pCamera;
|
||||
bool operator()(SRenderablePtr left, SRenderablePtr right) {
|
||||
CVector3f cPos = pCamera->Position();
|
||||
CVector3f cDir = pCamera->Direction();
|
||||
|
||||
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 = pCamera;
|
||||
|
||||
if (mSortType == BackToFront)
|
||||
std::stable_sort(mRenderables.begin(), mRenderables.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 (mRenderables.size() > mSize) mRenderables.resize(mSize);
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
void CRenderBucket::Draw(const SViewInfo& ViewInfo)
|
||||
{
|
||||
ERenderOptions Options = ViewInfo.pRenderer->RenderOptions();
|
||||
|
||||
for (u32 n = 0; n < mSize; n++)
|
||||
{
|
||||
if (mRenderables[n].Command == eDrawMesh)
|
||||
mRenderables[n].pRenderable->Draw(Options, mRenderables[n].ComponentIndex, ViewInfo);
|
||||
|
||||
else if (mRenderables[n].Command == eDrawSelection)
|
||||
mRenderables[n].pRenderable->DrawSelection();
|
||||
|
||||
// todo: implementation for eDrawExtras
|
||||
}
|
||||
}
|
||||
33
src/Core/Render/CRenderBucket.h
Normal file
33
src/Core/Render/CRenderBucket.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef CRENDERBUCKET_H
|
||||
#define CRENDERBUCKET_H
|
||||
|
||||
#include "CCamera.h"
|
||||
#include "ERenderOptions.h"
|
||||
#include "SRenderablePtr.h"
|
||||
#include <Common/types.h>
|
||||
#include <vector>
|
||||
|
||||
class CRenderBucket
|
||||
{
|
||||
public:
|
||||
enum ESortType
|
||||
{
|
||||
BackToFront,
|
||||
FrontToBack
|
||||
};
|
||||
private:
|
||||
ESortType mSortType;
|
||||
std::vector<SRenderablePtr> mRenderables;
|
||||
u32 mEstSize;
|
||||
u32 mSize;
|
||||
|
||||
public:
|
||||
CRenderBucket();
|
||||
void SetSortType(ESortType Type);
|
||||
void Add(const SRenderablePtr& ptr);
|
||||
void Sort(CCamera* pCamera);
|
||||
void Clear();
|
||||
void Draw(const SViewInfo& ViewInfo);
|
||||
};
|
||||
|
||||
#endif // CRENDERBUCKET_H
|
||||
388
src/Core/Render/CRenderer.cpp
Normal file
388
src/Core/Render/CRenderer.cpp
Normal file
@@ -0,0 +1,388 @@
|
||||
#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 = eDrawWorld | eDrawObjects | eDrawLights | eDrawSky |
|
||||
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 ************
|
||||
ERenderOptions CRenderer::RenderOptions() const
|
||||
{
|
||||
return mOptions;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleWorld(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawWorld;
|
||||
else mOptions &= ~eDrawWorld;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleWorldCollision(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawWorldCollision;
|
||||
else mOptions &= ~eDrawWorldCollision;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleObjects(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawObjects;
|
||||
else mOptions &= ~eDrawObjects;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleObjectCollision(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawObjectCollision;
|
||||
else mOptions &= ~eDrawObjectCollision;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleLights(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawLights;
|
||||
else mOptions &= ~eDrawLights;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleSky(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawSky;
|
||||
else mOptions &= ~eDrawSky;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleBackfaceCull(bool b)
|
||||
{
|
||||
if (b) mOptions |= eEnableBackfaceCull;
|
||||
else mOptions &= ~eEnableBackfaceCull;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleUVAnimation(bool b)
|
||||
{
|
||||
if (b) mOptions |= eEnableUVScroll;
|
||||
else mOptions &= ~eEnableUVScroll;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleGrid(bool b)
|
||||
{
|
||||
mDrawGrid = b;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleOccluders(bool b)
|
||||
{
|
||||
if (b) mOptions |= eEnableOccluders;
|
||||
else mOptions &= ~eEnableOccluders;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleAlphaDisabled(bool b)
|
||||
{
|
||||
if (b) mOptions |= eNoAlpha;
|
||||
else mOptions &= ~eNoAlpha;
|
||||
}
|
||||
|
||||
void CRenderer::SetBloom(EBloomMode BloomMode)
|
||||
{
|
||||
mBloomMode = BloomMode;
|
||||
|
||||
if (BloomMode != eNoBloom)
|
||||
mOptions |= eEnableBloom;
|
||||
else
|
||||
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::RenderBuckets(const SViewInfo& ViewInfo)
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
mSceneFramebuffer.Bind();
|
||||
|
||||
// Set backface culling
|
||||
if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE);
|
||||
else glDisable(GL_CULL_FACE);
|
||||
|
||||
// Render scene to texture
|
||||
glDepthRange(0.f, 1.f);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
mOpaqueBucket.Draw(ViewInfo);
|
||||
mOpaqueBucket.Clear();
|
||||
mTransparentBucket.Sort(ViewInfo.pCamera);
|
||||
mTransparentBucket.Draw(ViewInfo);
|
||||
mTransparentBucket.Clear();
|
||||
}
|
||||
|
||||
void CRenderer::RenderBloom()
|
||||
{
|
||||
// Check to ensure bloom is enabled
|
||||
if (mBloomMode == eNoBloom) return;
|
||||
|
||||
// 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) };
|
||||
|
||||
u32 BloomWidth = (mBloomMode == eBloom ? mBloomWidth : mViewportWidth);
|
||||
u32 BloomHeight = (mBloomMode == eBloom ? mBloomHeight : mViewportHeight);
|
||||
float BloomHScale = (mBloomMode == eBloom ? mBloomHScale : 0);
|
||||
float BloomVScale = (mBloomMode == eBloom ? mBloomVScale : 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, BloomWidth, BloomHeight);
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
CGraphics::SetIdentityMVP();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
// Pass 1: Alpha-blend the scene texture on a black background
|
||||
mBloomFramebuffers[0].Resize(BloomWidth, BloomHeight);
|
||||
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(BloomWidth, BloomHeight);
|
||||
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] * BloomHScale, 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(BloomWidth, BloomHeight);
|
||||
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] * BloomVScale, 0.f);
|
||||
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Translate).ToMatrix4f();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
CDrawUtil::DrawSquare();
|
||||
}
|
||||
|
||||
// Render result onto main scene framebuffer
|
||||
mSceneFramebuffer.Bind();
|
||||
glViewport(0, 0, mViewportWidth, mViewportHeight);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
||||
|
||||
CGraphics::SetIdentityMVP();
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
CDrawUtil::UseTextureShader();
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
mBloomFramebuffers[2].Texture()->Bind(0);
|
||||
CDrawUtil::DrawSquare();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void CRenderer::RenderSky(CModel *pSkyboxModel, const SViewInfo& ViewInfo)
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
if (!pSkyboxModel) return;
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||
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::sPixelBlock.TintColor = CColor::skWhite.ToVector4f();
|
||||
CGraphics::sNumLights = 0;
|
||||
CGraphics::UpdateVertexBlock();
|
||||
CGraphics::UpdatePixelBlock();
|
||||
CGraphics::UpdateLightBlock();
|
||||
|
||||
// Load rotation-only view matrix
|
||||
CGraphics::sMVPBlock.ViewMatrix = ViewInfo.RotationOnlyViewMatrix;
|
||||
CGraphics::UpdateMVPBlock();
|
||||
|
||||
glDepthRange(1.f, 1.f);
|
||||
pSkyboxModel->Draw(mOptions, 0);
|
||||
}
|
||||
|
||||
void CRenderer::AddOpaqueMesh(IRenderable *pRenderable, int AssetID, CAABox& AABox, ERenderCommand Command)
|
||||
{
|
||||
SRenderablePtr ptr;
|
||||
ptr.pRenderable = pRenderable;
|
||||
ptr.ComponentIndex = AssetID;
|
||||
ptr.AABox = AABox;
|
||||
ptr.Command = Command;
|
||||
mOpaqueBucket.Add(ptr);
|
||||
}
|
||||
|
||||
void CRenderer::AddTransparentMesh(IRenderable *pRenderable, int AssetID, CAABox& AABox, ERenderCommand Command)
|
||||
{
|
||||
SRenderablePtr ptr;
|
||||
ptr.pRenderable = pRenderable;
|
||||
ptr.ComponentIndex = AssetID;
|
||||
ptr.AABox = AABox;
|
||||
ptr.Command = Command;
|
||||
mTransparentBucket.Add(ptr);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void CRenderer::EndFrame()
|
||||
{
|
||||
// Render result to screen
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mDefaultFramebuffer);
|
||||
InitFramebuffer();
|
||||
glViewport(0, 0, mViewportWidth, mViewportHeight);
|
||||
|
||||
CGraphics::SetIdentityMVP();
|
||||
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();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
gDrawCount = 0;
|
||||
}
|
||||
|
||||
void CRenderer::ClearDepthBuffer()
|
||||
{
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// ************ 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;
|
||||
91
src/Core/Render/CRenderer.h
Normal file
91
src/Core/Render/CRenderer.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#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 "SRenderablePtr.h"
|
||||
#include "SViewInfo.h"
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/CColor.h>
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <Common/types.h>
|
||||
#include <OpenGL/CFramebuffer.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, eFakeBloom
|
||||
};
|
||||
|
||||
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
|
||||
ERenderOptions RenderOptions() const;
|
||||
void ToggleWorld(bool b);
|
||||
void ToggleWorldCollision(bool b);
|
||||
void ToggleObjects(bool b);
|
||||
void ToggleObjectCollision(bool b);
|
||||
void ToggleLights(bool b);
|
||||
void ToggleSky(bool b);
|
||||
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 RenderBuckets(const SViewInfo& ViewInfo);
|
||||
void RenderBloom();
|
||||
void RenderSky(CModel *pSkyboxModel, const SViewInfo& ViewInfo);
|
||||
void AddOpaqueMesh(IRenderable *pRenderable, int AssetID, CAABox& AABox, ERenderCommand Command);
|
||||
void AddTransparentMesh(IRenderable *pRenderable, int AssetID, CAABox& AABox, ERenderCommand Command);
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
void ClearDepthBuffer();
|
||||
|
||||
// Private
|
||||
private:
|
||||
void InitFramebuffer();
|
||||
};
|
||||
|
||||
extern u32 gDrawCount;
|
||||
|
||||
#endif // RENDERMANAGER_H
|
||||
11
src/Core/Render/ERenderCommand.h
Normal file
11
src/Core/Render/ERenderCommand.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef ERENDERCOMMAND
|
||||
#define ERENDERCOMMAND
|
||||
|
||||
enum ERenderCommand
|
||||
{
|
||||
eDrawMesh,
|
||||
eDrawSelection
|
||||
};
|
||||
|
||||
#endif // ERENDERCOMMAND
|
||||
|
||||
25
src/Core/Render/ERenderOptions.h
Normal file
25
src/Core/Render/ERenderOptions.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef ERENDEROPTIONS
|
||||
#define ERENDEROPTIONS
|
||||
|
||||
#include <Common/EnumUtil.h>
|
||||
|
||||
enum ERenderOptions
|
||||
{
|
||||
eNoRenderOptions = 0x0,
|
||||
eDrawWorld = 0x1,
|
||||
eDrawWorldCollision = 0x2,
|
||||
eDrawObjects = 0x4,
|
||||
eDrawObjectCollision = 0x8,
|
||||
eDrawLights = 0x10,
|
||||
eDrawSky = 0x20,
|
||||
eEnableUVScroll = 0x40,
|
||||
eEnableBackfaceCull = 0x80,
|
||||
eEnableOccluders = 0x100,
|
||||
eNoMaterialSetup = 0x200,
|
||||
eEnableBloom = 0x400,
|
||||
eNoAlpha = 0x800
|
||||
};
|
||||
DEFINE_ENUM_FLAGS(ERenderOptions)
|
||||
|
||||
#endif // ERENDEROPTIONS
|
||||
|
||||
20
src/Core/Render/IRenderable.h
Normal file
20
src/Core/Render/IRenderable.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef IRENDERABLE_H
|
||||
#define IRENDERABLE_H
|
||||
|
||||
#include "ERenderOptions.h"
|
||||
#include "SViewInfo.h"
|
||||
#include <Common/types.h>
|
||||
|
||||
class CRenderer;
|
||||
|
||||
class IRenderable
|
||||
{
|
||||
public:
|
||||
IRenderable() {}
|
||||
virtual ~IRenderable() {}
|
||||
virtual void AddToRenderer(CRenderer* pRenderer, const SViewInfo& ViewInfo) = 0;
|
||||
virtual void Draw(ERenderOptions /*Options*/, int /*ComponentIndex*/, const SViewInfo& /*ViewInfo*/) {}
|
||||
virtual void DrawSelection() {}
|
||||
};
|
||||
|
||||
#endif // IRENDERABLE_H
|
||||
18
src/Core/Render/SRenderablePtr.h
Normal file
18
src/Core/Render/SRenderablePtr.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef SRENDERABLEPTR_H
|
||||
#define SRENDERABLEPTR_H
|
||||
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/types.h>
|
||||
#include <Core/ERenderCommand.h>
|
||||
#include <Scene/CSceneNode.h>
|
||||
#include <Resource/CMaterial.h>
|
||||
|
||||
struct SRenderablePtr
|
||||
{
|
||||
IRenderable *pRenderable;
|
||||
u32 ComponentIndex;
|
||||
CAABox AABox;
|
||||
ERenderCommand Command;
|
||||
};
|
||||
|
||||
#endif // SRENDERABLEPTR_H
|
||||
20
src/Core/Render/SViewInfo.h
Normal file
20
src/Core/Render/SViewInfo.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef SVIEWINFO
|
||||
#define SVIEWINFO
|
||||
|
||||
#include "CFrustumPlanes.h"
|
||||
#include <Common/CMatrix4f.h>
|
||||
#include <Common/CRay.h>
|
||||
|
||||
struct SViewInfo
|
||||
{
|
||||
class CSceneManager *pScene;
|
||||
class CRenderer *pRenderer;
|
||||
|
||||
class CCamera *pCamera;
|
||||
bool GameMode;
|
||||
CFrustumPlanes ViewFrustum;
|
||||
CMatrix4f RotationOnlyViewMatrix;
|
||||
};
|
||||
|
||||
#endif // SVIEWINFO
|
||||
|
||||
31
src/Core/Resource/CAnimSet.cpp
Normal file
31
src/Core/Resource/CAnimSet.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "CAnimSet.h"
|
||||
#include <Core/CResCache.h>
|
||||
|
||||
CAnimSet::CAnimSet() : CResource()
|
||||
{
|
||||
}
|
||||
|
||||
CAnimSet::~CAnimSet()
|
||||
{
|
||||
}
|
||||
|
||||
u32 CAnimSet::getNodeCount()
|
||||
{
|
||||
return nodes.size();
|
||||
}
|
||||
|
||||
TString CAnimSet::getNodeName(u32 node)
|
||||
{
|
||||
if (node >= nodes.size())
|
||||
return nodes[0].name;
|
||||
else
|
||||
return nodes[node].name;
|
||||
}
|
||||
|
||||
CModel* CAnimSet::getNodeModel(u32 node)
|
||||
{
|
||||
if (node >= nodes.size())
|
||||
return nodes[0].model;
|
||||
else
|
||||
return nodes[node].model;
|
||||
}
|
||||
36
src/Core/Resource/CAnimSet.h
Normal file
36
src/Core/Resource/CAnimSet.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef CANIMSET_H
|
||||
#define CANIMSET_H
|
||||
|
||||
#include <Common/types.h>
|
||||
#include <Core/TResPtr.h>
|
||||
#include <vector>
|
||||
#include "model/CModel.h"
|
||||
#include "CResource.h"
|
||||
|
||||
// will expand later! this is where animation support will come in
|
||||
class CAnimSet : public CResource
|
||||
{
|
||||
DECLARE_RESOURCE_TYPE(eAnimSet)
|
||||
friend class CAnimSetLoader;
|
||||
|
||||
struct SNode
|
||||
{
|
||||
TString name;
|
||||
TResPtr<CModel> model;
|
||||
u32 skinID;
|
||||
u32 skelID;
|
||||
|
||||
SNode() { model = nullptr; }
|
||||
};
|
||||
std::vector<SNode> nodes;
|
||||
|
||||
public:
|
||||
CAnimSet();
|
||||
~CAnimSet();
|
||||
|
||||
u32 getNodeCount();
|
||||
TString getNodeName(u32 node);
|
||||
CModel* getNodeModel(u32 node);
|
||||
};
|
||||
|
||||
#endif // CCHARACTERSET_H
|
||||
138
src/Core/Resource/CAnimationParameters.cpp
Normal file
138
src/Core/Resource/CAnimationParameters.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "CAnimationParameters.h"
|
||||
#include "CAnimSet.h"
|
||||
#include <Core/CResCache.h>
|
||||
#include <Core/Log.h>
|
||||
#include <iostream>
|
||||
|
||||
CAnimationParameters::CAnimationParameters()
|
||||
{
|
||||
mGame = ePrime;
|
||||
mpCharSet = nullptr;
|
||||
mNodeIndex = 0;
|
||||
mUnknown1 = 0;
|
||||
mUnknown2 = 0;
|
||||
mUnknown3 = 0;
|
||||
mUnknown4 = 0;
|
||||
}
|
||||
|
||||
CAnimationParameters::CAnimationParameters(CInputStream& SCLY, EGame game)
|
||||
{
|
||||
mGame = game;
|
||||
mpCharSet = nullptr;
|
||||
mNodeIndex = 0;
|
||||
mUnknown1 = 0;
|
||||
mUnknown2 = 0;
|
||||
mUnknown3 = 0;
|
||||
mUnknown4 = 0;
|
||||
|
||||
if (game <= eEchoes)
|
||||
{
|
||||
u32 animSetID = SCLY.ReadLong();
|
||||
mNodeIndex = SCLY.ReadLong();
|
||||
mUnknown1 = SCLY.ReadLong();
|
||||
|
||||
mpCharSet = gResCache.GetResource(animSetID, "ANCS");
|
||||
}
|
||||
|
||||
else if (game <= eCorruption)
|
||||
{
|
||||
u64 charID = SCLY.ReadLongLong();
|
||||
mUnknown1 = SCLY.ReadLong();
|
||||
|
||||
mpCharSet = gResCache.GetResource(charID, "CHAR");
|
||||
}
|
||||
|
||||
else if (game == eReturns)
|
||||
{
|
||||
SCLY.Seek(-6, SEEK_CUR);
|
||||
u32 offset = SCLY.Tell();
|
||||
u32 propID = SCLY.ReadLong();
|
||||
SCLY.Seek(2, SEEK_CUR);
|
||||
|
||||
mUnknown1 = (u32) SCLY.ReadByte();
|
||||
mUnknown1 &= 0xFF;
|
||||
|
||||
if (mUnknown1 == 0x60)
|
||||
{
|
||||
u64 charID = SCLY.ReadLongLong();
|
||||
mUnknown2 = SCLY.ReadLong();
|
||||
mUnknown3 = SCLY.ReadLong();
|
||||
mUnknown4 = SCLY.ReadLong();
|
||||
|
||||
mpCharSet = gResCache.GetResource(charID, "CHAR");
|
||||
}
|
||||
|
||||
else if (mUnknown1 != 0x80)
|
||||
{
|
||||
Log::FileError(SCLY.GetSourceString(), offset,
|
||||
"Unexpected AnimationParameters byte: " + TString::HexString(mUnknown1, true, true, 2) + " (property " + TString::HexString(propID, true, true, 8) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CModel* CAnimationParameters::GetCurrentModel(s32 nodeIndex)
|
||||
{
|
||||
if (!mpCharSet) return nullptr;
|
||||
if (mpCharSet->Type() != eAnimSet) return nullptr;
|
||||
if (nodeIndex == -1) nodeIndex = mNodeIndex;
|
||||
|
||||
CAnimSet *pSet = static_cast<CAnimSet*>(mpCharSet.RawPointer());
|
||||
if (pSet->getNodeCount() <= (u32) nodeIndex) return nullptr;
|
||||
return pSet->getNodeModel(nodeIndex);
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
EGame CAnimationParameters::Version()
|
||||
{
|
||||
return mGame;
|
||||
}
|
||||
|
||||
CResource* CAnimationParameters::Resource()
|
||||
{
|
||||
return mpCharSet;
|
||||
}
|
||||
|
||||
u32 CAnimationParameters::CharacterIndex()
|
||||
{
|
||||
return mNodeIndex;
|
||||
}
|
||||
|
||||
u32 CAnimationParameters::Unknown(u32 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return mUnknown1;
|
||||
case 1: return mUnknown2;
|
||||
case 2: return mUnknown3;
|
||||
case 3: return mUnknown4;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ SETTERS ************
|
||||
void CAnimationParameters::SetResource(CResource *pRes)
|
||||
{
|
||||
if ((pRes->Type() == eAnimSet) || (pRes->Type() == eCharacter))
|
||||
{
|
||||
mpCharSet = pRes;
|
||||
mNodeIndex = 0;
|
||||
}
|
||||
else
|
||||
Log::Error("Resource with invalid type passed to CAnimationParameters: " + pRes->Source());
|
||||
}
|
||||
|
||||
void CAnimationParameters::SetNodeIndex(u32 index)
|
||||
{
|
||||
mNodeIndex = index;
|
||||
}
|
||||
|
||||
void CAnimationParameters::SetUnknown(u32 index, u32 value)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: mUnknown1 = value;
|
||||
case 1: mUnknown2 = value;
|
||||
case 2: mUnknown3 = value;
|
||||
case 3: mUnknown4 = value;
|
||||
}
|
||||
}
|
||||
37
src/Core/Resource/CAnimationParameters.h
Normal file
37
src/Core/Resource/CAnimationParameters.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef CANIMATIONPARAMETERS_H
|
||||
#define CANIMATIONPARAMETERS_H
|
||||
|
||||
#include "CResource.h"
|
||||
#include "model/CModel.h"
|
||||
#include <Core/TResPtr.h>
|
||||
#include "EFormatVersion.h"
|
||||
|
||||
class CAnimationParameters
|
||||
{
|
||||
EGame mGame;
|
||||
TResPtr<CResource> mpCharSet;
|
||||
|
||||
u32 mNodeIndex;
|
||||
u32 mUnknown1;
|
||||
u32 mUnknown2;
|
||||
u32 mUnknown3;
|
||||
u32 mUnknown4;
|
||||
|
||||
public:
|
||||
CAnimationParameters();
|
||||
CAnimationParameters(CInputStream& SCLY, EGame game);
|
||||
CModel* GetCurrentModel(s32 nodeIndex = -1);
|
||||
|
||||
// Getters
|
||||
EGame Version();
|
||||
CResource* Resource();
|
||||
u32 CharacterIndex();
|
||||
u32 Unknown(u32 index);
|
||||
|
||||
// Setters
|
||||
void SetResource(CResource *pRes);
|
||||
void SetNodeIndex(u32 index);
|
||||
void SetUnknown(u32 index, u32 value);
|
||||
};
|
||||
|
||||
#endif // CANIMATIONPARAMETERS_H
|
||||
114
src/Core/Resource/CCollisionMesh.cpp
Normal file
114
src/Core/Resource/CCollisionMesh.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "CCollisionMesh.h"
|
||||
#include <Core/CRenderer.h>
|
||||
|
||||
CCollisionMesh::CCollisionMesh()
|
||||
{
|
||||
mVBO.SetVertexDesc(ePosition);
|
||||
mVertexCount = 0;
|
||||
mLineCount = 0;
|
||||
mFaceCount = 0;
|
||||
mBuffered = false;
|
||||
mIBO.SetPrimitiveType(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
CCollisionMesh::~CCollisionMesh()
|
||||
{
|
||||
if (mBuffered)
|
||||
{
|
||||
mIBO.Clear();
|
||||
mVBO.Clear();
|
||||
mBuffered = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CCollisionMesh::BufferGL()
|
||||
{
|
||||
if (mBuffered)
|
||||
{
|
||||
mIBO.Clear();
|
||||
mVBO.Clear();
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
// Add all the verts to our VBO, first...
|
||||
mVBO.Reserve(mCollisionVertices.size());
|
||||
for (u16 v = 0; v < mCollisionVertices.size(); v++)
|
||||
mVBO.AddVertex(CVertex(mCollisionVertices[v].Pos));
|
||||
|
||||
// Then add all the relevant indices to the IBO
|
||||
mIBO.Reserve(mCollisionFaces.size() * 3);
|
||||
for (u32 v = 0; v < mCollisionFaces.size(); v++)
|
||||
{
|
||||
u16 Verts[3];
|
||||
|
||||
CCollisionFace *Face = &mCollisionFaces[v];
|
||||
CCollisionLine *LineA = GetLine(Face->Lines[0]);
|
||||
CCollisionLine *LineB = GetLine(Face->Lines[1]);
|
||||
Verts[0] = LineA->Vertices[0];
|
||||
Verts[1] = LineA->Vertices[1];
|
||||
|
||||
// We have two vertex indices; the last one is one of the ones on line B, but we're not sure which one
|
||||
if ((LineB->Vertices[0] != Verts[0]) &&
|
||||
(LineB->Vertices[0] != Verts[1]))
|
||||
Verts[2] = LineB->Vertices[0];
|
||||
else
|
||||
Verts[2] = LineB->Vertices[1];
|
||||
|
||||
// Some faces have a property that indicates they need to be inverted
|
||||
if (!Face->Properties.Invert)
|
||||
mIBO.AddIndices(&Verts[0], 3);
|
||||
else {
|
||||
mIBO.AddIndex(Verts[2]);
|
||||
mIBO.AddIndex(Verts[1]);
|
||||
mIBO.AddIndex(Verts[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer, and done
|
||||
mVBO.Buffer();
|
||||
mIBO.Buffer();
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CCollisionMesh::Draw()
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
|
||||
mVBO.Bind();
|
||||
mIBO.Bind();
|
||||
|
||||
glDrawElements(GL_TRIANGLES, mIBO.GetSize(), GL_UNSIGNED_SHORT, (void*) 0);
|
||||
gDrawCount++;
|
||||
mIBO.Unbind();
|
||||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
void CCollisionMesh::DrawWireframe()
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
|
||||
mVBO.Bind();
|
||||
mIBO.Bind();
|
||||
for (u32 f = 0; f < mFaceCount; f++)
|
||||
{
|
||||
glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, (void*) (f * 6));
|
||||
gDrawCount++;
|
||||
}
|
||||
mIBO.Unbind();
|
||||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionVertex* CCollisionMesh::GetVertex(u16 index)
|
||||
{
|
||||
return &mCollisionVertices[index];
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionLine* CCollisionMesh::GetLine(u16 index)
|
||||
{
|
||||
return &mCollisionLines[index];
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionFace* CCollisionMesh::GetFace(u16 index)
|
||||
{
|
||||
return &mCollisionFaces[index];
|
||||
}
|
||||
88
src/Core/Resource/CCollisionMesh.h
Normal file
88
src/Core/Resource/CCollisionMesh.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef CCOLLISIONMESH_H
|
||||
#define CCOLLISIONMESH_H
|
||||
|
||||
#include <Common/CAABox.h>
|
||||
#include <OpenGL/CVertexBuffer.h>
|
||||
#include <OpenGL/CIndexBuffer.h>
|
||||
#include "CResource.h"
|
||||
|
||||
class CCollisionMesh
|
||||
{
|
||||
friend class CCollisionLoader;
|
||||
|
||||
class CCollisionOctree
|
||||
{
|
||||
friend class CCollisionLoader;
|
||||
struct SOctreeNode {};
|
||||
|
||||
struct SLeaf : public SOctreeNode
|
||||
{
|
||||
CAABox AABox;
|
||||
std::vector<u16> FaceIndices;
|
||||
};
|
||||
|
||||
struct SBranch : public SOctreeNode
|
||||
{
|
||||
u16 Flags;
|
||||
SOctreeNode *pChildren[8];
|
||||
};
|
||||
|
||||
SOctreeNode* Root;
|
||||
};
|
||||
|
||||
struct SCollisionProperties
|
||||
{
|
||||
// todo: figure out what the other properties are
|
||||
bool Invert;
|
||||
};
|
||||
|
||||
class CCollisionVertex
|
||||
{
|
||||
public:
|
||||
SCollisionProperties Properties;
|
||||
CVector3f Pos;
|
||||
};
|
||||
|
||||
class CCollisionLine
|
||||
{
|
||||
public:
|
||||
SCollisionProperties Properties;
|
||||
u16 Vertices[2];
|
||||
};
|
||||
|
||||
class CCollisionFace
|
||||
{
|
||||
public:
|
||||
SCollisionProperties Properties;
|
||||
u16 Lines[3];
|
||||
};
|
||||
|
||||
CVertexBuffer mVBO;
|
||||
CIndexBuffer mIBO;
|
||||
u32 mVertexCount;
|
||||
u32 mLineCount;
|
||||
u32 mFaceCount;
|
||||
bool mBuffered;
|
||||
|
||||
CAABox mAABox;
|
||||
CCollisionOctree *mOctree;
|
||||
std::vector<u32> mFlags;
|
||||
std::vector<CCollisionVertex> mCollisionVertices;
|
||||
std::vector<CCollisionLine> mCollisionLines;
|
||||
std::vector<CCollisionFace> mCollisionFaces;
|
||||
bool mOctreeLoaded;
|
||||
|
||||
CCollisionVertex *GetVertex(u16 index);
|
||||
CCollisionLine *GetLine(u16 index);
|
||||
CCollisionFace *GetFace(u16 index);
|
||||
|
||||
public:
|
||||
CCollisionMesh();
|
||||
~CCollisionMesh();
|
||||
|
||||
void BufferGL();
|
||||
void Draw();
|
||||
void DrawWireframe();
|
||||
};
|
||||
|
||||
#endif // CCOLLISIONMESH_H
|
||||
38
src/Core/Resource/CCollisionMeshGroup.cpp
Normal file
38
src/Core/Resource/CCollisionMeshGroup.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "CCollisionMeshGroup.h"
|
||||
|
||||
CCollisionMeshGroup::CCollisionMeshGroup()
|
||||
{
|
||||
}
|
||||
|
||||
CCollisionMeshGroup::~CCollisionMeshGroup()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
u32 CCollisionMeshGroup::NumMeshes()
|
||||
{
|
||||
return mMeshes.size();
|
||||
}
|
||||
|
||||
CCollisionMesh* CCollisionMeshGroup::MeshByIndex(u32 index)
|
||||
{
|
||||
return mMeshes[index];
|
||||
}
|
||||
|
||||
void CCollisionMeshGroup::AddMesh(CCollisionMesh *pMesh)
|
||||
{
|
||||
mMeshes.push_back(pMesh);
|
||||
}
|
||||
|
||||
void CCollisionMeshGroup::Draw()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
(*it)->Draw();
|
||||
}
|
||||
|
||||
void CCollisionMeshGroup::DrawWireframe()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
(*it)->DrawWireframe();
|
||||
}
|
||||
25
src/Core/Resource/CCollisionMeshGroup.h
Normal file
25
src/Core/Resource/CCollisionMeshGroup.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef CCOLLISIONMESHGROUP_H
|
||||
#define CCOLLISIONMESHGROUP_H
|
||||
|
||||
#include "CResource.h"
|
||||
#include "CCollisionMesh.h"
|
||||
#include <Core/TResPtr.h>
|
||||
#include <vector>
|
||||
|
||||
class CCollisionMeshGroup : public CResource
|
||||
{
|
||||
DECLARE_RESOURCE_TYPE(eCollisionMeshGroup)
|
||||
std::vector<CCollisionMesh*> mMeshes;
|
||||
|
||||
public:
|
||||
CCollisionMeshGroup();
|
||||
~CCollisionMeshGroup();
|
||||
|
||||
u32 NumMeshes();
|
||||
CCollisionMesh* MeshByIndex(u32 index);
|
||||
void AddMesh(CCollisionMesh *pMesh);
|
||||
void Draw();
|
||||
void DrawWireframe();
|
||||
};
|
||||
|
||||
#endif // CCOLLISIONMESHGROUP_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user