Teraz już wiem, że atan2 zwraca wartości od -M_PI do M_PI. Poprawiłem kod tak, aby wartość dla rotacji była zawsze w przedziale o 0 do 2*M_PI. Teraz na spokojnie mogę się zająć rotacją w osi Y tak jak rotacją w osi Z (na zasadzie wskazówek zegarka czyli y+=len*cos, x+=len*sin)
#include <iostream>
using namespace std;
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengles2.h>
#include "shaders.cpp"
#include "camera.cpp"
float toDegrees = 180.f / M_PI;
float toRads = M_PI / 180.f;
float dz = 2.f; float deg1z, deg2z, deg3z; float deg1y, deg2y, deg3y;
float deg1x, deg2x, deg3x;
float len1, len2, len3; float fullAnglez1, fullAnglez2, fullAnglez3; float fullAngley1, fullAngley2, fullAngley3;
float fullAnglex1, fullAnglex2, fullAnglex3;
int testindex;
float camx, camy, camz;
class trit
{
public:
float v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z; float r, g, b, a; trit * next;
float r1x, r1y, r1z, r2x, r2y, r2z, r3x, r3y, r3z; float p1x, p1y, p2x, p2y, p3x, p3y; float cx, cy, cz; trit( float, float, float, float, float, float, float, float, float, float, float, float, float );
trit( trit * );
~trit();
};
class model
{
public:
trit * mesh;
model * next;
float cx, cy, cz; float anglex, angley, anglez; float rotx, roty, rotz; model();
~model();
void addTrit( float, float, float, float, float, float, float, float, float, float, float, float, float );
void addTrit( trit * );
void setCenter( float, float, float ); void translate();
void rotatez();
void rotatey();
void rotatex();
void projection();
void calcCenterOfTriangles();
void sortTrits();
void calculate(); void render();
};
class tritEngine
{
public:
model * models;
camera * cam;
tritEngine();
~tritEngine();
void setCamera( camera * );
void addModel( model * );
void translate();
void rotatez();
void rotatey();
void rotatex();
void calculate(); void sortModels();
void sort(); void render();
};
float dist( float x1, float y1, float z1, float x2, float y2, float z2 )
{
return sqrt( pow( x2 - x1, 2 ) + pow( y2 - y1, 2 ) + pow( z2 - z1, 2 ) );
}
float dist( camera * cam, trit * t )
{
return sqrt( pow( cam->x - t->cx, 2 ) + pow( cam->y - t->cy, 2 ) + pow( cam->z - t->cz, 2 ) );
}
trit::trit( float v1x, float v1y, float v1z, float v2x, float v2y, float v2z, float v3x, float v3y, float v3z, float r = 128, float g = 128, float b = 128, float a = 256 )
{
this->v1x = v1x; this->v1y = v1y; this->v1z = v1z;
this->v2x = v2x; this->v2y = v2y; this->v2z = v2z;
this->v3x = v3x; this->v3y = v3y; this->v3z = v3z;
this->r = r; this->g = g; this->b = b; this->a = a;
next = NULL;
}
trit::trit( trit * t )
{
this->v1x = t->v1x; this->v1y = t->v1y; this->v1z = t->v1z;
this->v2x = t->v2x; this->v2y = t->v2y; this->v2z = t->v2z;
this->v3x = t->v3x; this->v3y = t->v3y; this->v3z = t->v3z;
this->r = t->r; this->g = t->g; this->b = t->b; this->a = t->a;
this->r1x = r1x; this->r1y = r1y; this->r1z = r1z;
this->r1x = r2x; this->r1y = r2y; this->r1z = r2z;
this->r1x = r3x; this->r1y = r3y; this->r1z = r3z;
next = NULL;
}
trit::~trit()
{
}
model::model()
{
mesh = NULL;
next = NULL;
cx = cy = cz = 0;
anglex = angley = anglez = 0;
rotx = roty = rotz = 0;
}
model::~model()
{
}
void model::addTrit( float v1x, float v1y, float v1z, float v2x, float v2y, float v2z, float v3x, float v3y, float v3z, float r = 128, float g = 128, float b = 128, float a = 256 )
{
trit * t = new trit( v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z, r, g, b, a );
if( mesh != NULL )
t->next = mesh;
mesh = t;
}
void model::addTrit( trit * t )
{
if( mesh != NULL )
t->next = mesh;
mesh = t;
}
void model::setCenter( float cx, float cy, float cz )
{
this->cx = cx;
this->cy = cy;
this->cz = cz;
}
void model::translate()
{
for( trit * t = mesh; t != NULL; t = t->next )
{
t->r1x = t->v1x;
t->r1y = t->v1y;
t->r1z = t->v1z;
t->r2x = t->v2x;
t->r2y = t->v2y;
t->r2z = t->v2z;
t->r3x = t->v3x;
t->r3y = t->v3y;
t->r3z = t->v3z;
}
}
void model::rotatez()
{
for( trit * t = mesh; t != NULL; t = t->next )
{
len1 = sqrt( pow( cx - t->v1x, 2 ) + pow( cy - t->v1y, 2 ) + pow( cz - t->v1z, 2 ) );
len2 = sqrt( pow( cx - t->v2x, 2 ) + pow( cy - t->v2y, 2 ) + pow( cz - t->v2z, 2 ) );
len3 = sqrt( pow( cx - t->v3x, 2 ) + pow( cy - t->v3y, 2 ) + pow( cz - t->v3z, 2 ) );
deg1z =( atan2( cy - t->v1y, cx - t->v1x ) + M_PI ) * toDegrees;
deg2z =( atan2( cy - t->v2y, cx - t->v2x ) + M_PI ) * toDegrees;
deg3z =( atan2( cy - t->v3y, cx - t->v3x ) + M_PI ) * toDegrees;
if( testindex++ < 360 * 2 )
{
cout << deg1z << ", " << deg2z << ", " << deg3z << endl;
}
fullAnglez1 =( deg1z + anglez ) * toRads;
fullAnglez2 =( deg2z + anglez ) * toRads;
fullAnglez3 =( deg3z + anglez ) * toRads;
t->r1x = cx + len1 * sin( fullAnglez1 );
t->r1y = cy + len1 * cos( fullAnglez1 );
t->r2x = cx + len2 * sin( fullAnglez2 );
t->r2y = cy + len2 * cos( fullAnglez2 );
t->r3x = cx + len3 * sin( fullAnglez3 );
t->r3y = cy + len3 * cos( fullAnglez3 );
}
}
void model::rotatey()
{
for( trit * t = mesh; t != NULL; t = t->next )
{
len1 = sqrt( pow( cx - t->v1x, 2 ) + pow( cy - t->v1z, 2 ) + pow( cz - t->v1z, 2 ) );
len2 = sqrt( pow( cx - t->v2x, 2 ) + pow( cy - t->v2z, 2 ) + pow( cz - t->v2z, 2 ) );
len3 = sqrt( pow( cx - t->v3x, 2 ) + pow( cy - t->v3z, 2 ) + pow( cz - t->v3z, 2 ) );
deg1y =( atan2( cz - t->v1z, cx - t->v1x ) + M_PI ) * toDegrees;
deg2y =( atan2( cz - t->v2z, cx - t->v2x ) + M_PI ) * toDegrees;
deg3y =( atan2( cz - t->v3z, cx - t->v3x ) + M_PI ) * toDegrees;
fullAngley1 =( deg1y + angley ) * toRads;
fullAngley2 =( deg2y + angley ) * toRads;
fullAngley3 =( deg3y + angley ) * toRads;
t->r1x = t->r1x + len1 * sin( fullAngley1 );
t->r2x = t->r2x + len2 * sin( fullAngley2 );
t->r3x = t->r3x + len3 * sin( fullAngley3 );
}
}
void model::rotatex()
{
for( trit * t = mesh; t != NULL; t = t->next )
{
len1 = sqrt( pow( cx - t->r1x, 2 ) + pow( cy - t->r1y, 2 ) + pow( cz - t->r1z, 2 ) );
len2 = sqrt( pow( cx - t->r2x, 2 ) + pow( cy - t->r2y, 2 ) + pow( cz - t->r2z, 2 ) );
len3 = sqrt( pow( cx - t->r3x, 2 ) + pow( cy - t->r3y, 2 ) + pow( cz - t->r3z, 2 ) );
deg1x = atan2( cy - t->r1y, cz - t->r1z ) * toDegrees;
deg2x = atan2( cy - t->r2y, cz - t->r2z ) * toDegrees;
deg3x = atan2( cy - t->r3y, cz - t->r3z ) * toDegrees;
fullAnglex1 =( deg1x + anglex ) * toRads;
fullAnglex2 =( deg2x + anglex ) * toRads;
fullAnglex3 =( deg3x + anglex ) * toRads;
t->r1y = t->r1y + len1 * sin( fullAnglex1 );
t->r1z = t->r1z + len1 * cos( fullAnglex1 );
t->r2y = t->r2y + len2 * sin( fullAnglex2 );
t->r2z = t->r2z + len2 * cos( fullAnglex2 );
t->r3y = t->r3y + len3 * sin( fullAnglex3 );
t->r3z = t->r3z + len3 * cos( fullAnglex3 );
}
}
void model::projection()
{
for( trit * t = mesh; t != NULL; t = t->next )
{
t->p1x = t->r1x; t->p1y = t->r1y;
t->p2x = t->r2x; t->p2y = t->r2y;
t->p3x = t->r3x; t->p3y = t->r3y;
}
}
void model::calcCenterOfTriangles()
{
for( trit * t = mesh; t != NULL; t = t->next )
{
t->cx =( t->r1x + t->r2x + t->r3x ) / 3.f;
t->cy =( t->r1y + t->r2y + t->r3y ) / 3.f;
t->cz =( t->r1z + t->r2z + t->r3z ) / 3.f;
}
}
void model::sortTrits()
{
trit * orNewFirst, * orCurrent, * orSearch, * orNext;
if( mesh != NULL && mesh->next != NULL )
{
orNewFirst = mesh;
orCurrent = mesh->next;
orNewFirst->next = NULL;
while( orCurrent != NULL )
{
orNext = orCurrent->next;
if( orCurrent->cz > orNewFirst->cz )
{
orCurrent->next = orNewFirst;
orNewFirst = orCurrent;
} else
{
orSearch = orNewFirst;
while( orSearch->next != NULL && orSearch->next->cz > orCurrent->cz )
orSearch = orSearch->next;
orCurrent->next = orSearch->next;
orSearch->next = orCurrent;
};
orCurrent = orNext;
}
mesh = orNewFirst;
}
}
void model::calculate()
{
translate();
rotatez();
rotatey();
projection();
calcCenterOfTriangles();
sortTrits();
}
void model::render()
{
float dz = 2.f; for( trit * t = mesh; t != NULL; t = t->next )
drawTritColor(
t->p1x, t->p1y,
t->p2x, t->p2y,
t->p3x, t->p3y,
t->r, t->g, t->b, t->a
);
}
tritEngine::tritEngine()
{
models = NULL;
cam = new camera( 480, 720 );
}
tritEngine::~tritEngine()
{
}
void tritEngine::addModel( model * m )
{
if( models != NULL )
m->next = models;
models = m;
}
void tritEngine::calculate()
{
for( model * m = models; m != NULL; m = m->next )
{
m->anglez += m->rotz; if( m->anglez >= 360 ) m->anglez = int( m->anglez ) % 360;
m->angley += m->roty; if( m->angley >= 360 ) m->angley = int( m->angley ) % 360;
m->anglex += m->rotx; if( m->anglex >= 360 ) m->anglex = int( m->anglex ) % 360;
m->calculate();
}
}
void tritEngine::sortModels()
{
}
void tritEngine::render()
{
for( model * m = models; m != NULL; m = m->next )
m->render();
}
SDL_Window * window;
bool programRun;
float screenWidth, screenHeight;
void initSDL()
{
SDL_Init( SDL_INIT_EVERYTHING );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 8 );
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode( 0, & DM );
window = SDL_CreateWindow(
"tritEngine",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
int( DM.w ), int( DM.h ),
SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN );
SDL_GL_CreateContext( window );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
void initProgram()
{
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode( 0, & DM );
screenWidth = int( DM.w );
screenHeight = int( DM.h );
programRun = true;
}
void drawBackground()
{
glClearColor( 0.125f, 0.125f, 0.125f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
void createStandardCube( tritEngine * engine, float x, float y, float z, float side, float az = 0, float ay = 0, float ax = 0, float rz = 0, float ry = 0, float rx = 0 )
{
model * cube;
trit * t1, * t2, * t3, * t4, * t5, * t6, * t7, * t8, * t9, * t10, * t11, * t12;
t1 = new trit( x - side, y - side, z - side, x - side, y + side, z - side, x + side, y + side, z - side, 128, 48, 48, 256 );
t2 = new trit( x - side, y - side, z - side, x + side, y - side, z - side, x + side, y + side, z - side, 128, 48, 48, 256 );
t3 = new trit( x - side, y - side, z + side, x - side, y + side, z + side, x + side, y + side, z + side, 128, 48, 48, 256 );
t4 = new trit( x - side, y - side, z + side, x + side, y - side, z + side, x + side, y + side, z + side, 128, 48, 48, 256 );
t5 = new trit( x - side, y - side, z - side, x - side, y + side, z - side, x - side, y + side, z + side, 48, 128, 48, 256 );
t6 = new trit( x - side, y - side, z - side, x - side, y - side, z + side, x - side, y + side, z + side, 48, 128, 48, 256 );
t7 = new trit( x + side, y - side, z - side, x + side, y + side, z - side, x + side, y + side, z + side, 48, 128, 48, 256 );
t8 = new trit( x + side, y - side, z - side, x + side, y - side, z + side, x + side, y + side, z + side, 48, 128, 48, 256 );
t9 = new trit( x - side, y + side, z - side, x - side, y + side, z + side, x + side, y + side, z + side, 48, 48, 128, 256 );
t10 = new trit( x - side, y + side, z - side, x + side, y + side, z - side, x + side, y + side, z + side, 48, 48, 128, 256 );
t11 = new trit( x - side, y - side, z - side, x - side, y - side, z + side, x + side, y - side, z + side, 48, 48, 128, 256 );
t12 = new trit( x - side, y - side, z - side, x + side, y - side, z - side, x + side, y - side, z + side, 48, 48, 128, 256 );
cube = new model();
cube->setCenter( x, y, z );
cube->addTrit( t1 ); cube->addTrit( t2 ); cube->addTrit( t3 ); cube->addTrit( t4 ); cube->addTrit( t5 ); cube->addTrit( t6 ); cube->addTrit( t7 ); cube->addTrit( t8 ); cube->addTrit( t9 ); cube->addTrit( t10 ); cube->addTrit( t11 ); cube->addTrit( t12 ); cube->anglez = az;
cube->angley = ay;
cube->anglex = ax;
cube->rotz = rz;
cube->roty = ry;
cube->rotx = rx;
engine->addModel( cube );
}
int main()
{
initSDL();
initProgram();
setScreen( screenWidth, screenHeight );
initShader();
tritEngine * engine = new tritEngine();
createStandardCube(
engine,
0, 0, 0, 200, 45, 0, 0, 0, 1, 0 );
testindex = 0;
while( programRun )
{
drawBackground();
engine->calculate();
engine->sortModels();
engine->render();
SDL_GL_SwapWindow( window );
};
}