Today I finally figured out what I needed to do to animate my GIF but now that I have it animated the FPS on my program lowered dramatically. I have my GIF in a serperate function so it doesn't have to reload every texture whenever I try to update the frames of the GIF. I also plan on loading more GIFs if there is a way to fix my FPS drop issue so I need a way to reduce lag on all of them. Is there any easy way to fix this?
My code:
LUtil.cpp:
#include "LUtil.h"
#include <IL/il.h>
#include <IL/ilu.h>
#include "LSpriteSheet.h"
int add = 0;
int zoom = 0;
double leftzoom = -SCREEN_WIDTH;
double topzoom = -SCREEN_HEIGHT;
double rightzoom = SCREEN_WIDTH;
double bottomzoom = SCREEN_HEIGHT;
float sy = 0.f;
int scroll = 0;
GLfloat gCameraX = 0.f, gCameraY = 0.f, gCameraZ = 0.f;
//Sprite texture
LSpriteSheet gArrowSprites;
LSpriteSheet gSamusSprites;
LSpriteSheet jSamusSprites;
bool initGL()
{
//Initialize GLEW
GLenum glewError = glewInit();
if( glewError != GLEW_OK )
{
printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
return false;
}
//Make sure OpenGL 2.1 is supported
if( !GLEW_VERSION_2_1 )
{
printf( "OpenGL 2.1 not supported!\n" );
return false;
}
//Set the viewport
glViewport( 0.f, -0.f, SCREEN_WIDTH, SCREEN_HEIGHT );
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( leftzoom, rightzoom, bottomzoom, topzoom, 1.0, -1.0 );
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPushMatrix();
//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );
//Enable texturing
glEnable( GL_TEXTURE_2D );
glEnable( GL_BLEND );
glDisable( GL_DEPTH_TEST );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
printf( "Error initializing OpenGL! %s\n", gluErrorString(error));
return false;
}
//Initialize DevIL
ilInit();
ilClearColour( 255, 255, 255, 000 );
//Check for error
ILenum ilError = ilGetError();
if( ilError != IL_NO_ERROR )
{
printf( "Error initializing DevIL! %s\n", iluErrorString(ilError) );
return false;
}
return true;
}
LFRect clip;
bool loadMedia()
{
//Load texture
if( !gArrowSprites.loadTextureFromFile( "Textures/SamusM.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}
clip = { 0.f, 0.f, 330.f, 355.f };
//Top left
clip.x = 0.f;
clip.y = 0.f;
gArrowSprites.addClipSprite( clip );
//Top right
clip = {0.f, 0.f, 310.f, 480.f};
clip.x = 331.f;
clip.y = 0.f;
gArrowSprites.addClipSprite( clip );
clip = {0.f, 0.f, 330.f, 125.f};
//Bottom left
clip.x = 0.f;
clip.y = 355.f;
gArrowSprites.addClipSprite( clip );
clip = { 0.f, 0.f, 330.f, 355.f };
//Top left
clip.x = 0.f;
clip.y = 480.f;
gArrowSprites.addClipSprite( clip );
//Top right
clip = {0.f, 0.f, 310.f, 480.f};
clip.x = 331.f;
clip.y = 480.f;
gArrowSprites.addClipSprite( clip );
clip = {0.f, 0.f, 330.f, 125.f};
//Bottom left
clip.x = 0.f;
clip.y = 835.f;
gArrowSprites.addClipSprite( clip );
//Generate VBO
if( !gArrowSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
if( !jSamusSprites.loadTextureFromFile( "Textures/SamusAran.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}
clip = { 0.f, 0.f, 375.f, 562.f };
//Top left
clip.x = 0.f;
clip.y = 0.f;
jSamusSprites.addClipSprite( clip );
if( !jSamusSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
return true;
}
bool textureLoaded = false;
bool loadGif(){
if(textureLoaded == false){
if( !gSamusSprites.loadTextureFromFile( "Textures/SamusG.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}
textureLoaded = true;
}
sy += 214.f;
if(sy == 8988.f){
sy = 0.f;
}
clip = {0.f, 0.f, 213.f, 214.f};
clip.x = 0.f;
clip.y = sy;
gSamusSprites.addClipSprite( clip );
if( !gSamusSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
return true;
}
void update()
{
}
void render()
{
//Clear color buffer
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
if(add == 0){
if(zoom < 100){
double const f_zoom = 1.0 - 0.01 * zoom;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(leftzoom * f_zoom, rightzoom * f_zoom, bottomzoom * f_zoom, topzoom * f_zoom, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
if(zoom < -102){
double const f_zoom = 1.0 + 0.01 * zoom;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(leftzoom * f_zoom, rightzoom * f_zoom, bottomzoom * f_zoom, topzoom * f_zoom, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
glTranslatef( -1080.f, -782.f, 0.f );
gArrowSprites.renderSprite( 0 );
//Render top right arrow
glTranslatef( +1080.f, +782.f, 0.f );
glTranslatef( 1085.f, -120.f, 0.f );
gArrowSprites.renderSprite( 1 );
//Render bottom left arrow
glTranslatef( -1085.f, +120.f, 0.f );
glTranslatef( 0.f, 885.f ,0.f );
gArrowSprites.renderSprite( 2 );
glTranslatef(0.f, -885.f, 0.f);
jSamusSprites.renderSprite( 0 );
glTranslatef( -620.f, -855.f, 0.f );
glTranslatef( 620.f, 0.f , 0.f );
gSamusSprites.renderSprite( 0 );
}
if(add == 1){
if(zoom < 100){
double const f_zoom = 1.0 - 0.01 * zoom;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(leftzoom * f_zoom, rightzoom * f_zoom, bottomzoom * f_zoom, topzoom * f_zoom, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
if(zoom < -102){
double const f_zoom = 1.0 + 0.01 * zoom;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(leftzoom * f_zoom, rightzoom * f_zoom, bottomzoom * f_zoom, topzoom * f_zoom, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
glTranslatef( -1080.f, -782.f, 0.f );
gArrowSprites.renderSprite( 3 );
glTranslatef( +1080.f, +782.f, 0.f );
glTranslatef( 1085.f, -120.f, 0.f );
gArrowSprites.renderSprite( 4 );
glTranslatef( -1085.f, +120.f, 0.f );
glTranslatef( 0.f, 885.f ,0.f );
gArrowSprites.renderSprite( 5 );
glTranslatef(0.f, -885.f, 0.f);
jSamusSprites.renderSprite( 0 );
glTranslatef( -620.f, -855.f, 0.f );
glTranslatef( 620.f, 0.f , 0.f );
gSamusSprites.renderSprite( 0 );
}
glLoadIdentity();
glutSwapBuffers();
}
void handleKeys( unsigned char key, int x, int y )
{
//If the user presses q
if( key == 'q' && add == 0 )
{
add++;
}
else if( key == 'q' && add == 1)
{
add--;
}
//Update the sprite rectangles so the texture change takes effect
if( key == 27 ) {
exit(0);
}
if(key == 'a') {
gCameraX += 8.f;
}
else if (key == 'd') {
gCameraX -= 8.f;
}
else if (key == 'w') {
gCameraY += 8.f;
}
else if (key == 's') {
gCameraY -= 8.f;
}
else if (key == '+' && zoom != 99) {
zoom += 1;
}
else if (key == '-' && zoom != -101) {
zoom -= 1;
}
//Take saved matrix off the stack and reset it
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glLoadIdentity();
//Move camera to position
glTranslatef( gCameraX, gCameraY, gCameraZ );
//Save default matrix again with camera translation
glPushMatrix();
}
Main.cpp:
#include "LUtil.h"
void runMainLoop( int val );
void runGifLoop( int val2 );
int main( int argc, char* args[] )
{
glutInit( &argc, args );
glutInitContextVersion( 2, 1 );
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT );
glutCreateWindow( "Samus" );
if( !initGL() )
{
printf( "Unable to initialize graphics library!\n" );
return 1;
}
if( !loadMedia() )
{
printf( "Unable to load media!\n" );
return 2;
}
glutKeyboardFunc( handleKeys );
glutDisplayFunc( render );
glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, 0 );
glutTimerFunc( 1000 / SCREEN_FPS, runGifLoop, 0 );
glutMainLoop();
return 0;
}
void runMainLoop( int val )
{
update();
render();
glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, val );
}
void runGifLoop( int val2 )
{
loadGif();
glutTimerFunc( 1000 / SCREEN_FPS, runGifLoop, val2 );
}
Related
I want to use OpenGL to implement an animation that can be started and paused with mouse clicks. Since I am currently using the GLFW, the functions in GLUT are no longer applicable.
In GLUT, the implementation can be like this:
void windowMouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
// start
glutIdleFunc(idleFunction);
}
else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
// pause
glutIdleFunc(NULL);
}
}
However, glutIdleFunc() does not work in GLFW. I just wrote a coding frame to perform my goal but got stuck in finding the proper function to replace glutIdleFunc().
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
// start
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
// pause
}
}
Is there any function in GLFW that can replace the previous one? Or is there any way to perform continuous animation with GLFW?
Get creative with glfwPostEmptyEvent() and glfwWaitEventsTimeout():
// g++ main.cpp `pkg-config --cflags --libs glfw3 gl`
#include <GLFW/glfw3.h>
void (*idleFunc)(GLFWwindow*) = nullptr;
void idle( GLFWwindow* aWindow )
{
static float angle = 0.0f;
static double prvTime = glfwGetTime();
const double curTime = glfwGetTime();
const double dt = (curTime - prvTime);
prvTime = curTime;
angle += 60.0 * dt;
int w, h;
glfwGetFramebufferSize( aWindow, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPushMatrix();
glRotatef( angle, 0, 0, 1 );
glBegin(GL_TRIANGLES);
glColor3ub( 0, 255, 0 );
glVertex2f( -0.5, -0.5 );
glVertex2f( 0.5, -0.5 );
glVertex2f( 0.0, 0.5 );
glEnd();
glPopMatrix();
glfwSwapBuffers( aWindow );
}
void display( GLFWwindow* aWindow )
{
int w, h;
glfwGetFramebufferSize( aWindow, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glBegin(GL_TRIANGLES);
glColor3ub( 255, 0, 0 );
glVertex2f( -0.5, -0.5 );
glVertex2f( 0.5, -0.5 );
glVertex2f( 0.0, 0.5 );
glEnd();
glfwSwapBuffers( aWindow );
}
void button( GLFWwindow* window, int button, int action, int mode )
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
idleFunc = idle;
glfwPostEmptyEvent();
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
idleFunc = nullptr;
glfwPostEmptyEvent();
}
}
int main( int, char** )
{
glfwInit();
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
glfwMakeContextCurrent( window );
glfwSetMouseButtonCallback( window, button );
while( !glfwWindowShouldClose( window ) )
{
if(idleFunc)
{
idleFunc(window);
glfwWaitEventsTimeout(0.016);
}
else
{
display(window);
glfwWaitEvents();
}
}
glfwTerminate();
}
The glfwPostEmptyEvent() along with the structure of the glfwWindowShouldClose() loop in main() lets you simulate the behavior of glutPostRedisplay() and the glfwWaitEventsTimeout() lets the idleFunc() (if any) run every 16 milliseconds or so.
I am trying to modify an program.implemented in 2015 visual studio. After opening the project in Visual Studio 2019 there are many errors of the type below.
Severity Code Description Project File Line Suppression State
Error C2664 'Model::Model(Model &&)': cannot convert argument 1 from 'const > char [24]' to 'GLchar *' OpenGl
Severity Code Description Project File Line Suppression State
Message Conversion from string literal loses const qualifier (see /Zc:strictStrings) OpenGl
Error formed in that line:
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow *window = glfwCreateWindow( WIDTH, HEIGHT, "LearnOpenGL",
nullptr, nullptr );
if ( nullptr == window )
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate( );
return EXIT_FAILURE;
}
glfwMakeContextCurrent( window );
glfwGetFramebufferSize( window, &SCREEN_WIDTH, &SCREEN_HEIGHT );
// Set the required callback functions
glfwSetKeyCallback( window, KeyCallback );
glfwSetCursorPosCallback( window, MouseCallback );
// GLFW Options
glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_DISABLED );
// Set this to true so GLEW knows to use a modern approach to retrieving
function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
if ( GLEW_OK != glewInit( ) )
{
std::cout << "Failed to initialize GLEW" << std::endl;
return EXIT_FAILURE;
}
// Define the viewport dimensions
glViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
// OpenGL options
glEnable( GL_DEPTH_TEST );
// Setup and compile our shaders
Shader shader( "res/shaders/modelLoading.vert",
"res/shaders/modelLoading.frag" );
// Load models
Model ourModel("res/models/nanosuit.obj");
// Draw in wireframe
//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
glm::mat4 projection = glm::perspective( camera.GetZoom( ), ( float
)SCREEN_WIDTH/( float )SCREEN_HEIGHT, 0.1f, 100.0f );
// Game loop
while( !glfwWindowShouldClose( window ) )
{
// Set frame time
GLfloat currentFrame = glfwGetTime( );
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// Check and call events
glfwPollEvents( );
DoMovement( );
// Clear the colorbuffer
glClearColor( 0.05f, 0.05f, 0.05f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
shader.Use( );
glm::mat4 view = camera.GetViewMatrix( );
glUniformMatrix4fv( glGetUniformLocation( shader.Program, "projection"
), 1, GL_FALSE, glm::value_ptr( projection ) );
glUniformMatrix4fv( glGetUniformLocation( shader.Program, "view" ),
1,
GL_FALSE, glm::value_ptr( view ) );
// Draw the loaded model
glm::mat4 model;
model = glm::translate( model, glm::vec3( 0.0f, -1.75f, 0.0f ) ); //
Translate it down a bit so it's at the center of the scene
model = glm::scale( model, glm::vec3( 0.2f, 0.2f, 0.2f ) ); // It's a
bit too big for our scene, so scale it down
glUniformMatrix4fv( glGetUniformLocation( shader.Program, "model" ),
1, GL_FALSE, glm::value_ptr( model ) );
ourModel.Draw( shader );
// Swap the buffers
glfwSwapBuffers( window );
}
glfwTerminate( );
return 0;
}
// Moves/alters the camera positions based on user input
void DoMovement( )
{
// Camera controls
if ( keys[GLFW_KEY_W] || keys[GLFW_KEY_UP] )
{
camera.ProcessKeyboard( FORWARD, deltaTime );
}
if ( keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN] )
{
camera.ProcessKeyboard( BACKWARD, deltaTime );
}
if ( keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT] )
{
camera.ProcessKeyboard( LEFT, deltaTime );
}
if ( keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT] )
{
camera.ProcessKeyboard( RIGHT, deltaTime );
**strong text** }
}
// Is called whenever a key is pressed/released via GLFW
void KeyCallback( GLFWwindow *window, int key, int scancode, int
action, int mode )
{
if ( GLFW_KEY_ESCAPE == key && GLFW_PRESS == action )
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if ( key >= 0 && key < 1024 )
{
if ( action == GLFW_PRESS )
{
keys[key] = true;
}
else if ( action == GLFW_RELEASE )
{
keys[key] = false;
}
}
}
void MouseCallback( GLFWwindow *window, double xPos, double yPos )
{
if ( firstMouse )
{
lastX = xPos;
lastY = yPos;
firstMouse = false;
}
GLfloat xOffset = xPos - lastX;
GLfloat yOffset = lastY - yPos; // Reversed since y-coordinates go from
bottom to left
lastX = xPos;
lastY = yPos;
camera.ProcessMouseMovement( xOffset, yOffset );
}
the Error exactly in
// Load models
Model ourModel("res/models/nanosuit.obj");
You could pass the model name as a non-const C string:
char tmp[] = "res/models/nanosuit.obj";
Model ourModel(tmp);
I'm trying to animate a gif in my window by making it scroll to each frame on my tilesheet but it currently stays on only one frame. I assume it's because I'm not limiting the fps on the gif but I have no clue how to do that. Anyone?
#max66 I'm trying to obtain an animation by doing this. I'm trying to make it go down the y axis on the texture(which is a sprite tile sheet) which works without the if statement so far but it freezes on the last frame.
My (newish) code:
#include "LUtil.h"
#include <IL/il.h>
#include <IL/ilu.h>
#include "LSpriteSheet.h"
int add = 0;
int zoom = 0;
int factor = 0;
int factor2 = 0;
float y = 0.f;
int scroll = 0;
GLfloat gCameraX = 0.f, gCameraY = 0.f, gCameraZ = 0.f;
//Sprite texture
LSpriteSheet gArrowSprites;
LSpriteSheet gSamusSprites;
bool initGL()
{
//Initialize GLEW
GLenum glewError = glewInit();
if( glewError != GLEW_OK )
{
printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
return false;
}
//Make sure OpenGL 2.1 is supported
if( !GLEW_VERSION_2_1 )
{
printf( "OpenGL 2.1 not supported!\n" );
return false;
}
//Set the viewport
glViewport( 0.f, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT );
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, 5.0, -5.0 );
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPushMatrix();
//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );
//Enable texturing
glEnable( GL_TEXTURE_2D );
glEnable( GL_BLEND );
glDisable( GL_DEPTH_TEST );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
printf( "Error initializing OpenGL! %s\n", gluErrorString(error));
return false;
}
//Initialize DevIL
ilInit();
ilClearColour( 255, 255, 255, 000 );
//Check for error
ILenum ilError = ilGetError();
if( ilError != IL_NO_ERROR )
{
printf( "Error initializing DevIL! %s\n", iluErrorString(ilError) );
return false;
}
return true;
}
bool loadMedia()
{
//Load texture
if( !gArrowSprites.loadTextureFromFile( "SamusM.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}
LFRect clip = { 0.f, 0.f, 330.f, 355.f };
//Top left
clip.x = 0.f;
clip.y = 0.f;
gArrowSprites.addClipSprite( clip );
//Top right
clip = {0.f, 0.f, 310.f, 480.f};
clip.x = 331.f;
clip.y = 0.f;
gArrowSprites.addClipSprite( clip );
clip = {0.f, 0.f, 330.f, 125.f};
//Bottom left
clip.x = 0.f;
clip.y = 355.f;
gArrowSprites.addClipSprite( clip );
clip = { 0.f, 0.f, 330.f, 355.f };
//Top left
clip.x = 0.f;
clip.y = 480.f;
gArrowSprites.addClipSprite( clip );
//Top right
clip = {0.f, 0.f, 310.f, 480.f};
clip.x = 331.f;
clip.y = 480.f;
gArrowSprites.addClipSprite( clip );
clip = {0.f, 0.f, 330.f, 125.f};
//Bottom left
clip.x = 0.f;
clip.y = 835.f;
gArrowSprites.addClipSprite( clip );
//Generate VBO
if( !gArrowSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
if( !gSamusSprites.loadTextureFromFile( "SamusG.png" ) )
{
printf( "Unable to load texture!\n" );
return false;
}
while(scroll != 40){
y += 214.f;
scroll++;
if(scroll == 40){
scroll = 0;
}
}
clip = {0.f, 0.f, 213.f, 214.f};
clip.x = 0.f;
clip.y = y;
gSamusSprites.addClipSprite( clip );
if( !gSamusSprites.generateDataBuffer() )
{
printf( "Unable to clip sprite sheet!\n" );
return false;
}
return true;
}
void update()
{
}
void render()
{
//Clear color buffer
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
if(add == 0){
if(zoom < 101){
double const f_zoom = 1.0 + 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}
if(zoom < -10){
double const f_zoom = 1.0 - 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}
glTranslatef( -100.f, 178.f, 0.f );
gArrowSprites.renderSprite( 0 );
//Render top right arrow
glTranslatef( +100.f, -178.f, 0.f );
glTranslatef( 1240.f, 240.f, 0.f );
gArrowSprites.renderSprite( 1 );
//Render bottom left arrow
glTranslatef( -1240.f, +240.f, 0.f );
glTranslatef( 620.f, 500.f ,0.f );
gArrowSprites.renderSprite( 2 );
glTranslatef( -620.f, -500.f, 0.f );
glTranslatef( 620.f, 0.f , 0.f );
gSamusSprites.renderSprite( 0 );
}
if(add == 1){
if(zoom < 101){
double const f_zoom = 1.0 + 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}
if(zoom < -10){
double const f_zoom = 1.0 - 0.1 * zoom;
glScaled(f_zoom, f_zoom, f_zoom);
}
glTranslatef( -100.f, 178.f, 0.f );
gArrowSprites.renderSprite( 3 );
glTranslatef( +100.f, -178.f, 0.f );
glTranslatef( 1240.f, 240.f, 0.f );
gArrowSprites.renderSprite( 4 );
glTranslatef( -1240.f, +240.f, 0.f );
glTranslatef( 620.f, 500.f ,0.f );
gArrowSprites.renderSprite( 5 );
}
glLoadIdentity();
glutSwapBuffers();
}
void handleKeys( unsigned char key, int x, int y )
{
//If the user presses q
if( key == 'q' && add == 0)
{
add++;
}
else if( key == 'q' && add == 1)
{
add--;
}
//Update the sprite rectangles so the texture change takes effect
if( key == 27 ) {
exit(0);
}
if(key == 'a') {
gCameraX += 8.f;
factor--;
factor2++;
}
else if (key == 'd') {
gCameraX -= 8.f;
factor++;
factor2--;
}
else if (key == 'w') {
gCameraY += 8.f;
}
else if (key == 's') {
gCameraY -= 8.f;
}
else if (key == '+' && zoom != 100) {
zoom += 1;
if(factor >= 19) {
gCameraX -= 64.f;
}
if(factor2 >= 33){
gCameraX += 16.f;
}
else{
gCameraX -= 64.f;
gCameraY -= 50.f;
}
}
else if (key == '-' && zoom != -9) {
zoom -= 1;
if(factor >= 19){
gCameraX += 64.f;
}
if(factor2 >= 33){
gCameraX -= 32.f;
}
else{
gCameraX += 64.f;
gCameraY += 50.f;
}
}
//Take saved matrix off the stack and reset it
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glLoadIdentity();
//Move camera to position
glTranslatef( gCameraX, gCameraY, gCameraZ );
//Save default matrix again with camera translation
glPushMatrix();
}
EDIT: I just tried adjusting the y coordinate value in the for loop and nothing was happening so I tried removing the if statement and still nothing. But if I adjust the y value at the top of my file the texture will change. So why isn't my loop adding to my y value?
I suppose it's because in your for
for(int scroll; scroll > 40; scroll++){
you declare the scroll variable but you don't initialize it.
So scroll start with an undefined value that can be greather than 40.
Solution (I suppose): initialize scroll.
p.s.: sorry for my bad English.
--- EDIT 2016.05.23 ---
Look at this code
while(scroll != 40){
y += 214.f;
scroll++;
if(scroll == 40){
scroll = 0;
}
}
clip = {0.f, 0.f, 213.f, 214.f};
clip.x = 0.f;
clip.y = y;
gSamusSprites.addClipSprite( clip );
If scrool reach the while with a value different from 40, the while never exit and you only increment (forever) y.
I suppose you intention was to call gSamusSprites.addClipSprite() (or a similar function) for every iteration of the while.
I suppose your intention was to iterate the cycle only 40 times and exit.
If my suppositions are correct, you can try something like [caution: not tested]
clip = {0.f, 0.f, 213.f, 214.f};
for (scroll = 0; scroll < 40; ++scroll, clip.y += 214.f )
gSamusSprites.addClipSprite( clip ); // or a different function?
In this post the rectangle moved via mouse. I want to add a triangle and move like rectangle via mouse.
The triangle function like this:
void drawTriangle(float x,float y,float size){
glPushMatrix();
glTranslatef( x, y, 0.0f );
glScalef( size, size, 1.0f );
glBegin( GL_TRIANGLES );
glColor3ub( 255, 255, 255 );
glVertex2f( -1, 1 );
glVertex2f( 1, -1 );
glVertex2f( 1, 1 );
glEnd();
glPopMatrix();
Rectangle and triangle moved together. But I want to move it different. So what is my wrong?
You'll have to maintain an array of Shape objects and test each one for mouse collisions, as well as keep track of which Shape you're dragging:
#include <GL/glut.h>
#include <vector>
using namespace std;
struct Shape
{
float mX, mY;
float mSize;
bool mIsRectangle;
bool PointInside( const float x, const float y ) const
{
return
mX - mSize <= x && x <= mX + mSize
&&
mY - mSize <= y && y <= mY + mSize;
}
};
vector< Shape > objects;
Shape* dragging = NULL;
void mouse( int button, int state, int x, int y )
{
if( GLUT_DOWN == state )
{
dragging = NULL;
for( Shape& obj : objects )
{
if( obj.PointInside( x, y ) )
{
dragging = &obj;
glutPostRedisplay();
break;
}
}
}
else
{
dragging = NULL;
}
}
void motion( int x, int y )
{
if( dragging )
{
dragging->mX = x;
dragging->mY = y;
glutPostRedisplay();
}
}
void drawRect( float x, float y, float size )
{
glPushMatrix();
glTranslatef( x, y, 0.0f );
glScalef( size, size, 1.0f );
glBegin( GL_QUADS );
glColor3ub( 255, 255, 255 );
glVertex2f( -1, -1 );
glVertex2f( 1, -1 );
glVertex2f( 1, 1 );
glVertex2f( -1, 1 );
glEnd();
glPopMatrix();
}
void drawTriangle( float x, float y, float size )
{
glPushMatrix();
glTranslatef( x, y, 0.0f );
glScalef( size, size, 1.0f );
glBegin( GL_TRIANGLES );
glColor3ub( 255, 255, 255 );
glVertex2f( -1, 1 );
glVertex2f( 1, -1 );
glVertex2f( 1, 1 );
glEnd();
glPopMatrix();
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
for( const Shape& obj : objects )
{
if( obj.mIsRectangle )
drawRect( obj.mX, obj.mY, obj.mSize );
else
drawTriangle( obj.mX, obj.mY, obj.mSize );
}
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMouseFunc( mouse );
glutMotionFunc( motion );
Shape temp;
temp.mSize = 50;
temp.mX = temp.mY = 100;
temp.mIsRectangle = true;
objects.push_back( temp );
temp.mX = temp.mY = 200;
temp.mIsRectangle = false;
objects.push_back( temp );
glutMainLoop();
return 0;
}
As per my question on Math Stackexchange:
I am working on a project for my 3D Graphics class. The project is built with C++ and OpenGL / Glut. Basically, I create a horizontal rectangle window, subdivided into two squares. On the left, I have a two dimensional coordinate plane, which allows the users to point and click and define a profile 'curve'. I then need to wrap this curve around the Y-axis n number of times.
So, would anyone be able to guide me as to how I would use Trigonometry to calculate the X and Z values of the successive points? If for example, a user clicks and creates the point:
(1, 1, 0)
And their sweep resolution (n) is set to, say, 10, then I need to redraw that point every 36 (360/10) degrees around the Y-axis.
Am I correct in assuming that Trigonometry will help me here? If so, can someone please enlighten me a bit as to how to calculate the location of a translated point in 3D space? It's been a while since I took Trig, and I don't believe we ever left 2D space.
EDIT: I attempted to use:
x'=xcos(theta)-zsin(theta)
y'=y
z'=xsin(theta)+zcos(theta)
, as per my understanding of AMPerrine's answer, and I don't think it worked as I'd hoped:
// this is in a loop
// setup the new angle
double angle = i>0 ? (360/sweepResolutionMod)*i : 0;
angle = angle * (M_PI/180);
// for each point...
for( int i=0; i<clickedPoints.size(); i++ )
{
// initial point, normalized
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;
// log the initial point
cout << "(" << tempX << ", " << tempY << ", 0.0) by " << angle << " radians = ";
// generate the new point
GLfloat newX = (tempX * cos(angle)) - (tempZ * sin(angle));
GLfloat newY = tempY;
GLfloat newZ = (tempX * sin(angle)) - (tempZ * cos(angle));
// log the new point
cout << "(" << newX << ", " << newY << ", " << newZ << ")\n";
// render the new point
glVertex3d(newX, newY, newZ);
}
This produces no screen output, but console output of:
(0.048, -0.296, 0.0) by 0 radians = (0.048, -0.296, 0)
(0.376, -0.508, 0.0) by 0 radians = (0.376, -0.508, 0)
(0.72, -0.204, 0.0) by 0 radians = (0.72, -0.204, 0)
(0.652, 0.176, 0.0) by 0 radians = (0.652, 0.176, 0)
(0.368, 0.504, 0.0) by 0 radians = (0.368, 0.504, 0)
(0.048, -0.296, 0.0) by 0.628319 radians = (0.0388328, -0.296, 0.0282137)
(0.376, -0.508, 0.0) by 0.628319 radians = (0.30419, -0.508, 0.221007)
(0.72, -0.204, 0.0) by 0.628319 radians = (0.582492, -0.204, 0.423205)
(0.652, 0.176, 0.0) by 0.628319 radians = (0.527479, 0.176, 0.383236)
(0.368, 0.504, 0.0) by 0.628319 radians = (0.297718, 0.504, 0.216305)
(0.048, -0.296, 0.0) by 1.25664 radians = (0.0148328, -0.296, 0.0456507)
(0.376, -0.508, 0.0) by 1.25664 radians = (0.11619, -0.508, 0.357597)
(0.72, -0.204, 0.0) by 1.25664 radians = (0.222492, -0.204, 0.684761)
(0.652, 0.176, 0.0) by 1.25664 radians = (0.201479, 0.176, 0.620089)
(0.368, 0.504, 0.0) by 1.25664 radians = (0.113718, 0.504, 0.349989)
...
(0.048, -0.296, 0.0) by 6.28319 radians = (0.048, -0.296, -1.17566e-17)
(0.376, -0.508, 0.0) by 6.28319 radians = (0.376, -0.508, -9.20934e-17)
(0.72, -0.204, 0.0) by 6.28319 radians = (0.72, -0.204, -1.76349e-16)
(0.652, 0.176, 0.0) by 6.28319 radians = (0.652, 0.176, -1.59694e-16)
(0.368, 0.504, 0.0) by 6.28319 radians = (0.368, 0.504, -9.0134e-17)
I'm not sure what exactly is going on here, but I'm having a terrible time trying to figure it out, so please don't think I'm trying to get double reputation or anything, I'm just really stuck.
EDIT 2: Here is my whole display routine for my perspective subview:
void displayPersp(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt (-2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
// draw the axis
glBegin(GL_LINES);
// x
glVertex3f(500.0, 0.0, 0.0);
glVertex3f(-500.0, 0.0, 0.0);
// y
glVertex3f(0.0, -500.0, 0.0);
glVertex3f(0.0, 500.0, 0.0);
// z
glVertex3f(0.0, 0.0, -500.0);
glVertex3f(0.0, 0.0, 500.0);
glEnd();
cout << endl;
// loop as many number of times as we are going to draw the points around the Y-Axis
for( int i=0; i<=sweepResolutionMod; i++ )
{
cout << endl;
// setup the new angle
double angle = i>0 ? (360/sweepResolutionMod)*i : 0;
angle = angle * (M_PI/180);
// for each point...
for( int i=0; i<clickedPoints.size(); i++ )
{
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;
cout << "(" << tempX << ", " << tempY << ", 0.0) by " << angle << " degrees = ";
GLfloat newX = (tempX * cos(angle)) - (tempZ * sin(angle));
GLfloat newY = tempY;
GLfloat newZ = (tempX * sin(angle)) - (tempZ * cos(angle));
cout << "(" << newX << ", " << newY << ", " << newZ << ")\n";
glVertex3d(newX, newY, newZ);
}
// the following was my old solution, using OpenGL's rotate(), but that
// didn't allow me to get back the new point's coordinates.
/*
glRotatef(angle, 0.0, 1.0, 0.0);
// draw a line?
if( clickedPoints.size() > 1 )
{
glBegin(GL_LINE_STRIP);
for(int i=0; i<clickedPoints.size(); i++ )
{
glVertex3f((clickedPoints[i].x-250)/250, (clickedPoints[i].y-250)/250, 0.0);
}
glEnd();
}
// everyone gets points
glBegin(GL_POINTS);
for(int i=0; i<clickedPoints.size(); i++ )
{
glVertex3f((clickedPoints[i].x-250)/250, (clickedPoints[i].y-250)/250, 0.0);
}
glEnd();
*/
}
glutSwapBuffers();
}
EDIT 3: Here is a terrible illustration that illustrates what I need to do. I know the perspective seems off, but what I'm attempting to acquire is the green 'horizontals' in the right subview (this is using the commented out glRotatef() code above):
FINAL EDIT (for future generations!):
Here is what I finally got working, after discussing some linear algebra with a teacher at college:
void displayPersp(void)
{
glClear(GL_COLOR_BUFFER_BIT);
gluLookAt (-2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
// draw the axis
glBegin(GL_LINES);
// x
glVertex3f(500.0, 0.0, 0.0);
glVertex3f(-500.0, 0.0, 0.0);
// y
glVertex3f(0.0, -500.0, 0.0);
glVertex3f(0.0, 500.0, 0.0);
// z
glVertex3f(0.0, 0.0, -500.0);
glVertex3f(0.0, 0.0, 500.0);
glEnd();
cout << endl;
double previousTheta = 0.0;
for( int i=0; i<=sweepResolutionMod; i++ )
{
double theta = i>0 ? (360/sweepResolutionMod)*i : 0;
theta = theta * (M_PI/180);
if( clickedPoints.size() > 1 )
{
// the 'vertical' piece
glBegin(GL_LINE_STRIP);
for(int i=0; i<clickedPoints.size(); i++ )
{
// normalize
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;
// new points
GLfloat newX = ( tempX * cos(theta) ) + ( tempZ * sin(theta) );
GLfloat newY = tempY;
GLfloat newZ = ( tempZ * cos(theta) ) - ( tempX * sin(theta) );
glVertex3f(newX, newY, newZ);
}
glEnd();
// the 'horizontal' piece
if( previousTheta != theta )
{
glBegin(GL_LINES);
for(int i=0; i<clickedPoints.size(); i++ )
{
// normalize
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;
// new points
GLfloat newX = ( tempX * cos(theta) ) + ( tempZ * sin(theta) );
GLfloat newY = tempY;
GLfloat newZ = ( tempZ * cos(theta) ) - ( tempX * sin(theta) );
// previous points
GLfloat previousX = ( tempX * cos(previousTheta) ) + ( tempZ * sin(previousTheta) );
GLfloat previousY = tempY;
GLfloat previousZ = ( tempZ * cos(previousTheta) ) - ( tempX * sin(previousTheta) );
// horizontal component
glVertex3f(newX, newY, newZ);
glVertex3f(previousX, previousY, previousZ);
}
glEnd();
}
}
previousTheta = theta;
}
glutSwapBuffers();
}
Edit 2: Okay, I see the problem you're running into -- it's a limitation I'd forgotten about (so the code I'd posted previously was dead wrong and wouldn't work at all). The problem is that you're not allowed to call glRotate between a glBegin/glEnd pair -- if you do, it'll set an error flag, and no more drawing will be done.
That does mean you pretty much have to handle the rotation yourself. Fortunately, that's a bit simpler than you've tried to make it:
static const double pi = 3.1416;
for (int point=0; point<NUM_POINTS; point++) {
glBegin(GL_LINE_STRIP);
for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
double x = cos(theta);
double z = sin(theta);
glVertex3d(points[point][0]*x, points[point][1], -1.0-points[point][0]*z);
}
glEnd();
}
As-is, this code uses -1.0 along the Z axis as the center of rotation. You can obviously move that where you wish, though anything outside your clipping frustum obviously won't display.
Also note that to get a wireframe, you'll have to draw both your "vertical", and your "horizontal" lines separately, so the code will look something like this:
for (int point=0; point<NUM_POINTS; point++) {
glBegin(GL_LINE_STRIP);
for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
double x = cos(theta);
double z = sin(theta);
glVertex3d(points[point][0]*x, points[point][1], -1.0 - points[point][0]*z);
}
glEnd();
}
for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
glBegin(GL_LINE_STRIP);
for (int point=0; point<NUM_POINTS; point++) {
double x = cos(theta);
double z = sin(theta);
glVertex3d(points[point][0]*x, points[point][1], -1.0 - points[point][0]*z);
}
glEnd();
}
The trig functions take angles in radians, not degrees.
I also suspect that your viewport isn't setup properly, which explains why you can't see anything on the screen. Typically when I think stuff isn't rendering, it usually is, however, I haven't configured the camera, lighting and other stuff correctly.
Looks like you're trying to construct a surface of revolution/solid of revolution/"lathe object".
A working example:
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <vector>
#include <cmath>
using namespace std;
using namespace glm;
struct Vertex
{
Vertex( const vec3& position, const vec3& normal )
: position( position )
, normal( normal )
{}
vec3 position;
vec3 normal;
};
// spin the pts array around the Z axis.
// pts.x will become the radius, and pts.y will become the height
// pts should be sorted by y-coordinate
vector< Vertex > Lathe( const vector< vec2 >& pts, unsigned int segments = 32 )
{
// precalculate circle points
vector< vec2 > circlePts;
for( unsigned int i = 0; i <= segments; ++i )
{
float angle = ( i / (float)segments ) * 3.14159f * 2.0f;
circlePts.push_back( vec2( cos( angle ), sin( angle ) ) );
}
// fill each layer
typedef vector< vec3 > Layer;
typedef vector< Layer > Layers;
Layers layers( pts.size(), Layer( circlePts.size() ) );
for( size_t i = 0; i < pts.size(); ++i )
{
for( unsigned int j = 0; j < circlePts.size(); ++j )
{
layers[i][j] = vec3( circlePts[j] * pts[i].x, pts[i].y );
}
}
// move through layers generating triangles
vector< Vertex > verts;
for( size_t i = 1; i < layers.size(); ++i )
{
const Layer& prvLayer = layers[ i-1 ];
const Layer& curLayer = layers[ i-0 ];
for( size_t j = 1; j < circlePts.size(); ++j )
{
// upper = cur layer
// UL -- UR
// left | 0 / | right
// = j-1 | / 1 | = j-0
// LL -- LR
// lower = prv layer
const vec3& LL = prvLayer[ j-1 ]; // lower-left
const vec3& LR = prvLayer[ j-0 ]; // lower-right
const vec3& UL = curLayer[ j-1 ]; // upper-left
const vec3& UR = curLayer[ j-0 ]; // upper-right
// triangle0: LL -> UR -> UL
const vec3 normal0 = normalize( cross( UR - LL, UL - LL ) );
verts.push_back( Vertex( LL, normal0 ) );
verts.push_back( Vertex( UR, normal0 ) );
verts.push_back( Vertex( UL, normal0 ) );
// triangle1: LL -> LR -> UR
const vec3 normal1 = normalize( cross( LR - LL, UL - LL ) );
verts.push_back( Vertex( LL, normal1 ) );
verts.push_back( Vertex( LR, normal1 ) );
verts.push_back( Vertex( UR, normal1 ) );
}
}
return verts;
}
// mouse state
int btn;
ivec2 startMouse;
ivec2 startRot, curRot;
void mouse(int button, int state, int x, int y )
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
startRot = curRot;
}
}
void motion( int x, int y )
{
ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
if( btn == GLUT_LEFT_BUTTON )
{
curRot = startRot + ( curMouse - startMouse );
}
glutPostRedisplay();
}
vector< Vertex > model;
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
gluPerspective( 60, ar, 0.1, 40 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -10 );
glPushMatrix();
glRotatef( curRot.x % 360, 0, 1, 0 );
glRotatef( -curRot.y % 360, 1, 0, 0 );
// draw model
if( !model.empty() )
{
glColor3ub( 255, 0, 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
glDrawArrays( GL_TRIANGLES, 0, model.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
}
// draw bounding cube
glDisable( GL_LIGHTING );
glColor3ub( 255, 255, 255 );
glutWireCube( 7 );
glEnable( GL_LIGHTING );
glPopMatrix();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
vector< vec2 > pts;
pts.push_back( vec2( 0.1, -3 ) );
pts.push_back( vec2( 2, -2 ) );
pts.push_back( vec2( 3, -1 ) );
pts.push_back( vec2( 1, 0 ) );
pts.push_back( vec2( 3, 1 ) );
pts.push_back( vec2( 4, 2 ) );
pts.push_back( vec2( 4, 3 ) );
model = Lathe( pts );
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glEnable( GL_DEPTH_TEST );
// set up lighting
glShadeModel( GL_SMOOTH );
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
glEnable( GL_LIGHTING );
// set up "headlamp"-like light
glEnable( GL_LIGHT0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat position[] = { 0, 0, 1, 0 };
glLightfv( GL_LIGHT0, GL_POSITION, position );
glPolygonMode( GL_FRONT, GL_FILL );
glPolygonMode( GL_BACK, GL_LINE );
glutMainLoop();
return 0;
}