Code-style consistency improvement:

Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
This commit is contained in:
erwincoumans
2018-09-23 14:17:31 -07:00
parent b73b05e9fb
commit ab8f16961e
1773 changed files with 1081087 additions and 474249 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -7,60 +7,58 @@
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btVector3.h"
#include "tgaimage.h"
struct TinyRenderObjectData
{
//Camera
Matrix m_viewMatrix;
Matrix m_projectionMatrix;
Matrix m_viewportMatrix;
//Camera
Matrix m_viewMatrix;
Matrix m_projectionMatrix;
Matrix m_viewportMatrix;
btVector3 m_localScaling;
btVector3 m_lightDirWorld;
btVector3 m_lightColor;
float m_lightDistance;
float m_lightAmbientCoeff;
float m_lightDiffuseCoeff;
float m_lightSpecularCoeff;
//Model (vertices, indices, textures, shader)
Matrix m_modelMatrix;
class Model* m_model;
//class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader
//Output
TGAImage& m_rgbColorBuffer;
b3AlignedObjectArray<float>& m_depthBuffer;//required, hence a reference
b3AlignedObjectArray<float>* m_shadowBuffer;//optional, hence a pointer
b3AlignedObjectArray<int>* m_segmentationMaskBufferPtr;//optional, hence a pointer
TinyRenderObjectData(TGAImage& rgbColorBuffer,b3AlignedObjectArray<float>&depthBuffer);
TinyRenderObjectData(TGAImage& rgbColorBuffer,b3AlignedObjectArray<float>&depthBuffer,b3AlignedObjectArray<int>* segmentationMaskBuffer,int objectIndex);
TinyRenderObjectData(TGAImage& rgbColorBuffer,b3AlignedObjectArray<float>&depthBuffer,b3AlignedObjectArray<float>* shadowBuffer);
TinyRenderObjectData(TGAImage& rgbColorBuffer,b3AlignedObjectArray<float>&depthBuffer,b3AlignedObjectArray<float>* shadowBuffer, b3AlignedObjectArray<int>* segmentationMaskBuffer,int objectIndex, int linkIndex);
virtual ~TinyRenderObjectData();
void loadModel(const char* fileName);
void createCube(float HalfExtentsX,float HalfExtentsY,float HalfExtentsZ);
void registerMeshShape(const float* vertices, int numVertices,const int* indices, int numIndices, const float rgbaColor[4],
unsigned char* textureImage=0, int textureWidth=0, int textureHeight=0);
void registerMesh2(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& normals,btAlignedObjectArray<int>& indices);
void* m_userData;
int m_userIndex;
int m_objectIndex;
int m_linkIndex;
};
btVector3 m_lightColor;
float m_lightDistance;
float m_lightAmbientCoeff;
float m_lightDiffuseCoeff;
float m_lightSpecularCoeff;
//Model (vertices, indices, textures, shader)
Matrix m_modelMatrix;
class Model* m_model;
//class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader
//Output
TGAImage& m_rgbColorBuffer;
b3AlignedObjectArray<float>& m_depthBuffer; //required, hence a reference
b3AlignedObjectArray<float>* m_shadowBuffer; //optional, hence a pointer
b3AlignedObjectArray<int>* m_segmentationMaskBufferPtr; //optional, hence a pointer
TinyRenderObjectData(TGAImage& rgbColorBuffer, b3AlignedObjectArray<float>& depthBuffer);
TinyRenderObjectData(TGAImage& rgbColorBuffer, b3AlignedObjectArray<float>& depthBuffer, b3AlignedObjectArray<int>* segmentationMaskBuffer, int objectIndex);
TinyRenderObjectData(TGAImage& rgbColorBuffer, b3AlignedObjectArray<float>& depthBuffer, b3AlignedObjectArray<float>* shadowBuffer);
TinyRenderObjectData(TGAImage& rgbColorBuffer, b3AlignedObjectArray<float>& depthBuffer, b3AlignedObjectArray<float>* shadowBuffer, b3AlignedObjectArray<int>* segmentationMaskBuffer, int objectIndex, int linkIndex);
virtual ~TinyRenderObjectData();
void loadModel(const char* fileName);
void createCube(float HalfExtentsX, float HalfExtentsY, float HalfExtentsZ);
void registerMeshShape(const float* vertices, int numVertices, const int* indices, int numIndices, const float rgbaColor[4],
unsigned char* textureImage = 0, int textureWidth = 0, int textureHeight = 0);
void registerMesh2(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& normals, btAlignedObjectArray<int>& indices);
void* m_userData;
int m_userIndex;
int m_objectIndex;
int m_linkIndex;
};
class TinyRenderer
{
public:
static void renderObjectDepth(TinyRenderObjectData& renderData);
static void renderObject(TinyRenderObjectData& renderData);
public:
static void renderObjectDepth(TinyRenderObjectData& renderData);
static void renderObject(TinyRenderObjectData& renderData);
};
#endif // TINY_RENDERER_Hbla
#endif // TINY_RENDERER_Hbla

View File

@@ -1,7 +1,22 @@
#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) {}
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)
{
}

View File

