GPU/Math3D: Change Vec3 to allow for arbitrary component base types.

This commit is contained in:
neobrain 2013-07-25 14:46:42 +02:00
parent 0ed6e93b22
commit 6926926267
4 changed files with 156 additions and 105 deletions

View File

@ -98,7 +98,7 @@ static GLenum blendColor2Func(u32 fix) {
if (fix == 0)
return GL_ZERO;
Vec3 fix3 = Vec3::FromRGB(fix);
Vec3f fix3 = Vec3f::FromRGB(fix);
if (fix3.x >= 0.99 && fix3.y >= 0.99 && fix3.z >= 0.99)
return GL_ONE;
else if (fix3.x <= 0.01 && fix3.y <= 0.01 && fix3.z <= 0.01)
@ -106,8 +106,8 @@ static GLenum blendColor2Func(u32 fix) {
return GL_INVALID_ENUM;
}
static bool blendColorSimilar(Vec3 a, Vec3 b, float margin = 0.1f) {
Vec3 diff = a - b;
static bool blendColorSimilar(Vec3f a, Vec3f b, float margin = 0.1f) {
Vec3f diff = a - b;
if (fabsf(diff.x) <= margin && fabsf(diff.y) <= margin && fabsf(diff.z) <= margin)
return true;
return false;
@ -146,8 +146,8 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? blendColor2Func(gstate.getFixA()) : aLookup[blendFuncA];
GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? blendColor2Func(gstate.getFixB()) : bLookup[blendFuncB];
if (blendFuncA == GE_SRCBLEND_FIXA || blendFuncB == GE_DSTBLEND_FIXB) {
Vec3 fixA = Vec3::FromRGB(gstate.getFixA());
Vec3 fixB = Vec3::FromRGB(gstate.getFixB());
Vec3f fixA = Vec3f::FromRGB(gstate.getFixA());
Vec3f fixB = Vec3f::FromRGB(gstate.getFixB());
if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB != GL_INVALID_ENUM) {
// Can use blendcolor trivially.
const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f};
@ -159,7 +159,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
glstate.blendColor.set(blendColor);
glBlendFuncB = GL_CONSTANT_COLOR;
} else if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) {
if (blendColorSimilar(fixA, Vec3::AssignToAll(1.0f) - fixB)) {
if (blendColorSimilar(fixA, Vec3f::AssignToAll(1.0f) - fixB)) {
glBlendFuncA = GL_CONSTANT_COLOR;
glBlendFuncB = GL_ONE_MINUS_CONSTANT_COLOR;
const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f};
@ -177,9 +177,9 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
DEBUG_LOG(HLE, "ERROR INVALID blendcolorstate: FixA=%06x FixB=%06x FuncA=%i FuncB=%i", gstate.getFixA(), gstate.getFixB(), gstate.getBlendFuncA(), gstate.getBlendFuncB());
// Let's approximate, at least. Close is better than totally off.
const bool nearZeroA = blendColorSimilar(fixA, Vec3::AssignToAll(0.0f), 0.25f);
const bool nearZeroB = blendColorSimilar(fixB, Vec3::AssignToAll(0.0f), 0.25f);
if (nearZeroA || blendColorSimilar(fixA, Vec3::AssignToAll(1.0f), 0.25f)) {
const bool nearZeroA = blendColorSimilar(fixA, Vec3f::AssignToAll(0.0f), 0.25f);
const bool nearZeroB = blendColorSimilar(fixB, Vec3f::AssignToAll(0.0f), 0.25f);
if (nearZeroA || blendColorSimilar(fixA, Vec3f::AssignToAll(1.0f), 0.25f)) {
glBlendFuncA = nearZeroA ? GL_ZERO : GL_ONE;
glBlendFuncB = GL_CONSTANT_COLOR;
const float blendColor[4] = {fixB.x, fixB.y, fixB.z, 1.0f};

View File

@ -221,7 +221,7 @@ void TransformDrawEngine::DrawSpline(int ucount, int vcount, int utype, int vtyp
class Lighter {
public:
Lighter();
void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3 pos, Vec3 normal);
void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f normal);
private:
Color4 globalAmbient;
@ -230,7 +230,7 @@ private:
Color4 materialDiffuse;
Color4 materialSpecular;
float specCoef_;
// Vec3 viewer_;
// Vec3f viewer_;
bool doShadeMapping_;
int materialUpdate_;
};
@ -248,11 +248,11 @@ Lighter::Lighter() {
materialSpecular.GetFromRGB(gstate.materialspecular);
materialSpecular.a = 1.0f;
specCoef_ = getFloat24(gstate.materialspecularcoef);
// viewer_ = Vec3(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]);
// viewer_ = Vec3f(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]);
materialUpdate_ = gstate.materialupdate & 7;
}
void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3 pos, Vec3 norm)
void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], Vec3f pos, Vec3f norm)
{
Color4 in(colorIn);
@ -285,13 +285,13 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
GELightType type = gstate.getLightType(l);
Vec3 toLight(0,0,0);
Vec3 lightDir(0,0,0);
Vec3f toLight(0,0,0);
Vec3f lightDir(0,0,0);
if (type == GE_LIGHTTYPE_DIRECTIONAL)
toLight = Vec3(gstate_c.lightpos[l]); // lightdir is for spotlights
toLight = Vec3f(gstate_c.lightpos[l]); // lightdir is for spotlights
else
toLight = Vec3(gstate_c.lightpos[l]) - pos;
toLight = Vec3f(gstate_c.lightpos[l]) - pos;
bool doSpecular = gstate.isUsingSpecularLight(l);
bool poweredDiffuse = gstate.isUsingPoweredDiffuseLight(l);
@ -334,13 +334,13 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
Color4 diff = (lightDiff * *diffuse) * dot;
// Real PSP specular
Vec3 toViewer(0,0,1);
Vec3f toViewer(0,0,1);
// Better specular
// Vec3 toViewer = (viewer - pos).Normalized();
// Vec3f toViewer = (viewer - pos).Normalized();
if (doSpecular)
{
Vec3 halfVec = (toLight + toViewer);
Vec3f halfVec = (toLight + toViewer);
halfVec.Normalize();
dot = Dot(halfVec, norm);
@ -570,7 +570,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
// We do software T&L for now
float out[3], norm[3];
float pos[3], nrm[3];
Vec3 normal(0, 0, 1);
Vec3f normal(0, 0, 1);
reader.ReadPos(pos);
if (reader.hasNormal())
reader.ReadNrm(nrm);
@ -579,24 +579,24 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
Vec3ByMatrix43(out, pos, gstate.worldMatrix);
if (reader.hasNormal()) {
Norm3ByMatrix43(norm, nrm, gstate.worldMatrix);
normal = Vec3(norm).Normalized();
normal = Vec3f(norm).Normalized();
}
} else {
float weights[8];
reader.ReadWeights(weights);
// Skinning
Vec3 psum(0,0,0);
Vec3 nsum(0,0,0);
Vec3f psum(0,0,0);
Vec3f nsum(0,0,0);
int nweights = ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT) + 1;
for (int i = 0; i < nweights; i++)
{
if (weights[i] != 0.0f) {
Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12);
Vec3 tpos(out);
Vec3f tpos(out);
psum += tpos * weights[i];
if (reader.hasNormal()) {
Norm3ByMatrix43(norm, nrm, gstate.boneMatrix+i*12);
Vec3 tnorm(norm);
Vec3f tnorm(norm);
nsum += tnorm * weights[i];
}
}
@ -606,7 +606,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix);
if (reader.hasNormal()) {
Norm3ByMatrix43(norm, nsum.AsArray(), gstate.worldMatrix);
normal = Vec3(norm).Normalized();
normal = Vec3f(norm).Normalized();
}
}
@ -674,29 +674,29 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
case 1:
{
// Projection mapping
Vec3 source;
Vec3f source;
switch (gstate.getUVProjMode())
{
case 0: // Use model space XYZ as source
source = pos;
break;
case 1: // Use unscaled UV as source
source = Vec3(ruv[0], ruv[1], 0.0f);
source = Vec3f(ruv[0], ruv[1], 0.0f);
break;
case 2: // Use normalized normal as source
if (reader.hasNormal()) {
source = Vec3(norm).Normalized();
source = Vec3f(norm).Normalized();
} else {
ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
source = Vec3::AssignToAll(0.0f);
source = Vec3f::AssignToAll(0.0f);
}
break;
case 3: // Use non-normalized normal as source!
if (reader.hasNormal()) {
source = Vec3(norm);
source = Vec3f(norm);
} else {
ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
source = Vec3::AssignToAll(0.0f);
source = Vec3f::AssignToAll(0.0f);
}
break;
}
@ -711,8 +711,8 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
case 2:
// Shade mapping - use two light sources to generate U and V.
{
Vec3 lightpos0 = Vec3(gstate_c.lightpos[gstate.getUVLS0()]).Normalized();
Vec3 lightpos1 = Vec3(gstate_c.lightpos[gstate.getUVLS1()]).Normalized();
Vec3f lightpos0 = Vec3f(gstate_c.lightpos[gstate.getUVLS0()]).Normalized();
Vec3f lightpos1 = Vec3f(gstate_c.lightpos[gstate.getUVLS1()]).Normalized();
uv[0] = (1.0f + Dot(lightpos0, normal))/2.0f;
uv[1] = (1.0f - Dot(lightpos1, normal))/2.0f;

View File

@ -15,4 +15,56 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Math3D.h"
#include "Math3D.h"
template<>
Vec3<float> Vec3<float>::FromRGB(unsigned int rgb)
{
return Vec3((rgb & 0xFF) * (1.0f/255.0f),
((rgb >> 8) & 0xFF) * (1.0f/255.0f),
((rgb >> 16) & 0xFF) * (1.0f/255.0f));
}
template<>
Vec3<int> Vec3<int>::FromRGB(unsigned int rgb)
{
return Vec3(rgb & 0xFF, (rgb >> 8) & 0xFF, (rgb >> 16) & 0xFF);
}
template<>
float Vec3<float>::Length() const
{
return sqrtf(Length2());
}
template<>
void Vec3<float>::SetLength(const float l)
{
(*this) *= l / Length();
}
template<>
Vec3<float> Vec3<float>::WithLength(const float l) const
{
return (*this) * l / Length();
}
template<>
float Vec3<float>::Distance2To(Vec3<float> &other)
{
return Vec3<float>(other-(*this)).Length2();
}
template<>
Vec3<float> Vec3<float>::Normalized() const
{
return (*this) / Length();
}
template<>
float Vec3<float>::Normalize()
{
float len = Length();
(*this) = (*this)/len;
return len;
}

View File

@ -19,36 +19,34 @@
#include <cmath>
template<typename T>
class Vec3
{
public:
struct
{
float x,y,z;
T x,y,z;
};
float* AsArray() { return &x; }
T* AsArray() { return &x; }
Vec3(const float a[3]) : x(a[0]), y(a[1]), z(a[2]) {}
Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
Vec3() {}
Vec3(const T a[3]) : x(a[0]), y(a[1]), z(a[2]) {}
Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
static Vec3 FromRGB(unsigned int rgb)
// Only implemented for T=int and T=float
static Vec3 FromRGB(unsigned int rgb);
static Vec3 AssignToAll(const T& f)
{
return Vec3((rgb & 0xFF) * (1.0f/255.0f),
((rgb >> 8) & 0xFF) * (1.0f/255.0f),
((rgb >> 16) & 0xFF) * (1.0f/255.0f));
return Vec3<T>(f, f, f);
}
static Vec3 AssignToAll(float f)
{
return Vec3(f, f, f);
}
void Write(float a[3])
void Write(T a[3])
{
a[0] = x; a[1] = y; a[2] = z;
}
Vec3 operator +(const Vec3 &other) const
{
return Vec3(x+other.x, y+other.y, z+other.z);
@ -73,94 +71,93 @@ public:
{
return Vec3(x*other.x, y*other.y, z*other.z);
}
Vec3 operator * (const float f) const
template<typename V>
Vec3 operator * (const V& f) const
{
return Vec3(x*f,y*f,z*f);
}
void operator *= (const float f)
template<typename V>
void operator *= (const V& f)
{
x*=f; y*=f; z*=f;
}
Vec3 operator / (const float f) const
template<typename V>
Vec3 operator / (const V& f) const
{
float invf = (1.0f/f);
return Vec3(x*invf,y*invf,z*invf);
return Vec3(x/f,y/f,z/f);
}
void operator /= (const float f)
template<typename V>
void operator /= (const V& f)
{
*this = *this / f;
}
float Length2() const
T Length2() const
{
return x*x + y*y + z*z;
}
float Length() const
{
return sqrtf(Length2());
}
void SetLength(const float l)
{
(*this) *= l / Length();
}
Vec3 WithLength(const float l) const
{
return (*this) * l / Length();
}
float Distance2To(Vec3 &other)
{
return Vec3(other-(*this)).Length2();
}
Vec3 Normalized() const {
return (*this) / Length();
}
float Normalize() { //returns the previous length, is often useful
float len = Length();
(*this) = (*this)/len;
return len;
}
float &operator [] (int i) //allow vector[2] = 3 (vector.z=3)
// Only implemented for T=float
float Length() const;
void SetLength(const float l);
Vec3 WithLength(const float l) const;
float Distance2To(Vec3 &other);
Vec3 Normalized() const;
float Normalize(); // returns the previous length, which is often useful
T& operator [] (int i) //allow vector[2] = 3 (vector.z=3)
{
return *((&x) + i);
}
float operator [] (const int i) const
T operator [] (const int i) const
{
return *((&x) + i);
}
Vec3 Lerp(const Vec3 &other, const float t) const
{
return (*this)*(1-t) + other*t;
}
void SetZero()
{
x=0;y=0;z=0;
x=0; y=0; z=0;
}
// Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
float& u() { return x; }
float& v() { return y; }
float& w() { return z; }
T& u() { return x; }
T& v() { return y; }
T& w() { return z; }
float& r() { return x; }
float& g() { return y; }
float& b() { return z; }
T& r() { return x; }
T& g() { return y; }
T& b() { return z; }
float& s() { return x; }
float& t() { return y; }
float& q() { return z; }
T& s() { return x; }
T& t() { return y; }
T& q() { return z; }
const float& u() const { return x; }
const float& v() const { return y; }
const float& w() const { return z; }
const T& u() const { return x; }
const T& v() const { return y; }
const T& w() const { return z; }
const float& r() const { return x; }
const float& g() const { return y; }
const float& b() const { return z; }
const T& r() const { return x; }
const T& g() const { return y; }
const T& b() const { return z; }
const float& s() const { return x; }
const float& t() const { return y; }
const float& q() const { return z; }
const T& s() const { return x; }
const T& t() const { return y; }
const T& q() const { return z; }
};
template<typename T, typename V>
Vec3<T> operator * (const V& f, const Vec3<T>& vec)
{
return Vec3<T>(f*vec.x,f*vec.y,f*vec.z);
}
typedef Vec3<float> Vec3f;
inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12])
{
vecOut[0] = v[0] * m[0] + v[1] * m[3] + v[2] * m[6] + m[9];
@ -180,12 +177,14 @@ inline float Vec3Dot(const float v1[3], const float v2[3])
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
inline float Dot(const Vec3 &a, const Vec3& b)
template<typename T>
inline T Dot(const Vec3<T>& a, const Vec3<T>& b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
inline Vec3 Cross(const Vec3 &a, const Vec3& b)
template<typename T>
inline Vec3<T> Cross(const Vec3<T>& a, const Vec3<T>& b)
{
return Vec3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
return Vec3<T>(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}