forked from ssloy/tinyrenderer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
310 additions
and
300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
#include "geometry.h" | ||
|
||
template <> template <> vec<3,int> ::vec(const vec<3,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)),z(int(v.z+.5f)) {} | ||
template <> template <> vec<3,float>::vec(const vec<3,int> &v) : x(v.x),y(v.y),z(v.z) {} | ||
template <> template <> vec<2,int> ::vec(const vec<2,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)) {} | ||
template <> template <> vec<2,float>::vec(const vec<2,int> &v) : x(v.x),y(v.y) {} | ||
vec3 cross(const vec3 &v1, const vec3 &v2) { | ||
return vec<3>{v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x}; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,221 +1,238 @@ | ||
#ifndef __GEOMETRY_H__ | ||
#define __GEOMETRY_H__ | ||
|
||
#include <cmath> | ||
#include <vector> | ||
#include <cassert> | ||
#include <iostream> | ||
|
||
template<size_t DimCols,size_t DimRows,typename T> class mat; | ||
|
||
template <size_t DIM, typename T> struct vec { | ||
vec() { for (size_t i=DIM; i--; data_[i] = T()); } | ||
T& operator[](const size_t i) { assert(i<DIM); return data_[i]; } | ||
const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; } | ||
private: | ||
T data_[DIM]; | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template <typename T> struct vec<2,T> { | ||
vec() : x(T()), y(T()) {} | ||
vec(T X, T Y) : x(X), y(Y) {} | ||
template <class U> vec<2,T>(const vec<2,U> &v); | ||
T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; } | ||
const T& operator[](const size_t i) const { assert(i<2); return i<=0 ? x : y; } | ||
|
||
T x,y; | ||
template<int n> struct vec { | ||
vec() = default; | ||
double & operator[](const int i) { assert(i>=0 && i<n); return data[i]; } | ||
double operator[](const int i) const { assert(i>=0 && i<n); return data[i]; } | ||
double norm2() const { return (*this)*(*this) ; } | ||
double norm() const { return std::sqrt(norm2()); } | ||
double data[n] = {0}; | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template <typename T> struct vec<3,T> { | ||
vec() : x(T()), y(T()), z(T()) {} | ||
vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {} | ||
template <class U> vec<3,T>(const vec<3,U> &v); | ||
T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); } | ||
const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); } | ||
float norm() { return std::sqrt(x*x+y*y+z*z); } | ||
vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; } | ||
|
||
T x,y,z; | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template<size_t DIM,typename T> T operator*(const vec<DIM,T>& lhs, const vec<DIM,T>& rhs) { | ||
T ret = T(); | ||
for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]); | ||
template<int n> double operator*(const vec<n>& lhs, const vec<n>& rhs) { | ||
double ret = 0; | ||
for (int i=n; i--; ret+=lhs[i]*rhs[i]); | ||
return ret; | ||
} | ||
|
||
|
||
template<size_t DIM,typename T>vec<DIM,T> operator+(vec<DIM,T> lhs, const vec<DIM,T>& rhs) { | ||
for (size_t i=DIM; i--; lhs[i]+=rhs[i]); | ||
return lhs; | ||
template<int n> vec<n> operator+(const vec<n>& lhs, const vec<n>& rhs) { | ||
vec<n> ret = lhs; | ||
for (int i=n; i--; ret[i]+=rhs[i]); | ||
return ret; | ||
} | ||
|
||
template<size_t DIM,typename T>vec<DIM,T> operator-(vec<DIM,T> lhs, const vec<DIM,T>& rhs) { | ||
for (size_t i=DIM; i--; lhs[i]-=rhs[i]); | ||
return lhs; | ||
template<int n> vec<n> operator-(const vec<n>& lhs, const vec<n>& rhs) { | ||
vec<n> ret = lhs; | ||
for (int i=n; i--; ret[i]-=rhs[i]); | ||
return ret; | ||
} | ||
|
||
template<size_t DIM,typename T,typename U> vec<DIM,T> operator*(vec<DIM,T> lhs, const U& rhs) { | ||
for (size_t i=DIM; i--; lhs[i]*=rhs); | ||
return lhs; | ||
template<int n> vec<n> operator*(const double& rhs, const vec<n> &lhs) { | ||
vec<n> ret = lhs; | ||
for (int i=n; i--; ret[i]*=rhs); | ||
return ret; | ||
} | ||
|
||
template<size_t DIM,typename T,typename U> vec<DIM,T> operator/(vec<DIM,T> lhs, const U& rhs) { | ||
for (size_t i=DIM; i--; lhs[i]/=rhs); | ||
return lhs; | ||
template<int n> vec<n> operator*(const vec<n>& lhs, const double& rhs) { | ||
vec<n> ret = lhs; | ||
for (int i=n; i--; ret[i]*=rhs); | ||
return ret; | ||
} | ||
|
||
template<size_t LEN,size_t DIM,typename T> vec<LEN,T> embed(const vec<DIM,T> &v, T fill=1) { | ||
vec<LEN,T> ret; | ||
for (size_t i=LEN; i--; ret[i]=(i<DIM?v[i]:fill)); | ||
template<int n> vec<n> operator/(const vec<n>& lhs, const double& rhs) { | ||
vec<n> ret = lhs; | ||
for (int i=n; i--; ret[i]/=rhs); | ||
return ret; | ||
} | ||
|
||
template<size_t LEN,size_t DIM, typename T> vec<LEN,T> proj(const vec<DIM,T> &v) { | ||
vec<LEN,T> ret; | ||
for (size_t i=LEN; i--; ret[i]=v[i]); | ||
template<int n1,int n2> vec<n1> embed(const vec<n2> &v, double fill=1) { | ||
vec<n1> ret; | ||
for (int i=n1; i--; ret[i]=(i<n2?v[i]:fill)); | ||
return ret; | ||
} | ||
|
||
template <typename T> vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) { | ||
return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); | ||
template<int n1,int n2> vec<n1> proj(const vec<n2> &v) { | ||
vec<n1> ret; | ||
for (int i=n1; i--; ret[i]=v[i]); | ||
return ret; | ||
} | ||
|
||
template <size_t DIM, typename T> std::ostream& operator<<(std::ostream& out, vec<DIM,T>& v) { | ||
for(unsigned int i=0; i<DIM; i++) { | ||
out << v[i] << " " ; | ||
} | ||
return out ; | ||
|
||
template<int n> std::ostream& operator<<(std::ostream& out, const vec<n>& v) { | ||
for (int i=0; i<n; i++) out << v[i] << " "; | ||
return out; | ||
} | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template<size_t DIM,typename T> struct dt { | ||
static T det(const mat<DIM,DIM,T>& src) { | ||
T ret=0; | ||
for (size_t i=DIM; i--; ret += src[0][i]*src.cofactor(0,i)); | ||
return ret; | ||
} | ||
template<> struct vec<2> { | ||
vec() = default; | ||
vec(double X, double Y) : x(X), y(Y) {} | ||
double& operator[](const int i) { assert(i>=0 && i<2); return i==0 ? x : y; } | ||
double operator[](const int i) const { assert(i>=0 && i<2); return i==0 ? x : y; } | ||
double norm2() const { return (*this)*(*this) ; } | ||
double norm() const { return std::sqrt(norm2()); } | ||
vec & normalize() { *this = (*this)/norm(); return *this; } | ||
|
||
double x{}, y{}; | ||
}; | ||
|
||
template<typename T> struct dt<1,T> { | ||
static T det(const mat<1,1,T>& src) { | ||
return src[0][0]; | ||
} | ||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template<> struct vec<3> { | ||
vec() = default; | ||
vec(double X, double Y, double Z) : x(X), y(Y), z(Z) {} | ||
double& operator[](const int i) { assert(i>=0 && i<3); return i==0 ? x : (1==i ? y : z); } | ||
double operator[](const int i) const { assert(i>=0 && i<3); return i==0 ? x : (1==i ? y : z); } | ||
double norm2() const { return (*this)*(*this) ; } | ||
double norm() const { return std::sqrt(norm2()); } | ||
vec & normalize() { *this = (*this)/norm(); return *this; } | ||
|
||
double x{}, y{}, z{}; | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template<size_t DimRows,size_t DimCols,typename T> class mat { | ||
vec<DimCols,T> rows[DimRows]; | ||
public: | ||
mat() {} | ||
template<int n> struct dt; | ||
|
||
vec<DimCols,T>& operator[] (const size_t idx) { | ||
assert(idx<DimRows); | ||
return rows[idx]; | ||
} | ||
template<int nrows,int ncols> struct mat { | ||
vec<ncols> rows[nrows] = {{}}; | ||
|
||
const vec<DimCols,T>& operator[] (const size_t idx) const { | ||
assert(idx<DimRows); | ||
return rows[idx]; | ||
} | ||
mat() = default; | ||
vec<ncols>& operator[] (const int idx) { assert(idx>=0 && idx<nrows); return rows[idx]; } | ||
const vec<ncols>& operator[] (const int idx) const { assert(idx>=0 && idx<nrows); return rows[idx]; } | ||
|
||
vec<DimRows,T> col(const size_t idx) const { | ||
assert(idx<DimCols); | ||
vec<DimRows,T> ret; | ||
for (size_t i=DimRows; i--; ret[i]=rows[i][idx]); | ||
vec<nrows> col(const int idx) const { | ||
assert(idx>=0 && idx<ncols); | ||
vec<nrows> ret; | ||
for (int i=nrows; i--; ret[i]=rows[i][idx]); | ||
return ret; | ||
} | ||
|
||
void set_col(size_t idx, vec<DimRows,T> v) { | ||
assert(idx<DimCols); | ||
for (size_t i=DimRows; i--; rows[i][idx]=v[i]); | ||
void set_col(const int idx, const vec<nrows> &v) { | ||
assert(idx>=0 && idx<ncols); | ||
for (int i=nrows; i--; rows[i][idx]=v[i]); | ||
} | ||
|
||
static mat<DimRows,DimCols,T> identity() { | ||
mat<DimRows,DimCols,T> ret; | ||
for (size_t i=DimRows; i--; ) | ||
for (size_t j=DimCols;j--; ret[i][j]=(i==j)); | ||
static mat<nrows,ncols> identity() { | ||
mat<nrows,ncols> ret; | ||
for (int i=nrows; i--; ) | ||
for (int j=ncols;j--; ret[i][j]=(i==j)); | ||
return ret; | ||
} | ||
|
||
T det() const { | ||
return dt<DimCols,T>::det(*this); | ||
double det() const { | ||
return dt<ncols>::det(*this); | ||
} | ||
|
||
mat<DimRows-1,DimCols-1,T> get_minor(size_t row, size_t col) const { | ||
mat<DimRows-1,DimCols-1,T> ret; | ||
for (size_t i=DimRows-1; i--; ) | ||
for (size_t j=DimCols-1;j--; ret[i][j]=rows[i<row?i:i+1][j<col?j:j+1]); | ||
mat<nrows-1,ncols-1> get_minor(const int row, const int col) const { | ||
mat<nrows-1,ncols-1> ret; | ||
for (int i=nrows-1; i--; ) | ||
for (int j=ncols-1;j--; ret[i][j]=rows[i<row?i:i+1][j<col?j:j+1]); | ||
return ret; | ||
} | ||
|
||
T cofactor(size_t row, size_t col) const { | ||
double cofactor(const int row, const int col) const { | ||
return get_minor(row,col).det()*((row+col)%2 ? -1 : 1); | ||
} | ||
|
||
mat<DimRows,DimCols,T> adjugate() const { | ||
mat<DimRows,DimCols,T> ret; | ||
for (size_t i=DimRows; i--; ) | ||
for (size_t j=DimCols; j--; ret[i][j]=cofactor(i,j)); | ||
mat<nrows,ncols> adjugate() const { | ||
mat<nrows,ncols> ret; | ||
for (int i=nrows; i--; ) | ||
for (int j=ncols; j--; ret[i][j]=cofactor(i,j)); | ||
return ret; | ||
} | ||
|
||
mat<DimRows,DimCols,T> invert_transpose() { | ||
mat<DimRows,DimCols,T> ret = adjugate(); | ||
T tmp = ret[0]*rows[0]; | ||
return ret/tmp; | ||
mat<nrows,ncols> invert_transpose() const { | ||
mat<nrows,ncols> ret = adjugate(); | ||
return ret/(ret[0]*rows[0]); | ||
} | ||
|
||
mat<DimRows,DimCols,T> invert() { | ||
mat<nrows,ncols> invert() const { | ||
return invert_transpose().transpose(); | ||
} | ||
|
||
mat<DimCols,DimRows,T> transpose() { | ||
mat<DimCols,DimRows,T> ret; | ||
for (size_t i=DimCols; i--; ret[i]=this->col(i)); | ||
mat<ncols,nrows> transpose() const { | ||
mat<ncols,nrows> ret; | ||
for (int i=ncols; i--; ret[i]=this->col(i)); | ||
return ret; | ||
} | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
template<size_t DimRows,size_t DimCols,typename T> vec<DimRows,T> operator*(const mat<DimRows,DimCols,T>& lhs, const vec<DimCols,T>& rhs) { | ||
vec<DimRows,T> ret; | ||
for (size_t i=DimRows; i--; ret[i]=lhs[i]*rhs); | ||
template<int nrows,int ncols> vec<nrows> operator*(const mat<nrows,ncols>& lhs, const vec<ncols>& rhs) { | ||
vec<nrows> ret; | ||
for (int i=nrows; i--; ret[i]=lhs[i]*rhs); | ||
return ret; | ||
} | ||
|
||
template<size_t R1,size_t C1,size_t C2,typename T>mat<R1,C2,T> operator*(const mat<R1,C1,T>& lhs, const mat<C1,C2,T>& rhs) { | ||
mat<R1,C2,T> result; | ||
for (size_t i=R1; i--; ) | ||
for (size_t j=C2; j--; result[i][j]=lhs[i]*rhs.col(j)); | ||
template<int R1,int C1,int C2>mat<R1,C2> operator*(const mat<R1,C1>& lhs, const mat<C1,C2>& rhs) { | ||
mat<R1,C2> result; | ||
for (int i=R1; i--; ) | ||
for (int j=C2; j--; result[i][j]=lhs[i]*rhs.col(j)); | ||
return result; | ||
} | ||
|
||
template<int nrows,int ncols>mat<nrows,ncols> operator*(const mat<nrows,ncols>& lhs, const double& val) { | ||
mat<nrows,ncols> result; | ||
for (int i=nrows; i--; result[i] = lhs[i]*val); | ||
return result; | ||
} | ||
|
||
template<size_t DimRows,size_t DimCols,typename T>mat<DimCols,DimRows,T> operator/(mat<DimRows,DimCols,T> lhs, const T& rhs) { | ||
for (size_t i=DimRows; i--; lhs[i]=lhs[i]/rhs); | ||
return lhs; | ||
template<int nrows,int ncols>mat<nrows,ncols> operator/(const mat<nrows,ncols>& lhs, const double& val) { | ||
mat<nrows,ncols> result; | ||
for (int i=nrows; i--; result[i] = lhs[i]/val); | ||
return result; | ||
} | ||
|
||
template <size_t DimRows,size_t DimCols,class T> std::ostream& operator<<(std::ostream& out, mat<DimRows,DimCols,T>& m) { | ||
for (size_t i=0; i<DimRows; i++) out << m[i] << std::endl; | ||
template<int nrows,int ncols>mat<nrows,ncols> operator+(const mat<nrows,ncols>& lhs, const mat<nrows,ncols>& rhs) { | ||
mat<nrows,ncols> result; | ||
for (int i=nrows; i--; ) | ||
for (int j=ncols; j--; result[i][j]=lhs[i][j]+rhs[i][j]); | ||
return result; | ||
} | ||
|
||
template<int nrows,int ncols>mat<nrows,ncols> operator-(const mat<nrows,ncols>& lhs, const mat<nrows,ncols>& rhs) { | ||
mat<nrows,ncols> result; | ||
for (int i=nrows; i--; ) | ||
for (int j=ncols; j--; result[i][j]=lhs[i][j]-rhs[i][j]); | ||
return result; | ||
} | ||
|
||
template<int nrows,int ncols> std::ostream& operator<<(std::ostream& out, const mat<nrows,ncols>& m) { | ||
for (int i=0; i<nrows; i++) out << m[i] << std::endl; | ||
return out; | ||
} | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
typedef vec<2, float> Vec2f; | ||
typedef vec<2, int> Vec2i; | ||
typedef vec<3, float> Vec3f; | ||
typedef vec<3, int> Vec3i; | ||
typedef vec<4, float> Vec4f; | ||
typedef mat<4,4,float> Matrix; | ||
template<int n> struct dt { | ||
static double det(const mat<n,n>& src) { | ||
double ret = 0; | ||
for (int i=n; i--; ret += src[0][i]*src.cofactor(0,i)); | ||
return ret; | ||
} | ||
}; | ||
|
||
template<> struct dt<1> { | ||
static double det(const mat<1,1>& src) { | ||
return src[0][0]; | ||
} | ||
}; | ||
|
||
///////////////////////////////////////////////////////////////////////////////// | ||
|
||
typedef vec<2> vec2; | ||
typedef vec<3> vec3; | ||
typedef vec<4> vec4; | ||
typedef mat<4,4> mat44; | ||
vec3 cross(const vec3 &v1, const vec3 &v2); | ||
|
||
#endif //__GEOMETRY_H__ | ||
|
Oops, something went wrong.