@@ -4,86 +4,149 @@
#include <cassert>
#include <stdlib.h>
template <size_t DimCols, size_t DimRows, typename T>
class mat;
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];
}
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];
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; }
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;
T x, y;
};
/////////////////////////////////////////////////////////////////////////////////
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; }
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;
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]);
return ret;
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])
;
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 <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<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 <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<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 <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<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 <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<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));
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))
;
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]);
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])
;
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 <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);
}
#if 0
template <size_t DIM, typename T> std::ostream& operator<<(std::ostream& out, vec<DIM,T>& v) {
@@ -95,113 +158,150 @@ template <size_t DIM, typename T> std::ostream& operator<<(std::ostream& out, ve
#endif
/////////////////////////////////////////////////////////////////////////////////
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 <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<typename T> struct dt<1,T> {
static T det(const mat<1,1,T>& src) {
return src[0][0];
}
template <typename T>
struct dt<1, T>
{
static T det(const mat<1, 1, T>& src)
{
return src[0][0];
}
};
/////////////////////////////////////////////////////////////////////////////////
template<size_t DimRows,size_t DimCols,typename T> class mat {
vec<DimCols,T> rows[DimRows];
template <size_t DimRows, size_t DimCols, typename T>
class mat
{
vec<DimCols, T> rows[DimRows];
public:
mat() {}
mat() {}
vec<DimCols,T>& operator[] (const size_t idx) {
assert(idx<DimRows);
return rows[idx];
}
vec<DimCols, T>& operator[](const size_t idx)
{
assert(idx < DimRows);
return rows[idx];
}
const vec<DimCols,T>& operator[] (const size_t idx) const {
assert(idx<DimRows);
return rows[idx];
}
const vec<DimCols, T>& operator[](const size_t idx) const
{
assert(idx < DimRows);
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]);
return ret;
}
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])
;
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(size_t idx, vec<DimRows, T> v)
{
assert(idx < DimCols);
for (size_t i = DimRows; 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));
return ret;
}
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))
;
return ret;
}
T det() const {
return dt<DimCols,T>::det(*this);
}
T det() const
{
return dt<DimCols, T>::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]);
return ret;
}
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])
;
return ret;
}
T cofactor(size_t row, size_t col) const {
return get_minor(row,col).det()*((row+col)%2 ? -1 : 1);
}
T cofactor(size_t row, size_t 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));
return ret;
}
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))
;
return ret;
}
mat<DimRows,DimCols,T> invert_transpose() {
mat<DimRows,DimCols,T> ret = adjugate();
T tmp = ret[0]*rows[0];
return ret/tmp;
}
mat<DimRows, DimCols, T> invert_transpose()
{
mat<DimRows, DimCols, T> ret = adjugate();
T tmp = ret[0] * rows[0];
return ret / tmp;
}
mat<DimRows,DimCols,T> invert() {
return invert_transpose().transpose();
}
mat<DimRows, DimCols, T> invert()
{
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));
return ret;
}
mat<DimCols, DimRows, T> transpose()
{
mat<DimCols, DimRows, T> ret;
for (size_t i = DimCols; 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);
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)
;
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));
return result;
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))
;
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 <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;
}
#if 0
@@ -212,11 +312,10 @@ template <size_t DimRows,size_t DimCols,class T> std::ostream& operator<<(std::o
#endif
/////////////////////////////////////////////////////////////////////////////////
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;
#endif //__GEOMETRY_H__
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;
#endif //__GEOMETRY_H__

View File

@@ -16,60 +16,57 @@ static b3MouseButtonCallback sOldMouseButtonCB = 0;
static b3KeyboardCallback sOldKeyboardCB = 0;
//static b3RenderCallback sOldRenderCB = 0;
float gWidth = 0 ;
float gWidth = 0;
float gHeight = 0;
void MyWheelCallback(float deltax, float deltay)
{
if (sOldWheelCB)
sOldWheelCB(deltax,deltay);
sOldWheelCB(deltax, deltay);
}
void MyResizeCallback( float width, float height)
void MyResizeCallback(float width, float height)
{
gWidth = width;
gHeight = height;
gWidth = width;
gHeight = height;
if (sOldResizeCB)
sOldResizeCB(width,height);
sOldResizeCB(width, height);
}
void MyMouseMoveCallback( float x, float y)
void MyMouseMoveCallback(float x, float y)
{
printf("Mouse Move: %f, %f\n", x,y);
printf("Mouse Move: %f, %f\n", x, y);
if (sOldMouseMoveCB)
sOldMouseMoveCB(x,y);
sOldMouseMoveCB(x, y);
}
void MyMouseButtonCallback(int button, int state, float x, float y)
{
if (sOldMouseButtonCB)
sOldMouseButtonCB(button,state,x,y);
sOldMouseButtonCB(button, state, x, y);
}
void MyKeyboardCallback(int keycode, int state)
{
//keycodes are in examples/CommonInterfaces/CommonWindowInterface.h
//for example B3G_ESCAPE for escape key
//state == 1 for pressed, state == 0 for released.
// use app->m_window->isModifiedPressed(...) to check for shift, escape and alt keys
printf("MyKeyboardCallback received key:%c in state %d\n",keycode,state);
printf("MyKeyboardCallback received key:%c in state %d\n", keycode, state);
if (sOldKeyboardCB)
sOldKeyboardCB(keycode,state);
sOldKeyboardCB(keycode, state);
}
#include "TinyRenderer.h"
int main(int argc, char* argv[])
{
b3CommandLineArgs myArgs(argc,argv);
b3CommandLineArgs myArgs(argc, argv);
SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App", 640, 480, true);
SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",640,480,true);
app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13);
app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0);
app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0);
sOldKeyboardCB = app->m_window->getKeyboardCallback();
app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0, 0, 0);
sOldKeyboardCB = app->m_window->getKeyboardCallback();
app->m_window->setKeyboardCallback(MyKeyboardCallback);
sOldMouseMoveCB = app->m_window->getMouseMoveCallback();
app->m_window->setMouseMoveCallback(MyMouseMoveCallback);
@@ -79,159 +76,149 @@ int main(int argc, char* argv[])
app->m_window->setWheelCallback(MyWheelCallback);
sOldResizeCB = app->m_window->getResizeCallback();
app->m_window->setResizeCallback(MyResizeCallback);
int textureWidth = gWidth;
int textureHeight = gHeight;
TGAImage rgbColorBuffer(gWidth,gHeight,TGAImage::RGB);
b3AlignedObjectArray<float> depthBuffer;
depthBuffer.resize(gWidth*gHeight);
TinyRenderObjectData renderData(rgbColorBuffer,depthBuffer);//, "african_head/african_head.obj");//floor.obj");
int textureWidth = gWidth;
int textureHeight = gHeight;
TGAImage rgbColorBuffer(gWidth, gHeight, TGAImage::RGB);
b3AlignedObjectArray<float> depthBuffer;
depthBuffer.resize(gWidth * gHeight);
TinyRenderObjectData renderData(rgbColorBuffer, depthBuffer); //, "african_head/african_head.obj");//floor.obj");
//renderData.loadModel("african_head/african_head.obj");
renderData.loadModel("floor.obj");
//renderData.createCube(1,1,1);
myArgs.GetCmdLineArgument("mp4_file",gVideoFileName);
if (gVideoFileName)
app->dumpFramesToVideo(gVideoFileName);
myArgs.GetCmdLineArgument("png_file",gPngFileName);
char fileName[1024];
unsigned char* image=new unsigned char[textureWidth*textureHeight*4];
int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight);
myArgs.GetCmdLineArgument("mp4_file", gVideoFileName);
if (gVideoFileName)
app->dumpFramesToVideo(gVideoFileName);
myArgs.GetCmdLineArgument("png_file", gPngFileName);
char fileName[1024];
unsigned char* image = new unsigned char[textureWidth * textureHeight * 4];
int textureHandle = app->m_renderer->registerTexture(image, textureWidth, textureHeight);
int cubeIndex = app->registerCubeShape(1, 1, 1);
b3Vector3 pos = b3MakeVector3(0, 0, 0);
b3Quaternion orn(0, 0, 0, 1);
b3Vector3 color = b3MakeVector3(1, 0, 0);
b3Vector3 scaling = b3MakeVector3(1, 1, 1);
app->m_renderer->registerGraphicsInstance(cubeIndex, pos, orn, color, scaling);
app->m_renderer->writeTransforms();
int cubeIndex = app->registerCubeShape(1,1,1);
b3Vector3 pos = b3MakeVector3(0,0,0);
b3Quaternion orn(0,0,0,1);
b3Vector3 color=b3MakeVector3(1,0,0);
b3Vector3 scaling=b3MakeVector3 (1,1,1);
app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling);
app->m_renderer->writeTransforms();
do
{
static int frameCount = 0;
static int frameCount = 0;
frameCount++;
if (gPngFileName)
{
printf("gPngFileName=%s\n",gPngFileName);
{
printf("gPngFileName=%s\n", gPngFileName);
sprintf(fileName,"%s%d.png",gPngFileName,frameCount++);
app->dumpNextFrameToPng(fileName);
}
app->m_instancingRenderer->init();
sprintf(fileName, "%s%d.png", gPngFileName, frameCount++);
app->dumpNextFrameToPng(fileName);
}
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera();
///clear the color and z (depth) buffer
for(int y=0;y<textureHeight;++y)
{
unsigned char* pi=image+(y)*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
TGAColor color;
color.bgra[0] = 255;
color.bgra[1] = 255;
color.bgra[2] = 255;
color.bgra[3] = 255;
renderData.m_rgbColorBuffer.set(x,y,color);
renderData.m_depthBuffer[x+y*textureWidth] = -1e30f;
}
}
float projMat[16];
app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat);
float viewMat[16];
app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat);
B3_ATTRIBUTE_ALIGNED16(float modelMat[16]);
//sync the object transform
b3Transform tr;
tr.setIdentity();
static float posUp = 0.f;
// posUp += 0.001;
b3Vector3 org = b3MakeVector3(0,posUp,0);
tr.setOrigin(org);
tr.getOpenGLMatrix(modelMat);
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
renderData.m_viewMatrix[i][j] = viewMat[i+4*j];
renderData.m_modelMatrix[i][j] = modelMat[i+4*j];
}
}
//render the object
TinyRenderer::renderObject(renderData);
#if 1
//update the texels of the texture using a simple pattern, animated using frame index
for(int y=0;y<textureHeight;++y)
{
unsigned char* pi=image+(y)*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
TGAColor color = renderData.m_rgbColorBuffer.get(x,y);
///clear the color and z (depth) buffer
for (int y = 0; y < textureHeight; ++y)
{
unsigned char* pi = image + (y)*textureWidth * 3;
for (int x = 0; x < textureWidth; ++x)
{
TGAColor color;
color.bgra[0] = 255;
color.bgra[1] = 255;
color.bgra[2] = 255;
color.bgra[3] = 255;
renderData.m_rgbColorBuffer.set(x, y, color);
renderData.m_depthBuffer[x + y * textureWidth] = -1e30f;
}
}
float projMat[16];
app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat);
float viewMat[16];
app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat);
B3_ATTRIBUTE_ALIGNED16(float modelMat[16]);
//sync the object transform
b3Transform tr;
tr.setIdentity();
static float posUp = 0.f;
// posUp += 0.001;
b3Vector3 org = b3MakeVector3(0, posUp, 0);
tr.setOrigin(org);
tr.getOpenGLMatrix(modelMat);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
renderData.m_viewMatrix[i][j] = viewMat[i + 4 * j];
renderData.m_modelMatrix[i][j] = modelMat[i + 4 * j];
}
}
//render the object
TinyRenderer::renderObject(renderData);
#if 1
//update the texels of the texture using a simple pattern, animated using frame index
for (int y = 0; y < textureHeight; ++y)
{
unsigned char* pi = image + (y)*textureWidth * 3;
for (int x = 0; x < textureWidth; ++x)
{
TGAColor color = renderData.m_rgbColorBuffer.get(x, y);
pi[0] = color.bgra[2];
pi[1] = color.bgra[1];
pi[2] = color.bgra[0];
pi[3] = 255;
pi+=3;
}
}
#else
//update the texels of the texture using a simple pattern, animated using frame index
for(int y=0;y<textureHeight;++y)
{
const int t=(y+frameCount)>>4;
unsigned char* pi=image+y*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
TGAColor color = renderData.m_rgbColorBuffer.get(x,y);
pi += 3;
}
}
#else
const int s=x>>4;
const unsigned char b=180;
unsigned char c=b+((s+(t&1))&1)*(255-b);
pi[0]=pi[1]=pi[2]=pi[3]=c;
pi+=3;
}
}
#endif
app->m_renderer->activateTexture(textureHandle);
app->m_renderer->updateTexture(textureHandle,image);
float color[4] = {1,1,1,1};
app->m_primRenderer->drawTexturedRect(0,0,gWidth/3,gHeight/3,color,0,0,1,1,true);
app->m_renderer->renderScene();
//update the texels of the texture using a simple pattern, animated using frame index
for (int y = 0; y < textureHeight; ++y)
{
const int t = (y + frameCount) >> 4;
unsigned char* pi = image + y * textureWidth * 3;
for (int x = 0; x < textureWidth; ++x)
{
TGAColor color = renderData.m_rgbColorBuffer.get(x, y);
const int s = x >> 4;
const unsigned char b = 180;
unsigned char c = b + ((s + (t & 1)) & 1) * (255 - b);
pi[0] = pi[1] = pi[2] = pi[3] = c;
pi += 3;
}
}
#endif
app->m_renderer->activateTexture(textureHandle);
app->m_renderer->updateTexture(textureHandle, image);
float color[4] = {1, 1, 1, 1};
app->m_primRenderer->drawTexturedRect(0, 0, gWidth / 3, gHeight / 3, color, 0, 0, 1, 1, true);
app->m_renderer->renderScene();
app->drawGrid();
char bla[1024];
sprintf(bla,"Simple test frame %d", frameCount);
sprintf(bla, "Simple test frame %d", frameCount);
app->drawText(bla,10,10);
app->drawText(bla, 10, 10);
app->swapBuffer();
} while (!app->m_window->requestedExit());
delete app;
return 0;
}

