mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-01 14:24:02 +00:00
GPU/Math3D: Change Vec3 to allow for arbitrary component base types.
This commit is contained in:
parent
0ed6e93b22
commit
6926926267
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
137
GPU/Math3D.h
137
GPU/Math3D.h
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user