GLProgramming.com

home :: about :: development guides :: irc :: forums :: search :: paste :: links :: contribute :: code dump

-> Click here to learn how to get live help <-


New Paste :: Recent Pastes:: Add Line Numbers


incorrect rotation by godecho
#ifdef _WIN32
    #pragma comment(lib, "glu32.lib")
    #pragma comment(lib, "opengl32.lib")
    #pragma comment(lib, "SDL.lib")
    #pragma comment(lib, "SDLmain.lib")    

    #define WIN32_LEAN_AND_MEAN 1
    #include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>
#include "SDL.h"

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstddef>
#include <iostream>

const float PI = 3.1415926535897932384626433832795f;

struct Point2f
{
    float x;
    float y;
};

struct Triangle
{
    Point2f points[3];
    
    Triangle operator = (const Triangle &rhs)
    {
        std::copy(rhs.points, rhs.points+3, points);
        return (*this);
    }

    void translate(float x, float y)
    {
        points[0].x += x;
        points[0].y += y;

        points[1].x += x;
        points[1].y += y;

        points[2].x += x;
        points[2].y += y;
    }

    void rotate(float radianAngle)
    {
        // x' = x*cos(theta) + y*sin(theta)
        // y' = y*cos(theta) - x*sin(theta)
        
        float cos_theta = cos(radianAngle);
        float sin_theta = sin(radianAngle);

        points[0].x = (points[0].x * cos_theta) + (points[0].y * sin_theta);
        points[0].y = (points[0].y * cos_theta) - (points[0].x * sin_theta);

        points[1].x = (points[1].x * cos_theta) + (points[1].y * sin_theta);
        points[1].y = (points[1].y * cos_theta) - (points[1].x * sin_theta);

        points[2].x = (points[2].x * cos_theta) + (points[2].y * sin_theta);
        points[2].y = (points[2].y * cos_theta) - (points[2].x * sin_theta);
    }
    
    std::ostream& print(std::ostream &os)    const
    {
        os    << '(' << points[0].x << ", " << points[0].y << ") "
            << '(' << points[1].x << ", " << points[1].y << ") "
            << '(' << points[2].x << ", " << points[2].y << ") ";
        
        return os;
    }
};

std::ostream& operator << (std::ostream &os, const Triangle &tri)
{
    return tri.print(os);
}


const GLuint    g_width        = 800;
const GLuint    g_height    = 800;
const GLuint    g_bpp        = 16;
const GLfloat    g_fov        = 45.0f;
const GLfloat    g_nClip        = 1.0f;
const GLfloat    g_fClip        = 500.0f;

Triangle g_originalTriangle;
Triangle g_transformedTriangle;
Triangle g_selftransform;

Point2f g_center1;
Point2f g_center2;

float g_angle = 0.0f;

const GLfloat g_colors[] = {    1.0f, 0.0f, 0.0f,
                                0.0f, 1.0f, 0.0f,
                                0.0f, 0.0f, 1.0f    };

bool Init();
bool CheckInput();
void Draw();
void SetOrthoProj();
void ResetPersProj();


int main(int argc, char** argv)
{
    if(Init() == false)
    {
        SDL_Quit();
        std::cerr << "Initialization has failed, exiting." << std::endl;
        return -1;
    }

    GLenum error;

    while(CheckInput() == true)
    {
        Draw();
        
        error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << "* OpenGL Error: " << gluErrorString(error) << std::endl;
        }

        SDL_GL_SwapBuffers();
    }

    SDL_Quit();

    return 0;
}

bool Init()
{
    if(SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
    {
        std::cerr << "InitSubSystem() failed. SDL Error: " << SDL_GetError() << std::endl;
        return false;
    }

    if(SDL_SetVideoMode(g_width, g_height, g_bpp, SDL_OPENGL) == 0)
    {
        std::cerr << "setVideoMode() Failed. SDL_Error: " << SDL_GetError() << std::endl;
        return false;
    }
    
    glViewport(0, 0, g_width, g_height);
    glMatrixMode(GL_PROJECTION);
    gluPerspective(    g_fov,
                    float(g_width)/float(g_height),
                    g_nClip,
                    g_fClip);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glShadeModel(GL_SMOOTH);    // Select Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);

    // set up some of our globals

    g_originalTriangle.points[0].x = 100;
    g_originalTriangle.points[0].y = 300;
    
    g_originalTriangle.points[1].x = 300;
    g_originalTriangle.points[1].y = 300;
    
    g_originalTriangle.points[2].x = 200;
    g_originalTriangle.points[2].y = 500;

    g_center1.x = ((g_originalTriangle.points[0].x + g_originalTriangle.points[1].x + g_originalTriangle.points[2].x) / 3.0f);
    g_center1.y = ((g_originalTriangle.points[0].y + g_originalTriangle.points[1].y + g_originalTriangle.points[2].y) / 3.0f);

    g_selftransform.points[0].x = 500;
    g_selftransform.points[0].y = 300;
                   
    g_selftransform.points[1].x = 700;
    g_selftransform.points[1].y = 300;
                   
    g_selftransform.points[2].x = 600;
    g_selftransform.points[2].y = 500;

    g_center2.x = ((g_selftransform.points[0].x + g_selftransform.points[1].x + g_selftransform.points[2].x) / 3.0f);
    g_center2.y = ((g_selftransform.points[0].y + g_selftransform.points[1].y + g_selftransform.points[2].y) / 3.0f);

    return true;
}

void Draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    SetOrthoProj();

    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    
    glColorPointer(3, GL_FLOAT, 0, g_colors);

    // example triangle 1
    g_transformedTriangle = g_originalTriangle;

    g_angle += 0.01f;

    g_transformedTriangle.translate(-g_center1.x, -g_center1.y);
    g_transformedTriangle.rotate(g_angle);
    g_transformedTriangle.translate( g_center1.x,  g_center1.y);
    
    glVertexPointer(2, GL_FLOAT, 0, g_transformedTriangle.points);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    // example triangle 2
    g_selftransform.translate(-g_center2.x, -g_center2.y);
    g_selftransform.rotate(0.1f);
    g_selftransform.translate( g_center2.x,  g_center2.y);
    
    glVertexPointer(2, GL_FLOAT, 0, g_selftransform.points);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    ResetPersProj();
}

bool CheckInput()
{
    static SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        if((event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE) || event.type == SDL_QUIT)
        {
            return false;
        }
    }
    return true;
}

void SetOrthoProj()
{
    glPushAttrib(GL_DEPTH_TEST);
    glDisable(GL_DEPTH_TEST);                        // Turn depth testing off

    glMatrixMode(GL_PROJECTION);                    // Switch to projection mode
    glPushMatrix();                                    // Save previous matrix which contains the settings for the perspective projection
    glLoadIdentity();

    glOrtho(0, g_width, 0, g_height, -1, 1);
    glMatrixMode(GL_MODELVIEW);
}

void ResetPersProj()
{
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();                                    // Pop the stack
    glMatrixMode(GL_MODELVIEW);                        // Put us back in modelview mode                                            

    glEnable(GL_DEPTH_TEST);                        // Turn depth testing back on
    glPopAttrib();
}