View File

@@ -4,53 +4,63 @@
#include <sstream>
#include "model.h"
#include "Bullet3Common/b3Logging.h"
#include <string.h> // memcpy
Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_() {
std::ifstream in;
in.open (filename, std::ifstream::in);
if (in.fail()) return;
std::string line;
while (!in.eof()) {
std::getline(in, line);
std::istringstream iss(line.c_str());
char trash;
if (!line.compare(0, 2, "v ")) {
iss >> trash;
Vec3f v;
for (int i=0;i<3;i++) iss >> v[i];
verts_.push_back(v);
} else if (!line.compare(0, 3, "vn ")) {
iss >> trash >> trash;
Vec3f n;
for (int i=0;i<3;i++) iss >> n[i];
norms_.push_back(n);
} else if (!line.compare(0, 3, "vt ")) {
iss >> trash >> trash;
Vec2f uv;
for (int i=0;i<2;i++) iss >> uv[i];
uv_.push_back(uv);
} else if (!line.compare(0, 2, "f ")) {
std::vector<Vec3i> f;
Vec3i tmp;
iss >> trash;
while (iss >> tmp[0] >> trash >> tmp[1] >> trash >> tmp[2]) {
for (int i=0; i<3; i++) tmp[i]--; // in wavefront obj all indices start at 1, not zero
f.push_back(tmp);
}
faces_.push_back(f);
}
}
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
load_texture(filename, "_spec.tga", specularmap_);
#include <string.h> // memcpy
Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_()
{
std::ifstream in;
in.open(filename, std::ifstream::in);
if (in.fail()) return;
std::string line;
while (!in.eof())
{
std::getline(in, line);
std::istringstream iss(line.c_str());
char trash;
if (!line.compare(0, 2, "v "))
{
iss >> trash;
Vec3f v;
for (int i = 0; i < 3; i++) iss >> v[i];
verts_.push_back(v);
}
else if (!line.compare(0, 3, "vn "))
{
iss >> trash >> trash;
Vec3f n;
for (int i = 0; i < 3; i++) iss >> n[i];
norms_.push_back(n);
}
else if (!line.compare(0, 3, "vt "))
{
iss >> trash >> trash;
Vec2f uv;
for (int i = 0; i < 2; i++) iss >> uv[i];
uv_.push_back(uv);
}
else if (!line.compare(0, 2, "f "))
{
std::vector<Vec3i> f;
Vec3i tmp;
iss >> trash;
while (iss >> tmp[0] >> trash >> tmp[1] >> trash >> tmp[2])
{
for (int i = 0; i < 3; i++) tmp[i]--; // in wavefront obj all indices start at 1, not zero
f.push_back(tmp);
}
faces_.push_back(f);
}
}
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
load_texture(filename, "_spec.tga", specularmap_);
}
Model::Model():verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_()
Model::Model() : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_()
{
}
void Model::setDiffuseTextureFromData(unsigned char* textureImage,int textureWidth,int textureHeight)
void Model::setDiffuseTextureFromData(unsigned char *textureImage, int textureWidth, int textureHeight)
{
{
B3_PROFILE("new TGAImage");
@@ -62,7 +72,7 @@ void Model::setDiffuseTextureFromData(unsigned char* textureImage,int textureWid
color.bytespp = 3;
{
B3_PROFILE("copy texels");
memcpy(diffusemap_.buffer(), textureImage, textureHeight*textureWidth * 3);
memcpy(diffusemap_.buffer(), textureImage, textureHeight * textureWidth * 3);
}
{
B3_PROFILE("flip_vertically");
@@ -70,9 +80,9 @@ void Model::setDiffuseTextureFromData(unsigned char* textureImage,int textureWid
}
}
void Model::loadDiffuseTexture(const char* relativeFileName)
void Model::loadDiffuseTexture(const char *relativeFileName)
{
diffusemap_.read_tga_file(relativeFileName);
diffusemap_.read_tga_file(relativeFileName);
}
void Model::reserveMemory(int numVertices, int numIndices)
@@ -83,99 +93,108 @@ void Model::reserveMemory(int numVertices, int numIndices)
faces_.reserve(numIndices);
}
void Model::addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v)
void Model::addVertex(float x, float y, float z, float normalX, float normalY, float normalZ, float u, float v)
{
verts_.push_back(Vec3f(x,y,z));
norms_.push_back(Vec3f(normalX,normalY,normalZ));
uv_.push_back(Vec2f(u,v));
verts_.push_back(Vec3f(x, y, z));
norms_.push_back(Vec3f(normalX, normalY, normalZ));
uv_.push_back(Vec2f(u, v));
}
void Model::addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0,
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2)
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2)
{
std::vector<Vec3i> f;
f.push_back(Vec3i(vertexposIndex0, normalIndex0, uvIndex0));
f.push_back(Vec3i(vertexposIndex1, normalIndex1, uvIndex1));
f.push_back(Vec3i(vertexposIndex2, normalIndex2, uvIndex2));
faces_.push_back(f);
std::vector<Vec3i> f;
f.push_back(Vec3i(vertexposIndex0, normalIndex0, uvIndex0));
f.push_back(Vec3i(vertexposIndex1, normalIndex1, uvIndex1));
f.push_back(Vec3i(vertexposIndex2, normalIndex2, uvIndex2));
faces_.push_back(f);
}
Model::~Model() {}
int Model::nverts() {
return (int)verts_.size();
int Model::nverts()
{
return (int)verts_.size();
}
int Model::nfaces() {
return (int)faces_.size();
int Model::nfaces()
{
return (int)faces_.size();
}
std::vector<int> Model::face(int idx) {
std::vector<int> face;
for (int i=0; i<(int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]);
return face;
std::vector<int> Model::face(int idx)
{
std::vector<int> face;
for (int i = 0; i < (int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]);
return face;
}
Vec3f Model::vert(int i) {
return verts_[i];
Vec3f Model::vert(int i)
{
return verts_[i];
}
Vec3f Model::vert(int iface, int nthvert) {
return verts_[faces_[iface][nthvert][0]];
Vec3f Model::vert(int iface, int nthvert)
{
return verts_[faces_[iface][nthvert][0]];
}
void Model::load_texture(std::string filename, const char *suffix, TGAImage &img) {
std::string texfile(filename);
size_t dot = texfile.find_last_of(".");
if (dot!=std::string::npos) {
texfile = texfile.substr(0,dot) + std::string(suffix);
std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl;
img.flip_vertically();
}
void Model::load_texture(std::string filename, const char *suffix, TGAImage &img)
{
std::string texfile(filename);
size_t dot = texfile.find_last_of(".");
if (dot != std::string::npos)
{
texfile = texfile.substr(0, dot) + std::string(suffix);
std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl;
img.flip_vertically();
}
}
TGAColor Model::diffuse(Vec2f uvf) {
if (diffusemap_.get_width() && diffusemap_.get_height())
{
TGAColor Model::diffuse(Vec2f uvf)
{
if (diffusemap_.get_width() && diffusemap_.get_height())
{
double val;
// bool repeat = true;
// if (repeat)
// bool repeat = true;
// if (repeat)
{
uvf[0] = modf(uvf[0],&val);
uvf[1] = modf(uvf[1],&val);
uvf[0] = modf(uvf[0], &val);
uvf[1] = modf(uvf[1], &val);
}
Vec2i uv(uvf[0]*diffusemap_.get_width(), uvf[1]*diffusemap_.get_height());
return diffusemap_.get(uv[0], uv[1]);
}
return TGAColor(255,255,255,255);
Vec2i uv(uvf[0] * diffusemap_.get_width(), uvf[1] * diffusemap_.get_height());
return diffusemap_.get(uv[0], uv[1]);
}
return TGAColor(255, 255, 255, 255);
}
Vec3f Model::normal(Vec2f uvf) {
Vec2i uv(uvf[0]*normalmap_.get_width(), uvf[1]*normalmap_.get_height());
TGAColor c = normalmap_.get(uv[0], uv[1]);
Vec3f res;
for (int i=0; i<3; i++)
res[2-i] = (float)c[i]/255.f*2.f - 1.f;
return res;
Vec3f Model::normal(Vec2f uvf)
{
Vec2i uv(uvf[0] * normalmap_.get_width(), uvf[1] * normalmap_.get_height());
TGAColor c = normalmap_.get(uv[0], uv[1]);
Vec3f res;
for (int i = 0; i < 3; i++)
res[2 - i] = (float)c[i] / 255.f * 2.f - 1.f;
return res;
}
Vec2f Model::uv(int iface, int nthvert) {
return uv_[faces_[iface][nthvert][1]];
Vec2f Model::uv(int iface, int nthvert)
{
return uv_[faces_[iface][nthvert][1]];
}
float Model::specular(Vec2f uvf) {
float Model::specular(Vec2f uvf)
{
if (specularmap_.get_width() && specularmap_.get_height())
{
Vec2i uv(uvf[0]*specularmap_.get_width(), uvf[1]*specularmap_.get_height());
return specularmap_.get(uv[0], uv[1])[0]/1.f;
Vec2i uv(uvf[0] * specularmap_.get_width(), uvf[1] * specularmap_.get_height());
return specularmap_.get(uv[0], uv[1])[0] / 1.f;
}
return 2.0;
}
Vec3f Model::normal(int iface, int nthvert) {
int idx = faces_[iface][nthvert][2];
return norms_[idx].normalize();
Vec3f Model::normal(int iface, int nthvert)
{
int idx = faces_[iface][nthvert][2];
return norms_[idx].normalize();
}

View File

@@ -5,50 +5,51 @@
#include "geometry.h"
#include "tgaimage.h"
class Model {
class Model
{
private:
std::vector<Vec3f> verts_;
std::vector<std::vector<Vec3i> > faces_; // attention, this Vec3i means vertex/uv/normal
std::vector<Vec3f> norms_;
std::vector<Vec2f> uv_;
TGAImage diffusemap_;
TGAImage normalmap_;
TGAImage specularmap_;
Vec4f m_colorRGBA;
void load_texture(std::string filename, const char *suffix, TGAImage &img);
public:
Model(const char *filename);
Model();
void setColorRGBA(const float rgba[4])
{
for (int i=0;i<4;i++)
m_colorRGBA[i] = rgba[i];
}
const Vec4f& getColorRGBA() const
{
return m_colorRGBA;
}
void loadDiffuseTexture(const char* relativeFileName);
void setDiffuseTextureFromData(unsigned char* textureImage,int textureWidth,int textureHeight);
void reserveMemory(int numVertices, int numIndices);
void addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v);
void addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0,
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2);
~Model();
int nverts();
int nfaces();
Vec3f normal(int iface, int nthvert);
Vec3f normal(Vec2f uv);
Vec3f vert(int i);
Vec3f vert(int iface, int nthvert);
Vec2f uv(int iface, int nthvert);
TGAColor diffuse(Vec2f uv);
float specular(Vec2f uv);
std::vector<int> face(int idx);
};
#endif //__MODEL_H__
std::vector<Vec3f> verts_;
std::vector<std::vector<Vec3i> > faces_; // attention, this Vec3i means vertex/uv/normal
std::vector<Vec3f> norms_;
std::vector<Vec2f> uv_;
TGAImage diffusemap_;
TGAImage normalmap_;
TGAImage specularmap_;
Vec4f m_colorRGBA;
void load_texture(std::string filename, const char* suffix, TGAImage& img);
public:
Model(const char* filename);
Model();
void setColorRGBA(const float rgba[4])
{
for (int i = 0; i < 4; i++)
m_colorRGBA[i] = rgba[i];
}
const Vec4f& getColorRGBA() const
{
return m_colorRGBA;
}
void loadDiffuseTexture(const char* relativeFileName);
void setDiffuseTextureFromData(unsigned char* textureImage, int textureWidth, int textureHeight);
void reserveMemory(int numVertices, int numIndices);
void addVertex(float x, float y, float z, float normalX, float normalY, float normalZ, float u, float v);
void addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0,
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2);
~Model();
int nverts();
int nfaces();
Vec3f normal(int iface, int nthvert);
Vec3f normal(Vec2f uv);
Vec3f vert(int i);
Vec3f vert(int iface, int nthvert);
Vec2f uv(int iface, int nthvert);
TGAColor diffuse(Vec2f uv);
float specular(Vec2f uv);
std::vector<int> face(int idx);
};
#endif //__MODEL_H__

View File

@@ -6,193 +6,202 @@
IShader::~IShader() {}
Matrix viewport(int x, int y, int w, int h)
Matrix viewport(int x, int y, int w, int h)
{
Matrix Viewport;
Viewport = Matrix::identity();
Viewport[0][3] = x+w/2.f;
Viewport[1][3] = y+h/2.f;
Viewport[2][3] = .5f;
Viewport[0][0] = w/2.f;
Viewport[1][1] = h/2.f;
Viewport[2][2] = .5f;
return Viewport;
Matrix Viewport;
Viewport = Matrix::identity();
Viewport[0][3] = x + w / 2.f;
Viewport[1][3] = y + h / 2.f;
Viewport[2][3] = .5f;
Viewport[0][0] = w / 2.f;
Viewport[1][1] = h / 2.f;
Viewport[2][2] = .5f;
return Viewport;
}
Matrix projection(float coeff) {
Matrix Projection;
Projection = Matrix::identity();
Projection[3][2] = coeff;
return Projection;
}
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) {
Vec3f f = (center - eye).normalize();
Vec3f u = up.normalize();
Vec3f s = cross(f,u).normalize();
u = cross(s,f);
Matrix ModelView;
ModelView[0][0] = s.x;
ModelView[0][1] = s.y;
ModelView[0][2] = s.z;
ModelView[1][0] = u.x;
ModelView[1][1] = u.y;
ModelView[1][2] = u.z;
ModelView[2][0] =-f.x;
ModelView[2][1] =-f.y;
ModelView[2][2] =-f.z;
ModelView[3][0] = 0.f;
ModelView[3][1] = 0.f;
ModelView[3][2] = 0.f;
ModelView[0][3] = -(s[0]*eye[0]+s[1]*eye[1]+s[2]*eye[2]);
ModelView[1][3] = -(u[0]*eye[0]+u[1]*eye[1]+u[2]*eye[2]);
ModelView[2][3] = f[0]*eye[0]+f[1]*eye[1]+f[2]*eye[2];
ModelView[3][3] = 1.f;
return ModelView;
}
Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) {
Vec3f s[2];
for (int i=2; i--; ) {
s[i][0] = C[i]-A[i];
s[i][1] = B[i]-A[i];
s[i][2] = A[i]-P[i];
}
Vec3f u = cross(s[0], s[1]);
if (std::abs(u[2])>1e-2) // dont forget that u[2] is integer. If it is zero then triangle ABC is degenerate
return Vec3f(1.f-(u.x+u.y)/u.z, u.y/u.z, u.x/u.z);
return Vec3f(-1,1,1); // in this case generate negative coordinates, it will be thrown away by the rasterizator
}
void triangleClipped(mat<4,3,float> &clipc, mat<4,3,float> &orgClipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix)
Matrix projection(float coeff)
{
triangleClipped(clipc, orgClipc,shader,image,zbuffer,0,viewPortMatrix,0);
Matrix Projection;
Projection = Matrix::identity();
Projection[3][2] = coeff;
return Projection;
}
void triangleClipped(mat<4,3,float> &clipc, mat<4,3,float> &orgClipc, IShader &shader, TGAImage &image, float *zbuffer, int* segmentationMaskBuffer, const Matrix& viewPortMatrix, int objectAndLinkIndex)
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up)
{
Vec3f f = (center - eye).normalize();
Vec3f u = up.normalize();
Vec3f s = cross(f, u).normalize();
u = cross(s, f);
mat<3,4,float> screenSpacePts = (viewPortMatrix*clipc).transpose(); // transposed to ease access to each of the points
mat<3,2,float> pts2;
for (int i=0; i<3; i++)
Matrix ModelView;
ModelView[0][0] = s.x;
ModelView[0][1] = s.y;
ModelView[0][2] = s.z;
ModelView[1][0] = u.x;
ModelView[1][1] = u.y;
ModelView[1][2] = u.z;
ModelView[2][0] = -f.x;
ModelView[2][1] = -f.y;
ModelView[2][2] = -f.z;
ModelView[3][0] = 0.f;
ModelView[3][1] = 0.f;
ModelView[3][2] = 0.f;
ModelView[0][3] = -(s[0] * eye[0] + s[1] * eye[1] + s[2] * eye[2]);
ModelView[1][3] = -(u[0] * eye[0] + u[1] * eye[1] + u[2] * eye[2]);
ModelView[2][3] = f[0] * eye[0] + f[1] * eye[1] + f[2] * eye[2];
ModelView[3][3] = 1.f;
return ModelView;
}
Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P)
{
Vec3f s[2];
for (int i = 2; i--;)
{
pts2[i] = proj<2>(screenSpacePts[i]/screenSpacePts[i][3]);
s[i][0] = C[i] - A[i];
s[i][1] = B[i] - A[i];
s[i][2] = A[i] - P[i];
}
Vec3f u = cross(s[0], s[1]);
if (std::abs(u[2]) > 1e-2) // dont forget that u[2] is integer. If it is zero then triangle ABC is degenerate
return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
return Vec3f(-1, 1, 1); // in this case generate negative coordinates, it will be thrown away by the rasterizator
}
void triangleClipped(mat<4, 3, float> &clipc, mat<4, 3, float> &orgClipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix &viewPortMatrix)
{
triangleClipped(clipc, orgClipc, shader, image, zbuffer, 0, viewPortMatrix, 0);
}
void triangleClipped(mat<4, 3, float> &clipc, mat<4, 3, float> &orgClipc, IShader &shader, TGAImage &image, float *zbuffer, int *segmentationMaskBuffer, const Matrix &viewPortMatrix, int objectAndLinkIndex)
{
mat<3, 4, float> screenSpacePts = (viewPortMatrix * clipc).transpose(); // transposed to ease access to each of the points
mat<3, 2, float> pts2;
for (int i = 0; i < 3; i++)
{
pts2[i] = proj<2>(screenSpacePts[i] / screenSpacePts[i][3]);
}
Vec2f bboxmin( std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width()-1, image.get_height()-1);
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j]));
bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j]));
}
}
Vec2f bboxmin(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width() - 1, image.get_height() - 1);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j]));
bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j]));
}
}
Vec2i P;
TGAColor color;
TGAColor color;
mat<3,4,float> orgScreenSpacePts = (viewPortMatrix*orgClipc).transpose(); // transposed to ease access to each of the points
mat<3,2,float> orgPts2;
for (int i=0; i<3; i++)
mat<3, 4, float> orgScreenSpacePts = (viewPortMatrix * orgClipc).transpose(); // transposed to ease access to each of the points
mat<3, 2, float> orgPts2;
for (int i = 0; i < 3; i++)
{
orgPts2[i] = proj<2>(orgScreenSpacePts[i]/orgScreenSpacePts[i][3]);
orgPts2[i] = proj<2>(orgScreenSpacePts[i] / orgScreenSpacePts[i][3]);
}
for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++) {
for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++)
for (P.x = bboxmin.x; P.x <= bboxmax.x; P.x++)
{
for (P.y = bboxmin.y; P.y <= bboxmax.y; P.y++)
{
float frag_depth = 0;
{
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
Vec3f bc_clip = Vec3f(bc_screen.x/screenSpacePts[0][3], bc_screen.y/screenSpacePts[1][3], bc_screen.z/screenSpacePts[2][3]);
bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z);
frag_depth = -1*(clipc[2]*bc_clip);
if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0 ||
zbuffer[P.x+P.y*image.get_width()]>frag_depth)
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
Vec3f bc_clip = Vec3f(bc_screen.x / screenSpacePts[0][3], bc_screen.y / screenSpacePts[1][3], bc_screen.z / screenSpacePts[2][3]);
bc_clip = bc_clip / (bc_clip.x + bc_clip.y + bc_clip.z);
frag_depth = -1 * (clipc[2] * bc_clip);
if (bc_screen.x < 0 || bc_screen.y < 0 || bc_screen.z < 0 ||
zbuffer[P.x + P.y * image.get_width()] > frag_depth)
continue;
}
Vec3f bc_screen2 = barycentric(orgPts2[0], orgPts2[1], orgPts2[2], P);
Vec3f bc_clip2 = Vec3f(bc_screen2.x/orgScreenSpacePts[0][3], bc_screen2.y/orgScreenSpacePts[1][3], bc_screen2.z/orgScreenSpacePts[2][3]);
bc_clip2 = bc_clip2/(bc_clip2.x+bc_clip2.y+bc_clip2.z);
float frag_depth2 = -1*(orgClipc[2]*bc_clip2);
bool discard = shader.fragment(bc_clip2, color);
Vec3f bc_screen2 = barycentric(orgPts2[0], orgPts2[1], orgPts2[2], P);
Vec3f bc_clip2 = Vec3f(bc_screen2.x / orgScreenSpacePts[0][3], bc_screen2.y / orgScreenSpacePts[1][3], bc_screen2.z / orgScreenSpacePts[2][3]);
bc_clip2 = bc_clip2 / (bc_clip2.x + bc_clip2.y + bc_clip2.z);
float frag_depth2 = -1 * (orgClipc[2] * bc_clip2);
if (!discard) {
zbuffer[P.x+P.y*image.get_width()] = frag_depth;
if (segmentationMaskBuffer)
{
segmentationMaskBuffer[P.x+P.y*image.get_width()] = objectAndLinkIndex;
}
image.set(P.x, P.y, color);
}
}
}
bool discard = shader.fragment(bc_clip2, color);
if (!discard)
{
zbuffer[P.x + P.y * image.get_width()] = frag_depth;
if (segmentationMaskBuffer)
{
segmentationMaskBuffer[P.x + P.y * image.get_width()] = objectAndLinkIndex;
}
image.set(P.x, P.y, color);
}
}
}
}
void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix)
void triangle(mat<4, 3, float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix &viewPortMatrix)
{
triangle(clipc,shader,image,zbuffer,0,viewPortMatrix,0);
triangle(clipc, shader, image, zbuffer, 0, viewPortMatrix, 0);
}
void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, int* segmentationMaskBuffer, const Matrix& viewPortMatrix, int objectAndLinkIndex) {
mat<3,4,float> pts = (viewPortMatrix*clipc).transpose(); // transposed to ease access to each of the points
void triangle(mat<4, 3, float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, int *segmentationMaskBuffer, const Matrix &viewPortMatrix, int objectAndLinkIndex)
{
mat<3, 4, float> pts = (viewPortMatrix * clipc).transpose(); // transposed to ease access to each of the points
mat<3,2,float> pts2;
for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]);
mat<3, 2, float> pts2;
for (int i = 0; i < 3; i++) pts2[i] = proj<2>(pts[i] / pts[i][3]);
Vec2f bboxmin( std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width()-1, image.get_height()-1);
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j]));
bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j]));
}
}
Vec2f bboxmin(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width() - 1, image.get_height() - 1);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j]));
bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j]));
}
}
Vec2i P;
TGAColor color;
for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++) {
for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++) {
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
Vec3f bc_clip = Vec3f(bc_screen.x/pts[0][3], bc_screen.y/pts[1][3], bc_screen.z/pts[2][3]);
bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z);
float frag_depth = -1*(clipc[2]*bc_clip);
if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0 ||
zbuffer[P.x+P.y*image.get_width()]>frag_depth)
TGAColor color;
for (P.x = bboxmin.x; P.x <= bboxmax.x; P.x++)
{
for (P.y = bboxmin.y; P.y <= bboxmax.y; P.y++)
{
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
Vec3f bc_clip = Vec3f(bc_screen.x / pts[0][3], bc_screen.y / pts[1][3], bc_screen.z / pts[2][3]);
bc_clip = bc_clip / (bc_clip.x + bc_clip.y + bc_clip.z);
float frag_depth = -1 * (clipc[2] * bc_clip);
if (bc_screen.x < 0 || bc_screen.y < 0 || bc_screen.z < 0 ||
zbuffer[P.x + P.y * image.get_width()] > frag_depth)
continue;
bool discard = shader.fragment(bc_clip, color);
if (frag_depth<-shader.m_farPlane)
discard=true;
if (frag_depth>shader.m_nearPlane)
discard=true;
bool discard = shader.fragment(bc_clip, color);
if (frag_depth < -shader.m_farPlane)
discard = true;
if (frag_depth > shader.m_nearPlane)
discard = true;
if (!discard) {
zbuffer[P.x+P.y*image.get_width()] = frag_depth;
if (segmentationMaskBuffer)
{
segmentationMaskBuffer[P.x+P.y*image.get_width()] = objectAndLinkIndex;
}
image.set(P.x, P.y, color);
}
}
}
if (!discard)
{
zbuffer[P.x + P.y * image.get_width()] = frag_depth;
if (segmentationMaskBuffer)
{
segmentationMaskBuffer[P.x + P.y * image.get_width()] = objectAndLinkIndex;
}
image.set(P.x, P.y, color);
}
}
}
}

View File

@@ -3,25 +3,22 @@
#include "tgaimage.h"
#include "geometry.h"
Matrix viewport(int x, int y, int w, int h);
Matrix projection(float coeff=0.f); // coeff = -1/c
Matrix projection(float coeff = 0.f); // coeff = -1/c
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up);
struct IShader {
float m_nearPlane;
struct IShader
{
float m_nearPlane;
float m_farPlane;
virtual ~IShader();
virtual Vec4f vertex(int iface, int nthvert) = 0;
virtual bool fragment(Vec3f bar, TGAColor &color) = 0;
virtual ~IShader();
virtual Vec4f vertex(int iface, int nthvert) = 0;
virtual bool fragment(Vec3f bar, TGAColor &color) = 0;
};
void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix);
void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, int* segmentationMaskBuffer, const Matrix& viewPortMatrix, int objectIndex);
void triangleClipped(mat<4,3,float> &clippedPts, mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix);
void triangleClipped(mat<4,3,float> &clippedPts, mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, int* segmentationMaskBuffer, const Matrix& viewPortMatrix, int objectIndex);
#endif //__OUR_GL_H__
void triangle(mat<4, 3, float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix &viewPortMatrix);
void triangle(mat<4, 3, float> &pts, IShader &shader, TGAImage &image, float *zbuffer, int *segmentationMaskBuffer, const Matrix &viewPortMatrix, int objectIndex);
void triangleClipped(mat<4, 3, float> &clippedPts, mat<4, 3, float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix &viewPortMatrix);
void triangleClipped(mat<4, 3, float> &clippedPts, mat<4, 3, float> &pts, IShader &shader, TGAImage &image, float *zbuffer, int *segmentationMaskBuffer, const Matrix &viewPortMatrix, int objectIndex);
#endif //__OUR_GL_H__

View File

@@ -7,350 +7,420 @@
TGAImage::TGAImage() : data(NULL), width(0), height(0), bytespp(0) {}
TGAImage::TGAImage(int w, int h, int bpp) : data(NULL), width(w), height(h), bytespp(bpp) {
unsigned long nbytes = width*height*bytespp;
data = new unsigned char[nbytes];
//memset(data, 0, nbytes);
TGAImage::TGAImage(int w, int h, int bpp) : data(NULL), width(w), height(h), bytespp(bpp)
{
unsigned long nbytes = width * height * bytespp;
data = new unsigned char[nbytes];
//memset(data, 0, nbytes);
}
TGAImage::TGAImage(const TGAImage &img) : data(NULL), width(img.width), height(img.height), bytespp(img.bytespp) {
unsigned long nbytes = width*height*bytespp;
data = new unsigned char[nbytes];
//memcpy(data, img.data, nbytes);
TGAImage::TGAImage(const TGAImage &img) : data(NULL), width(img.width), height(img.height), bytespp(img.bytespp)
{
unsigned long nbytes = width * height * bytespp;
data = new unsigned char[nbytes];
//memcpy(data, img.data, nbytes);
}
TGAImage::~TGAImage() {
if (data) delete [] data;
TGAImage::~TGAImage()
{
if (data) delete[] data;
}
TGAImage & TGAImage::operator =(const TGAImage &img) {
if (this != &img) {
if (data) delete [] data;
width = img.width;
height = img.height;
bytespp = img.bytespp;
unsigned long nbytes = width*height*bytespp;
data = new unsigned char[nbytes];
memcpy(data, img.data, nbytes);
}
return *this;
TGAImage &TGAImage::operator=(const TGAImage &img)
{
if (this != &img)
{
if (data) delete[] data;
width = img.width;
height = img.height;
bytespp = img.bytespp;
unsigned long nbytes = width * height * bytespp;
data = new unsigned char[nbytes];
memcpy(data, img.data, nbytes);
}
return *this;
}
bool TGAImage::read_tga_file(const char *filename) {
if (data) delete [] data;
data = NULL;
std::ifstream in;
in.open (filename, std::ios::binary);
if (!in.is_open()) {
std::cerr << "can't open file " << filename << "\n";
in.close();
return false;
}
TGA_Header header;
in.read((char *)&header, sizeof(header));
if (!in.good()) {
in.close();
std::cerr << "an error occured while reading the header\n";
return false;
}
width = header.width;
height = header.height;
bytespp = header.bitsperpixel>>3;
if (width<=0 || height<=0 || (bytespp!=GRAYSCALE && bytespp!=RGB && bytespp!=RGBA)) {
in.close();
std::cerr << "bad bpp (or width/height) value\n";
return false;
}
unsigned long nbytes = bytespp*width*height;
data = new unsigned char[nbytes];
if (3==header.datatypecode || 2==header.datatypecode) {
in.read((char *)data, nbytes);
if (!in.good()) {
in.close();
std::cerr << "an error occured while reading the data\n";
return false;
}
} else if (10==header.datatypecode||11==header.datatypecode) {
if (!load_rle_data(in)) {
in.close();
std::cerr << "an error occured while reading the data\n";
return false;
}
} else {
in.close();
std::cerr << "unknown file format " << (int)header.datatypecode << "\n";
return false;
}
if (!(header.imagedescriptor & 0x20)) {
flip_vertically();
}
if (header.imagedescriptor & 0x10) {
flip_horizontally();
}
std::cerr << width << "x" << height << "/" << bytespp*8 << "\n";
in.close();
return true;
bool TGAImage::read_tga_file(const char *filename)
{
if (data) delete[] data;
data = NULL;
std::ifstream in;
in.open(filename, std::ios::binary);
if (!in.is_open())
{
std::cerr << "can't open file " << filename << "\n";
in.close();
return false;
}
TGA_Header header;
in.read((char *)&header, sizeof(header));
if (!in.good())
{
in.close();
std::cerr << "an error occured while reading the header\n";
return false;
}
width = header.width;
height = header.height;
bytespp = header.bitsperpixel >> 3;
if (width <= 0 || height <= 0 || (bytespp != GRAYSCALE && bytespp != RGB && bytespp != RGBA))
{
in.close();
std::cerr << "bad bpp (or width/height) value\n";
return false;
}
unsigned long nbytes = bytespp * width * height;
data = new unsigned char[nbytes];
if (3 == header.datatypecode || 2 == header.datatypecode)
{
in.read((char *)data, nbytes);
if (!in.good())
{
in.close();
std::cerr << "an error occured while reading the data\n";
return false;
}
}
else if (10 == header.datatypecode || 11 == header.datatypecode)
{
if (!load_rle_data(in))
{
in.close();
std::cerr << "an error occured while reading the data\n";
return false;
}
}
else
{
in.close();
std::cerr << "unknown file format " << (int)header.datatypecode << "\n";
return false;
}
if (!(header.imagedescriptor & 0x20))
{
flip_vertically();
}
if (header.imagedescriptor & 0x10)
{
flip_horizontally();
}
std::cerr << width << "x" << height << "/" << bytespp * 8 << "\n";
in.close();
return true;
}
bool TGAImage::load_rle_data(std::ifstream &in) {
unsigned long pixelcount = width*height;
unsigned long currentpixel = 0;
unsigned long currentbyte = 0;
TGAColor colorbuffer;
do {
unsigned char chunkheader = 0;
chunkheader = in.get();
if (!in.good()) {
std::cerr << "an error occured while reading the data\n";
return false;
}
if (chunkheader<128) {
chunkheader++;
for (int i=0; i<chunkheader; i++) {
in.read((char *)colorbuffer.bgra, bytespp);
if (!in.good()) {
std::cerr << "an error occured while reading the header\n";
return false;
}
for (int t=0; t<bytespp; t++)
data[currentbyte++] = colorbuffer.bgra[t];
currentpixel++;
if (currentpixel>pixelcount) {
std::cerr << "Too many pixels read\n";
return false;
}
}
} else {
chunkheader -= 127;
in.read((char *)colorbuffer.bgra, bytespp);
if (!in.good()) {
std::cerr << "an error occured while reading the header\n";
return false;
}
for (int i=0; i<chunkheader; i++) {
for (int t=0; t<bytespp; t++)
data[currentbyte++] = colorbuffer.bgra[t];
currentpixel++;
if (currentpixel>pixelcount) {
std::cerr << "Too many pixels read\n";
return false;
}
}
}
} while (currentpixel < pixelcount);
return true;
bool TGAImage::load_rle_data(std::ifstream &in)
{
unsigned long pixelcount = width * height;
unsigned long currentpixel = 0;
unsigned long currentbyte = 0;
TGAColor colorbuffer;
do
{
unsigned char chunkheader = 0;
chunkheader = in.get();
if (!in.good())
{
std::cerr << "an error occured while reading the data\n";
return false;
}
if (chunkheader < 128)
{
chunkheader++;
for (int i = 0; i < chunkheader; i++)
{
in.read((char *)colorbuffer.bgra, bytespp);
if (!in.good())
{
std::cerr << "an error occured while reading the header\n";
return false;
}
for (int t = 0; t < bytespp; t++)
data[currentbyte++] = colorbuffer.bgra[t];
currentpixel++;
if (currentpixel > pixelcount)
{
std::cerr << "Too many pixels read\n";
return false;
}
}
}
else
{
chunkheader -= 127;
in.read((char *)colorbuffer.bgra, bytespp);
if (!in.good())
{
std::cerr << "an error occured while reading the header\n";
return false;
}
for (int i = 0; i < chunkheader; i++)
{
for (int t = 0; t < bytespp; t++)
data[currentbyte++] = colorbuffer.bgra[t];
currentpixel++;
if (currentpixel > pixelcount)
{
std::cerr << "Too many pixels read\n";
return false;
}
}
}
} while (currentpixel < pixelcount);
return true;
}
bool TGAImage::write_tga_file(const char *filename, bool rle) const {
unsigned char developer_area_ref[4] = {0, 0, 0, 0};
unsigned char extension_area_ref[4] = {0, 0, 0, 0};
unsigned char footer[18] = {'T','R','U','E','V','I','S','I','O','N','-','X','F','I','L','E','.','\0'};
std::ofstream out;
out.open (filename, std::ios::binary);
if (!out.is_open()) {
std::cerr << "can't open file " << filename << "\n";
out.close();
return false;
}
TGA_Header header;
memset((void *)&header, 0, sizeof(header));
header.bitsperpixel = bytespp<<3;
header.width = width;
header.height = height;
header.datatypecode = (bytespp==GRAYSCALE?(rle?11:3):(rle?10:2));
header.imagedescriptor = 0x20; // top-left origin
out.write((char *)&header, sizeof(header));
if (!out.good()) {
out.close();
std::cerr << "can't dump the tga file\n";
return false;
}
if (!rle) {
out.write((char *)data, width*height*bytespp);
if (!out.good()) {
std::cerr << "can't unload raw data\n";
out.close();
return false;
}
} else {
if (!unload_rle_data(out)) {
out.close();
std::cerr << "can't unload rle data\n";
return false;
}
}
out.write((char *)developer_area_ref, sizeof(developer_area_ref));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.write((char *)extension_area_ref, sizeof(extension_area_ref));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.write((char *)footer, sizeof(footer));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.close();
return true;
bool TGAImage::write_tga_file(const char *filename, bool rle) const
{
unsigned char developer_area_ref[4] = {0, 0, 0, 0};
unsigned char extension_area_ref[4] = {0, 0, 0, 0};
unsigned char footer[18] = {'T', 'R', 'U', 'E', 'V', 'I', 'S', 'I', 'O', 'N', '-', 'X', 'F', 'I', 'L', 'E', '.', '\0'};
std::ofstream out;
out.open(filename, std::ios::binary);
if (!out.is_open())
{
std::cerr << "can't open file " << filename << "\n";
out.close();
return false;
}
TGA_Header header;
memset((void *)&header, 0, sizeof(header));
header.bitsperpixel = bytespp << 3;
header.width = width;
header.height = height;
header.datatypecode = (bytespp == GRAYSCALE ? (rle ? 11 : 3) : (rle ? 10 : 2));
header.imagedescriptor = 0x20; // top-left origin
out.write((char *)&header, sizeof(header));
if (!out.good())
{
out.close();
std::cerr << "can't dump the tga file\n";
return false;
}
if (!rle)
{
out.write((char *)data, width * height * bytespp);
if (!out.good())
{
std::cerr << "can't unload raw data\n";
out.close();
return false;
}
}
else
{
if (!unload_rle_data(out))
{
out.close();
std::cerr << "can't unload rle data\n";
return false;
}
}
out.write((char *)developer_area_ref, sizeof(developer_area_ref));
if (!out.good())
{
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.write((char *)extension_area_ref, sizeof(extension_area_ref));
if (!out.good())
{
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.write((char *)footer, sizeof(footer));
if (!out.good())
{
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.close();
return true;
}
// TODO: it is not necessary to break a raw chunk for two equal pixels (for the matter of the resulting size)
bool TGAImage::unload_rle_data(std::ofstream &out) const {
const unsigned char max_chunk_length = 128;
unsigned long npixels = width*height;
unsigned long curpix = 0;
while (curpix<npixels) {
unsigned long chunkstart = curpix*bytespp;
unsigned long curbyte = curpix*bytespp;
unsigned char run_length = 1;
bool raw = true;
while (curpix+run_length<npixels && run_length<max_chunk_length) {
bool succ_eq = true;
for (int t=0; succ_eq && t<bytespp; t++) {
succ_eq = (data[curbyte+t]==data[curbyte+t+bytespp]);
}
curbyte += bytespp;
if (1==run_length) {
raw = !succ_eq;
}
if (raw && succ_eq) {
run_length--;
break;
}
if (!raw && !succ_eq) {
break;
}
run_length++;
}
curpix += run_length;
out.put(raw?run_length-1:run_length+127);
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
return false;
}
out.write((char *)(data+chunkstart), (raw?run_length*bytespp:bytespp));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
return false;
}
}
return true;
bool TGAImage::unload_rle_data(std::ofstream &out) const
{
const unsigned char max_chunk_length = 128;
unsigned long npixels = width * height;
unsigned long curpix = 0;
while (curpix < npixels)
{
unsigned long chunkstart = curpix * bytespp;
unsigned long curbyte = curpix * bytespp;
unsigned char run_length = 1;
bool raw = true;
while (curpix + run_length < npixels && run_length < max_chunk_length)
{
bool succ_eq = true;
for (int t = 0; succ_eq && t < bytespp; t++)
{
succ_eq = (data[curbyte + t] == data[curbyte + t + bytespp]);
}
curbyte += bytespp;
if (1 == run_length)
{
raw = !succ_eq;
}
if (raw && succ_eq)
{
run_length--;
break;
}
if (!raw && !succ_eq)
{
break;
}
run_length++;
}
curpix += run_length;
out.put(raw ? run_length - 1 : run_length + 127);
if (!out.good())
{
std::cerr << "can't dump the tga file\n";
return false;
}
out.write((char *)(data + chunkstart), (raw ? run_length * bytespp : bytespp));
if (!out.good())
{
std::cerr << "can't dump the tga file\n";
return false;
}
}
return true;
}
TGAColor TGAImage::get(int x, int y) const {
if (!data || x<0 || y<0 || x>=width || y>=height) {
return TGAColor(128.f,128.f,128.f,255.f);
}
return TGAColor(data+(x+y*width)*bytespp, bytespp);
TGAColor TGAImage::get(int x, int y) const
{
if (!data || x < 0 || y < 0 || x >= width || y >= height)
{
return TGAColor(128.f, 128.f, 128.f, 255.f);
}
return TGAColor(data + (x + y * width) * bytespp, bytespp);
}
bool TGAImage::set(int x, int y, TGAColor &c) {
if (!data || x<0 || y<0 || x>=width || y>=height) {
return false;
}
memcpy(data+(x+y*width)*bytespp, c.bgra, bytespp);
return true;
bool TGAImage::set(int x, int y, TGAColor &c)
{
if (!data || x < 0 || y < 0 || x >= width || y >= height)
{
return false;
}
memcpy(data + (x + y * width) * bytespp, c.bgra, bytespp);
return true;
}
bool TGAImage::set(int x, int y, const TGAColor &c) {
if (!data || x<0 || y<0 || x>=width || y>=height) {
return false;
}
memcpy(data+(x+y*width)*bytespp, c.bgra, bytespp);
return true;
bool TGAImage::set(int x, int y, const TGAColor &c)
{
if (!data || x < 0 || y < 0 || x >= width || y >= height)
{
return false;
}
memcpy(data + (x + y * width) * bytespp, c.bgra, bytespp);
return true;
}
int TGAImage::get_bytespp() {
return bytespp;
int TGAImage::get_bytespp()
{
return bytespp;
}
int TGAImage::get_width() {
return width;
int TGAImage::get_width()
{
return width;
}
int TGAImage::get_height() {
return height;
int TGAImage::get_height()
{
return height;
}
bool TGAImage::flip_horizontally() {
if (!data) return false;
int half = width>>1;
for (int i=0; i<half; i++) {
for (int j=0; j<height; j++) {
TGAColor c1 = get(i, j);
TGAColor c2 = get(width-1-i, j);
set(i, j, c2);
set(width-1-i, j, c1);
}
}
return true;
bool TGAImage::flip_horizontally()
{
if (!data) return false;
int half = width >> 1;
for (int i = 0; i < half; i++)
{
for (int j = 0; j < height; j++)
{
TGAColor c1 = get(i, j);
TGAColor c2 = get(width - 1 - i, j);
set(i, j, c2);
set(width - 1 - i, j, c1);
}
}
return true;
}
bool TGAImage::flip_vertically() {
if (!data) return false;
unsigned long bytes_per_line = width*bytespp;
unsigned char *line = new unsigned char[bytes_per_line];
int half = height>>1;
for (int j=0; j<half; j++) {
unsigned long l1 = j*bytes_per_line;
unsigned long l2 = (height-1-j)*bytes_per_line;
memmove((void *)line, (void *)(data+l1), bytes_per_line);
memmove((void *)(data+l1), (void *)(data+l2), bytes_per_line);
memmove((void *)(data+l2), (void *)line, bytes_per_line);
}
delete [] line;
return true;
bool TGAImage::flip_vertically()
{
if (!data) return false;
unsigned long bytes_per_line = width * bytespp;
unsigned char *line = new unsigned char[bytes_per_line];
int half = height >> 1;
for (int j = 0; j < half; j++)
{
unsigned long l1 = j * bytes_per_line;
unsigned long l2 = (height - 1 - j) * bytes_per_line;
memmove((void *)line, (void *)(data + l1), bytes_per_line);
memmove((void *)(data + l1), (void *)(data + l2), bytes_per_line);
memmove((void *)(data + l2), (void *)line, bytes_per_line);
}
delete[] line;
return true;
}
unsigned char *TGAImage::buffer() {
return data;
unsigned char *TGAImage::buffer()
{
return data;
}
void TGAImage::clear() {
memset((void *)data, 0, width*height*bytespp);
void TGAImage::clear()
{
memset((void *)data, 0, width * height * bytespp);
}
bool TGAImage::scale(int w, int h) {
if (w<=0 || h<=0 || !data) return false;
unsigned char *tdata = new unsigned char[w*h*bytespp];
int nscanline = 0;
int oscanline = 0;
int erry = 0;
unsigned long nlinebytes = w*bytespp;
unsigned long olinebytes = width*bytespp;
for (int j=0; j<height; j++) {
int errx = width-w;
int nx = -bytespp;
int ox = -bytespp;
for (int i=0; i<width; i++) {
ox += bytespp;
errx += w;
while (errx>=(int)width) {
errx -= width;
nx += bytespp;
memcpy(tdata+nscanline+nx, data+oscanline+ox, bytespp);
}
}
erry += h;
oscanline += olinebytes;
while (erry>=(int)height) {
if (erry>=(int)height<<1) // it means we jump over a scanline
memcpy(tdata+nscanline+nlinebytes, tdata+nscanline, nlinebytes);
erry -= height;
nscanline += nlinebytes;
}
}
delete [] data;
data = tdata;
width = w;
height = h;
return true;
bool TGAImage::scale(int w, int h)
{
if (w <= 0 || h <= 0 || !data) return false;
unsigned char *tdata = new unsigned char[w * h * bytespp];
int nscanline = 0;
int oscanline = 0;
int erry = 0;
unsigned long nlinebytes = w * bytespp;
unsigned long olinebytes = width * bytespp;
for (int j = 0; j < height; j++)
{
int errx = width - w;
int nx = -bytespp;
int ox = -bytespp;
for (int i = 0; i < width; i++)
{
ox += bytespp;
errx += w;
while (errx >= (int)width)
{
errx -= width;
nx += bytespp;
memcpy(tdata + nscanline + nx, data + oscanline + ox, bytespp);
}
}
erry += h;
oscanline += olinebytes;
while (erry >= (int)height)
{
if (erry >= (int)height << 1) // it means we jump over a scanline
memcpy(tdata + nscanline + nlinebytes, tdata + nscanline, nlinebytes);
erry -= height;
nscanline += nlinebytes;
}
}
delete[] data;
data = tdata;
width = w;
height = h;
return true;
}

View File

@@ -3,99 +3,110 @@
#include <fstream>
#pragma pack(push,1)
struct TGA_Header {
char idlength;
char colormaptype;
char datatypecode;
short colormaporigin;
short colormaplength;
char colormapdepth;
short x_origin;
short y_origin;
short width;
short height;
char bitsperpixel;
char imagedescriptor;
#pragma pack(push, 1)
struct TGA_Header
{
char idlength;
char colormaptype;
char datatypecode;
short colormaporigin;
short colormaplength;
char colormapdepth;
short x_origin;
short y_origin;
short width;
short height;
char bitsperpixel;
char imagedescriptor;
};
#pragma pack(pop)
struct TGAColor {
unsigned char bgra[4];
unsigned char bytespp;
struct TGAColor
{
unsigned char bgra[4];
unsigned char bytespp;
TGAColor() : bytespp(1)
TGAColor() : bytespp(1)
{
for (int i=0; i<4; i++)
for (int i = 0; i < 4; i++)
bgra[i] = 0;
}
}
TGAColor(unsigned char R, unsigned char G, unsigned char B, unsigned char A=255) : bytespp(4) {
bgra[0] = B;
bgra[1] = G;
bgra[2] = R;
bgra[3] = A;
}
TGAColor(unsigned char R, unsigned char G, unsigned char B, unsigned char A = 255) : bytespp(4)
{
bgra[0] = B;
bgra[1] = G;
bgra[2] = R;
bgra[3] = A;
}
TGAColor(unsigned char v) : bytespp(1) {
for (int i=0; i<4; i++) bgra[i] = 0;
bgra[0] = v;
}
TGAColor(unsigned char v) : bytespp(1)
{
for (int i = 0; i < 4; i++) bgra[i] = 0;
bgra[0] = v;
}
TGAColor(const unsigned char *p, unsigned char bpp) : bytespp(bpp)
{
for (int i = 0; i < (int)bpp; i++)
{
bgra[i] = p[i];
}
for (int i = bpp; i < 4; i++)
{
bgra[i] = 0;
}
}
TGAColor(const unsigned char *p, unsigned char bpp) : bytespp(bpp) {
for (int i=0; i<(int)bpp; i++) {
bgra[i] = p[i];
}
for (int i=bpp; i<4; i++) {
bgra[i] = 0;
}
}
unsigned char &operator[](const int i) { return bgra[i]; }
unsigned char& operator[](const int i) { return bgra[i]; }
TGAColor operator *(float intensity) const {
TGAColor res = *this;
intensity = (intensity>1.f?1.f:(intensity<0.f?0.f:intensity));
for (int i=0; i<4; i++) res.bgra[i] = bgra[i]*intensity;
return res;
}
TGAColor operator*(float intensity) const
{
TGAColor res = *this;
intensity = (intensity > 1.f ? 1.f : (intensity < 0.f ? 0.f : intensity));
for (int i = 0; i < 4; i++) res.bgra[i] = bgra[i] * intensity;
return res;
}
};
class TGAImage {
class TGAImage
{
protected:
unsigned char* data;
int width;
int height;
int bytespp;
unsigned char *data;
int width;
int height;
int bytespp;
bool load_rle_data(std::ifstream &in);
bool unload_rle_data(std::ofstream &out) const;
bool load_rle_data(std::ifstream &in);
bool unload_rle_data(std::ofstream &out) const;
public:
enum Format {
GRAYSCALE=1, RGB=3, RGBA=4
};
enum Format
{
GRAYSCALE = 1,
RGB = 3,
RGBA = 4
};
TGAImage();
TGAImage(int w, int h, int bpp);
TGAImage(const TGAImage &img);
bool read_tga_file(const char *filename);
bool write_tga_file(const char *filename, bool rle=true) const;
bool flip_horizontally();
bool flip_vertically();
bool scale(int w, int h);
TGAColor get(int x, int y) const;
bool set(int x, int y, TGAColor &c);
bool set(int x, int y, const TGAColor &c);
~TGAImage();
TGAImage & operator =(const TGAImage &img);
int get_width();
int get_height();
int get_bytespp();
unsigned char *buffer();
void clear();
TGAImage();
TGAImage(int w, int h, int bpp);
TGAImage(const TGAImage &img);
bool read_tga_file(const char *filename);
bool write_tga_file(const char *filename, bool rle = true) const;
bool flip_horizontally();
bool flip_vertically();
bool scale(int w, int h);
TGAColor get(int x, int y) const;
bool set(int x, int y, TGAColor &c);
bool set(int x, int y, const TGAColor &c);
~TGAImage();
TGAImage &operator=(const TGAImage &img);
int get_width();
int get_height();
int get_bytespp();
unsigned char *buffer();
void clear();
};
#endif //__IMAGE_H__
#endif //__IMAGE_H__