I got some problem with OpenGL matrix system.
I made five instances like below. I want to get their individual working.
C_IMGMGR cImgmgr1( 200 , 170 );
C_IMGMGR cImgmgr2( 200 , 170 );
C_IMGMGR cImgmgr3( 200 , 170 );
C_IMGMGR cImgmgr4( 200 , 170 );
C_IMGMGR cImgmgr5( 200 , 170 );
this is main,
int main( int argc, char** argv )
{
int nWinSizeX = 1280;
int nWinSizeY = 768;
glutInit( &argc , argv );
mainWindow = CreateMain( nWinSizeX , nWinSizeY );
SetProjection( nWinSizeX , nWinSizeY );
SetStateSettings();
NowFrameMove();
return 1;
}
and SetProjection()
void SetProjection( int nWinSizeX , int nWinSizeY )
{
cImgmgr1.Init_Viewport( 540 , 599 , nWinSizeX , nWinSizeY );
cImgmgr2.Init_Viewport( 40 , 299 , nWinSizeX , nWinSizeY );
cImgmgr3.Init_Viewport( 540 , 299 , nWinSizeX , nWinSizeY );
cImgmgr4.Init_Viewport( 1040 , 299 , nWinSizeX , nWinSizeY );
cImgmgr5.Init_Viewport( 540 , -1 , nWinSizeX , nWinSizeY );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0 , 1280 , 0.0 , 768 , -10000.0 , 10000.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( (200 / 2) , (170 / 2) , 0 );
}
and SetStateSetting()
void SetStateSettings()
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_TEXTURE_2D );
cImgmgr1.Init_Sprite( "data\\Image\\symbol01_Pay\\" );
cImgmgr2.Init_Sprite( "data\\Image\\symbol01_Pay\\" );
cImgmgr3.Init_Sprite( "data\\Image\\symbolTemp_Pay\\" );
cImgmgr4.Init_Sprite( "data\\Image\\symbol01_Pay\\" );
cImgmgr5.Init_Sprite( "data\\Image\\symbol01_Pay\\" );
}
here is Update() for glutDisplayFunc() and glutIdleFunc(),
void Update()
{
//////////////////////////////////////////////////////////////////////////
//Process
cImgmgr1.Process( FLIP_VERTICAL );
cImgmgr2.Process( FLIP_HORIZONTAL );
cImgmgr3.Process( NORMAL );
cImgmgr4.Process( NORMAL );
cImgmgr5.Process( NORMAL );
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//Render
glClearColor( 0.0F , 0.0F , 0.0F , 0.0F );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glClearDepth( 1.0 );
cImgmgr1.Render_Sprite( cImgmgr1.Get_Frame() );
cImgmgr2.Render_Sprite( cImgmgr2.Get_Frame() );
cImgmgr3.Render_Sprite( cImgmgr3.Get_Frame() );
cImgmgr4.Render_Sprite( cImgmgr4.Get_Frame() );
cImgmgr5.Render_Sprite( cImgmgr5.Get_Frame() );
//////////////////////////////////////////////////////////////////////////
glutSwapBuffers();
}
and IMGMGR class,
void C_IMGMGR::Process( E_RENDER_MODE eMode )
{
if( m_nFrame >= m_nFileCount )
m_nFrame = 0;
switch ( eMode )
{
case NORMAL :
break;
case FLIP_VERTICAL :
m_fRotationAngle = 1.0F;
m_fRotationX = 1.0F;
break;
case FLIP_HORIZONTAL :
m_fRotationAngle = 1.0F;
m_fRotationY = 1.0F;
break;
case FAN_LEFT :
m_fRotationAngle = 1.0F;
m_fRotationZ = 1.0F;
break;
case FAN_RIGHT :
m_fRotationAngle = 1.0F;
m_fRotationZ = -1.0F;
break;
case TRANSLATE_VERTICAL :
break;
case TRANSLATE_HORIZONTAL :
break;
}
}
void C_IMGMGR::Render_Sprite( int nFrame )
{
glBindTexture( GL_TEXTURE_2D , m_pLoadedSprite[nFrame] );
glViewport( m_nViewPortX , m_nViewPortY , m_nScreenW , m_nScreenH );
glPushMatrix();
glRotatef( m_fRotationAngle , m_fRotationX , m_fRotationY , m_fRotationZ );
glTranslatef( m_fTranslateX , m_fTranslateY , m_fTranslateZ );
glScalef( m_fScaleX , m_fScaleY , m_fScaleZ );
glBegin( GL_QUADS );
glTexCoord2f( 0.0F , 1.0F); glVertex2f( -(float)m_nImgX_half , -(float)m_nImgY_half);
glTexCoord2f( 1.0F , 1.0F); glVertex2f( (float)m_nImgX_half , -(float)m_nImgY_half);
glTexCoord2f( 1.0F , 0.0F); glVertex2f( (float)m_nImgX_half , (float)m_nImgY_half);
glTexCoord2f( 0.0F , 0.0F); glVertex2f( -(float)m_nImgX_half , (float)m_nImgY_half);
glEnd();
glPopMatrix();
}
they rotating together that looks like sharing FLIP_VERTICAL and FLIP_HORIZONTAL.
so, how can I separate their matrix for individual instance working?
There are a couple of issues with the posted code:
OpenGL operates as a state machine. When you make a draw call, it uses the state set at the time of the draw call. Therefore, the transformations need to be specified before the draw call if they should be applied to a draw call.
Related, calls like glRotatef() and glTranslatef() modify the current transformation matrix. Unless you do something about it, each of these calls combines the specified transformation with the previous current transformation. If you simply make a few of these calls for each draw call, all the transformations will be combined.
To fix these two problems, you need to change the order of the calls, and use glPushMatrix() and glPopMatrix() to save/restore the previous transformation when you apply the transformations for a specific draw call. The code will then look like this:
glPushMatrix();
glRotatef( m_fRotationAngle , m_fRotationX , m_fRotationY , m_fRotationZ );
glTranslatef( m_fTranslateX , m_fTranslateY , m_fTranslateZ );
glScalef( m_fScaleX , m_fScaleY , m_fScaleZ );
glBegin( GL_QUADS );
glTexCoord2f( 0.0F , 1.0F); glVertex2f( -(float)m_nImgX_half , -(float)m_nImgY_half);
glTexCoord2f( 1.0F , 1.0F); glVertex2f( (float)m_nImgX_half , -(float)m_nImgY_half);
glTexCoord2f( 1.0F , 0.0F); glVertex2f( (float)m_nImgX_half , (float)m_nImgY_half);
glTexCoord2f( 0.0F , 0.0F); glVertex2f( -(float)m_nImgX_half , (float)m_nImgY_half);
glEnd();
glPopMatrix();
I hope you are already aware that almost all of the OpenGL calls used in this code are deprecated, and not available anymore in modern versions of OpenGL. If you want to learn current OpenGL, look for tutorials for the OpenGL Core Profile, or for OpenGL ES 2.0 or later.
Related
I am not sure why why code doesn't show a rotating cube. I am looking for the reason why. I think it has something to do with the perspective or view but I am not sure. I just need to understand why I can't get a simple cube onto the screen.
#include <iostream>
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
#include "LoadShader.hpp" // just a function in a header that returns a GLuint for a shaderProgram
#define FS1 "shader1.frag"
#define VS1 "shader1.vert"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <assimp/cimport.h>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// The MAIN function, from here we start the application and run the game loop
int main()
{
// Init GLFW
glfwInit( );
// Set all the required options for GLFW
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
glfwWindowHint( GLFW_RESIZABLE, GL_FALSE );
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow *window = glfwCreateWindow( WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr );
int screenWidth, screenHeight;
glfwGetFramebufferSize( window, &screenWidth, &screenHeight );
if ( nullptr == window )
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate( );
return EXIT_FAILURE;
}
glfwMakeContextCurrent( window );
// 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;
}
glEnable( GL_DEPTH_TEST ) ;
//glDepthFunc( GL_LESS ) ;
// Define the viewport dimensions
glViewport( 0, 0, screenWidth, screenHeight );
//glMatrixMode(GL_PROJECTION);
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[ ] =
{ // verticies a0 // colors a1
// front
-1.0, -1.0, 1.0, .70f , 0.32f , 0.31f ,
1.0, -1.0, 1.0, .20f , 0.4f , 0.21f ,
1.0, 1.0, 1.0, .50f , 0.32f , 0.71f ,
-1.0, 1.0, 1.0, .60f , 0.62f , 0.11f ,
// back
-1.0, -1.0, -1.0, .30f , 0.87f , 0.60f ,
1.0, -1.0, -1.0, .30f , 0.87f , 0.f ,
1.0, 1.0, -1.0, .10f , 0.f , 0.60f ,
-1.0, 1.0, -1.0, .20f , 0.87f , 0.60f ,
// side Right
1.0f , 1.0 , 1.0 , .45f , .3f , .4f ,
1.0 , -1.0 , 1.0 , .5f , .8f, .1f ,
1.0 , -1.0 , -1.0 , .3f , .6f , .0f ,
1.0 , 1.0 , -1.0 , .45f , .87f , .53f ,
// left Side
-1.0f , 1.0 , 1.0 , .45f , .23f , .54f ,
-1.0 , -1.0 , 1.0 , .51f , .84f, .81f ,
-1.0 , -1.0 , -1.0 , .6f , .4f , .78f ,
-1.0 , 1.0 , -1.0 , .45f , .87f , .53f ,
//top
-1.f , 1.f , 1.f , .35f , .87f , .54f ,
-1.f , 1.f , -1.f , .45f , .98f, .92f ,
1.f , 1.f , 1.f , .50f , 0.f , .32f ,
1.f , 1.f , -1.f , 1.f , .72f , .87f ,
// bottom
-1.f , -1.f , 1.f , .35f , .87f , .54f ,
-1.f , -1.f , -1.f , .45f , .98f, .92f ,
1.f , -1.f , 1.f , .50f , .89f , .32f ,
1.f , -1.f , -1.f , 0.f , .72f , .87f
};
GLuint indices[ ] =
{
0 , 1 , 2 , 0 , 2 , 3 ,
4 , 5 , 6 , 4 , 6 , 7 ,
8 , 9 , 10 , 8 , 10 , 11 ,
12 , 13 , 14 , 12 , 14 , 15 ,
16 , 19 , 18 , 16 , 17 , 19 ,
20 , 23 , 22 , 20 , 21 , 23
} ;
int numOfIndices = sizeof( indices ) / sizeof ( GLuint ) ;
std::cout << numOfIndices << std::endl ;
GLuint VAO , VBO , EBO ;
glGenVertexArrays( 1 , &VAO ) ;
glBindVertexArray( VAO ) ;
glGenBuffers( 1 , &VBO ) ;
glBindBuffer( GL_ARRAY_BUFFER , VBO ) ;
glBufferData( GL_ARRAY_BUFFER , sizeof( vertices ) , vertices , GL_STATIC_DRAW ) ;
glVertexAttribPointer( 0 , 3 , GL_FLOAT , GL_FALSE , 6 * sizeof(GLfloat) , ( GLvoid * ) 0 ) ;
glEnableVertexAttribArray( 0 ) ;
glVertexAttribPointer( 1 , 3 , GL_FLOAT , GL_FALSE , 6 * sizeof(GLfloat) , (GLvoid*)(3 * sizeof(GL_FLOAT)) ) ;
glEnableVertexAttribArray( 1 ) ;
glGenBuffers( 1 , &EBO ) ;
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , EBO ) ;
glBufferData( GL_ELEMENT_ARRAY_BUFFER , sizeof( indices ) , indices , GL_STATIC_DRAW ) ;
GLuint program = LoadShaders( VS1 , FS1 ) ;
glUseProgram( program ) ;
float rotationDegrees = 1.f ;
float fov = 1.0f ;
glm::mat4 view;
view = glm::lookAt(glm::vec3( 0.0f, 1.0f, -3.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projectionMatrix = glm::perspective( fov , ( ( float ) HEIGHT ) / WIDTH , 1.f , 10.0f ) ;
glm::mat4 modelTransform = glm::translate( glm::mat4( 1.f ) , glm::vec3( .0f , -3.0f , -3.0f ) ) ;
glm::mat4 rotation = glm::rotate( glm::mat4(1.f) , rotationDegrees , glm::vec3( 1.f , 1.f , 0.f ) ) ;
//glm::mat4 rotation = glm::rotate( rotation1 , 30.f , glm::vec3( 0.f , 2.f , 0.f ) ) ;
glm::mat4 fullTransform = projectionMatrix * modelTransform * rotation ;
GLuint transformLocation = glGetUniformLocation( program , "uModelTranslate" ) ;
GLuint projectionLocation = glGetUniformLocation( program , "uProjectionMatrix" ) ;
//modelTransform = modelTransform * rotation ;
glUniformMatrix4fv( transformLocation , 1 , GL_FALSE , &modelTransform[0][0] ) ;
glUniformMatrix4fv( projectionLocation , 1 , GL_FALSE , &fullTransform[0][0] ) ;
bool canUp , canDown , canL , canR , canW , canS ,canA , canD , canQ , canE ;
canQ = true ;
canE = true ;
canD= true ;
canA = true ;
canUp = true ;
canS = true ;
canDown = true ;
canR = true ;
canL = true ;
canW = true ;
float nearF = 0.1f ;
float zZ = -3.0 ;
float yY = 1.0f ;
float xX = 0.f ;
while ( !glfwWindowShouldClose( window ) )
{
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents( );
rotationDegrees += .0001f ;
if( rotationDegrees >= 360 )
{
rotationDegrees =0 ;
}
view = glm::lookAt(glm::vec3( yY , xX, zZ),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 rotation = glm::rotate( glm::mat4(1.f) , rotationDegrees , glm::vec3( 1.f , 1.f , 0.f ) ) ;
glm::mat4 projectionMatrix = glm::perspective(glm::radians(fov), (float) WIDTH / (float)HEIGHT , nearF, 10.0f);
glm::mat4 fullTransform = projectionMatrix * view * rotation ;
glUniformMatrix4fv( projectionLocation , 1 , GL_FALSE , &fullTransform[0][0] ) ;
// Render
// Clear the colorbuffer
glClearColor( 0.f, 0.f, 0.f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
if (glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS )
{
glfwSetWindowShouldClose(window,true);
}
if (glfwGetKey(window,GLFW_KEY_UP) == GLFW_PRESS && canUp )
{
canUp = false ;
fov += 1.f ;
std::cout << fov << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_UP) != GLFW_PRESS && !canUp )
{
canUp = true ;
}
if (glfwGetKey(window,GLFW_KEY_DOWN) == GLFW_PRESS && canDown)
{
canDown = false ;
fov += -1.f ;
std::cout << fov << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_DOWN) != GLFW_PRESS && !canDown)
{
canDown = true ;
}
if (glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS )
{
glfwSetWindowShouldClose(window,true);
}
if (glfwGetKey(window,GLFW_KEY_LEFT) == GLFW_PRESS && canL )
{
canL = false ;
nearF += 1.f ;
std::cout << nearF << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_LEFT) != GLFW_PRESS && !canL )
{
canL = true ;
}
if (glfwGetKey(window,GLFW_KEY_RIGHT) == GLFW_PRESS && canR)
{
canR = false ;
nearF += -1.f ;
std::cout << nearF << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_RIGHT) != GLFW_PRESS && !canR)
{
canR = true ;
}
if (glfwGetKey(window,GLFW_KEY_W) == GLFW_PRESS && canW)
{
canW = false ;
zZ += -1.f ;
std::cout << zZ << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_W) != GLFW_PRESS && !canW)
{
canW = true ;
}
if (glfwGetKey(window,GLFW_KEY_S) == GLFW_PRESS && canS)
{
canS = false ;
zZ += +1.f ;
std::cout << zZ << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_S) != GLFW_PRESS && !canS)
{
canS = true ;
}
if (glfwGetKey(window,GLFW_KEY_A) == GLFW_PRESS && canA)
{
canA = false ;
xX += +1.f ;
std::cout << xX << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_A) != GLFW_PRESS && !canA)
{
canA = true ;
}
if (glfwGetKey(window,GLFW_KEY_D) == GLFW_PRESS && canD)
{
canD = false ;
xX += -1.f ;
std::cout << xX << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_D) != GLFW_PRESS && !canD)
{
canD = true ;
}
if (glfwGetKey(window,GLFW_KEY_Q) == GLFW_PRESS && canQ)
{
canQ = false ;
yY += -1.f ;
std::cout << yY << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_Q) != GLFW_PRESS && !canQ)
{
canQ = true ;
}
if (glfwGetKey(window,GLFW_KEY_E) == GLFW_PRESS && canE)
{
canE = false ;
yY += 1.f ;
std::cout << yY << std::endl ;
}
if (glfwGetKey(window,GLFW_KEY_E) != GLFW_PRESS && !canE)
{
canE = true ;
}
//glUseProgram( program ) ;
glDrawElements( GL_TRIANGLES , numOfIndices , GL_UNSIGNED_INT , 0 ) ;
// Swap the screen buffers
glfwSwapBuffers( window );
}
glfwTerminate( );
return EXIT_SUCCESS;
}
The unit of the angle for glm::perspective and glm::rotate is radians. A field of view of 1° is far to small.
The translation component of the modelTransform matrix moves the object out of the viewing frustum and has to be reduced.
Furthermore I recommend to enable the Depth Test.
e.g.:
float rotationDegrees = 0.0f;
float fov = 90.0f;
float nearF = 0.1f;
float zZ = -3.0;
float yY = 1.0f;
float xX = 0.0f;
glEnable(GL_DEPTH_TEST);
while (!glfwWindowShouldClose(wnd))
{
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(rotationDegrees), glm::vec3(1.0f , 1.0f , 0.0f)) ;
glm::mat4 modelTransform = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.5f, 0.0f)) ;
glm::mat4 view = glm::lookAt(glm::vec3(yY , xX, zZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 modelview = view * modelTransform * rotation;
glm::mat4 projectionMatrix = glm::perspective(glm::radians(fov), (float)WIDTH / (float)HEIGHT, nearF, 10.0f);
rotationDegrees += 1.0f;
glUniformMatrix4fv(transformLocation, 1, GL_FALSE, glm::value_ptr(modelview));
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
// [...]
}
Vertex shader:
#version 330 core
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inColor;
out vec3 vertCol;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelTranslate;
void main()
{
vertCol = inColor;
gl_Position = uProjectionMatrix * uModelTranslate * vec4(inPos.xyz, 1.0);
}
My program receives PCL pointcloud and plot each point one by one using:
glBegin(GL_POINTS);
glVertex3f(point.x, point.y, point].z);
glEnd();
It works but due to the large number of points the program is pretty slow. Is there a more efficient way to do this?
Jam all the points into a big VBO when the point-cloud changes & draw 'em all in one go using a single glDrawArrays() call. That way OpenGL can shift all the vertex data to GPU once instead of you spoon-feeding the driver geometry one glVertex() at a time every frame.
Heck, even vertex arrays will buy you a huge speed-up by avoiding hundreds of thousands of function-calls into the GL driver.
EDIT: Comparison:
10 million random points, using vertex buffer objects:
Vertex arrays:
Display lists:
And using immediate-mode:
Code (hit 'n' to cycle between drawing methods):
// http://glew.sourceforge.net/
#include <GL/glew.h>
// http://freeglut.sourceforge.net/
#include <GL/freeglut.h>
// http://glm.g-truc.net/
#include <glm/glm.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>
#include <sstream>
#include <chrono>
#include <cstddef>
struct Vertex
{
glm::vec4 pos;
glm::vec4 color;
};
std::vector< Vertex > verts;
GLuint vbo = 0;
GLuint dlist = 0;
void init()
{
// init geometry
for( size_t i = 0; i < 10000000; i++ )
{
Vertex vert;
vert.pos = glm::vec4( glm::linearRand( glm::vec3( -1.0f, -1.0f, -1.0f ), glm::vec3( 1.0f, 1.0f, 1.0f ) ), 1.0f );
vert.color = glm::vec4( glm::linearRand( glm::vec3( 0.00f, 0.0f, 0.0f ), glm::vec3( 1.0f, 1.0f, 1.0f ) ), 1.0f );
verts.push_back( vert );
}
// create display list
dlist = glGenLists( 1 );
glNewList( dlist, GL_COMPILE );
glBegin( GL_POINTS );
for( size_t i = 0; i < verts.size(); ++i )
{
glColor4fv( glm::value_ptr( verts[i].color) );
glVertex4fv( glm::value_ptr( verts[i].pos) );
}
glEnd();
glEndList();
// create VBO
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( Vertex ) * verts.size(), verts.data(), GL_STATIC_DRAW );
}
unsigned int method = 0;
void keyboard( unsigned char key, int x, int y )
{
if( 'n' == key )
{
method++;
if( method > 3 ) method = 0;
}
}
void display()
{
// timekeeping
static std::chrono::steady_clock::time_point prv = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point cur = std::chrono::steady_clock::now();
const float dt = std::chrono::duration< float >( cur - prv ).count();
prv = cur;
glClearColor( 0, 0, 0, 1 );
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 );
gluPerspective( 60.0, w / h, 0.1, 10.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( 2, 2, 2, 0, 0, 0, 0, 0, 1 );
static float angle = 0.0f;
angle += dt * 6.0f;
glRotatef( angle, 0, 0, 1 );
// render
switch( method )
{
case 0:
// VBO
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 4, GL_FLOAT, sizeof( Vertex ), (void*)offsetof( Vertex, pos ) );
glColorPointer( 4, GL_FLOAT, sizeof( Vertex ), (void*)offsetof( Vertex, color ) );
glDrawArrays( GL_POINTS, 0, verts.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
break;
case 1:
// vertex array
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 4, GL_FLOAT, sizeof( Vertex ), &verts[0].pos );
glColorPointer( 4, GL_FLOAT, sizeof( Vertex ), &verts[0].color );
glDrawArrays( GL_POINTS, 0, verts.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
break;
case 2:
// display list
glCallList( dlist );
break;
case 3:
// immediate mode
glBegin( GL_POINTS );
for( size_t i = 0; i < verts.size(); ++i )
{
glColor4fv( glm::value_ptr( verts[i].color) );
glVertex4fv( glm::value_ptr( verts[i].pos) );
}
glEnd();
break;
}
// info/frame time output
std::stringstream msg;
msg << "Using ";
switch( method )
{
case 0: msg << "vertex buffer object"; break;
case 1: msg << "vertex array"; break;
case 2: msg << "display list"; break;
case 3: msg << "immediate mode"; break;
}
msg << std::endl;
msg << "Frame time: " << (dt * 1000.0f) << " ms";
glColor3ub( 255, 255, 0 );
glWindowPos2i( 10, 25 );
glutBitmapString( GLUT_BITMAP_9_BY_15, (unsigned const char*)( msg.str().c_str() ) );
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutIdleFunc( display );
glutMainLoop();
return 0;
}
Yes definitely, the code you are showing is from a quite old version of OpenGL.
In more recent versions you can pack your data together and send it to the GPU in one call. The code becomes a little bit more complex but it is worth it.
I suggest you to look at this website : https://learnopengl.com/
It gathers everything you need to start using modern opengl.
Hope it helped.
I have problem. I wrote the code on clear opengl and c++ without any libraries(glut, glew...) but it doesnt work.
Function displayCB display polygon with
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex2f(-0.5f, -0.5f);
glVertex2f( 0.5f, -0.5f);
glVertex2f( 0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
and dont display two polygone with
glColor3f(1.0f, 0.0f, 0.0f);
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glBegin(GL_QUADS); // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();
Can you help me?
COMPILE WITH: g++ -g -o opengl1 opengl1.cxx -lGLU -lGL -lX11
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/time.h>
#define GL_GLEXT_PROTOTYPES
#define GLX_GLXEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
struct MyWin
{
Display *display;
Window win;
bool displayed;
int width;
int height;
};
const int WIN_XPOS = 256;
const int WIN_YPOS = 64;
const int WIN_XRES = 600;
const int WIN_YRES = 600;
const int NUM_SAMPLES = 4;
MyWin Win;
double elapsedMsec( const struct timeval &start, const struct timeval &stop )
{
return ( ( stop.tv_sec - start.tv_sec ) * 1000.0 +
( stop.tv_usec - start.tv_usec ) / 1000.0 );
}
double elapsedUsec( const struct timeval &start, const struct timeval &stop )
{
return ( ( stop.tv_sec - start.tv_sec ) * 1000000.0 +
( stop.tv_usec - start.tv_usec ) );
}
/// check() - Check for GL errors, and report any queued
void check( const char hdr[] = "" )
{
int err;
while ( ( err = glGetError() ) != GL_NO_ERROR )
fprintf( stderr, "OpenGL Error at %s: %s\n", hdr, gluErrorString(err) );
}
void displayCB()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//---------------------------------------------------
// FIXME: Insert GL draw code here
//---------------------------------------------------
glColor3f(1.0f, 0.0f, 0.0f);
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glBegin(GL_QUADS); // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();
// glBegin(GL_POLYGON);
// glVertex2f(-0.5f, -0.5f);
// glVertex2f( 0.5f, -0.5f);
// glVertex2f( 0.5f, 0.5f);
// glVertex2f(-0.5f, 0.5f);
// glEnd();
// Display it
glXSwapBuffers( Win.display, Win.win );
check( "displayCB()" );
}
//----------------------------------------------------------------------------
void keyboardCB( KeySym sym, unsigned char key, int x, int y,
bool &setting_change )
{
switch ( tolower( key ) )
{
case 27:
// ESCape - We're done!
exit (0);
break;
case 'k':
printf( "You hit the 'k' key\n" );
break;
case 0:
switch ( sym )
{
case XK_Left :
printf( "You hit the Left Arrow key\n" );
break;
case XK_Right :
printf( "You hit the Right Arrow key\n" );
break;
}
break;
}
}
//----------------------------------------------------------------------------
void reshapeCB( int width, int height )
{
Win.width = width;
Win.height = height;
}
//----------------------------------------------------------------------------
XVisualInfo *chooseVisual( Display *display )
{
int attribs [ 100 ] ;
int n = 0 ;
// Request 24-bit color with alpha
attribs [n++] = GLX_RGBA ;
attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 8 ;
attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 8 ;
attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 8 ;
// Request 24-bit depth buffer
attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 24 ;
// Request 4 multisamples per pixel
attribs [n++] = GLX_SAMPLE_BUFFERS ; attribs [n++] = 1 ;
attribs [n++] = GLX_SAMPLES ; attribs [n++] = NUM_SAMPLES ;
// Request double-buffering
attribs [n++] = GLX_DOUBLEBUFFER ;
attribs [n++] = None ;
return glXChooseVisual( display, DefaultScreen( display ), attribs );
}
//----------------------------------------------------------------------------
void createWindow()
{
// Init X and GLX
Win.displayed = false;
Display *display = Win.display = XOpenDisplay( ":0.0" );
if ( !display )
printf( "Cannot open X display\n" );
int screen = DefaultScreen( display );
Window root_win = RootWindow( display, screen );
if ( !glXQueryExtension( display, 0, 0 ) )
printf( "X Server doesn't support GLX extension\n" );
// Pick a visual
XVisualInfo *visinfo = chooseVisual( display );
if ( visinfo == 0 )
printf( "glXChooseVisual failed\n" );
// Describe the visual
printf( "Window Visual 0x%.2x\n", unsigned( visinfo->visualid ) );
// Create the X window
XSetWindowAttributes winAttr ;
winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
winAttr.background_pixmap = None ;
winAttr.background_pixel = 0 ;
winAttr.border_pixel = 0 ;
winAttr.colormap = XCreateColormap( display, root_win,
visinfo->visual, AllocNone );
unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
Window win = Win.win = XCreateWindow ( display, root_win,
WIN_XPOS, WIN_YPOS,
WIN_XRES, WIN_YRES, 0,
visinfo->depth, InputOutput,
visinfo->visual, mask, &winAttr ) ;
XStoreName( Win.display, win, "My GLX Window");
// Create an OpenGL context and attach it to our X window
GLXContext context = glXCreateContext( display, visinfo, NULL, 1 ) ;
if ( ! glXMakeCurrent( display, win, context ) )
printf( "glXMakeCurrent failed.\n" );
if ( ! glXIsDirect ( display, glXGetCurrentContext() ) )
printf( "Indirect GLX rendering context obtained\n" );
// Display the window
XMapWindow( display, win );
if ( ! glXMakeCurrent( display, win, context ) )
printf( "glXMakeCurrent failed.\n" );
check( "createWindow()" );
printf( "Window Size = %d x %d\n", WIN_XRES, WIN_YRES );
printf( "Window Samples = %d\n", NUM_SAMPLES );
}
//----------------------------------------------------------------------------
void processXEvents( Atom wm_protocols, Atom wm_delete_window )
{
bool setting_change = false;
while ( XEventsQueued( Win.display, QueuedAfterFlush ) )
{
XEvent event;
XNextEvent( Win.display, &event );
if( event.xany.window != Win.win )
continue;
switch ( event.type )
{
case MapNotify:
{
Win.displayed = true;
break;
}
case ConfigureNotify:
{
XConfigureEvent &cevent = event.xconfigure;
reshapeCB( cevent.width, cevent.height );
break;
}
case KeyPress:
{
char chr;
KeySym symbol;
XComposeStatus status;
XLookupString( &event.xkey, &chr, 1, &symbol, &status );
keyboardCB( symbol, chr, event.xkey.x, event.xkey.y,
setting_change );
break;
}
case ClientMessage:
{
if ( event.xclient.message_type == wm_protocols &&
Atom( event.xclient.data.l[0] ) == wm_delete_window )
{
//printf( "Received WM_DELETE_WINDOW\n" );
exit(0);
}
break;
}
}
}
}
//----------------------------------------------------------------------------
void mainLoop()
{
// Register to receive window close events (the "X" window manager button)
Atom wm_protocols = XInternAtom( Win.display, "WM_PROTOCOLS" , False);
Atom wm_delete_window = XInternAtom( Win.display, "WM_DELETE_WINDOW", False);
XSetWMProtocols( Win.display, Win.win, &wm_delete_window, True );
while (1)
{
// Redraw window (after it's mapped)
if ( Win.displayed )
displayCB();
// Update frame rate
static timeval last_xcheck = {0,0};
struct timeval now;
gettimeofday( &now, 0 );
// Check X events every 1/10 second
if ( elapsedMsec( last_xcheck, now ) > 100 )
{
processXEvents( wm_protocols, wm_delete_window );
last_xcheck = now;
}
}
}
//----------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
// Init globals
Win.width = WIN_XRES, Win.height = WIN_YRES;
// Create context and window
createWindow();
// Init OpenGL
glViewport ( 0, 0, Win.width, Win.height );
glColorMask ( 1,1,1,1 );
glClearColor( 0,0,1,1 );
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Go
printf( "Valid keys: Left, Right, k, ESC\n" );
printf( "Press ESC to quit\n" );
mainLoop();
return 0;
}
There are three problems here.
First: you haven't set up a GL viewport (e.g, using glFrustum() or gluPerspective()), so the perspective matrix isn't set up appropriately to do 3D graphics. As such, trying to draw a model in 3D won't work properly.
Second: The code that you've got here is written against the X11 windowing system, not Mac OS X. While it'll compile and sort-of-run on Mac OS, it will not run natively, nor will it perform particularly well. You will really want to use some interface which allows you to interface with the native Mac OS X GL implementation, such as SDL, GLUT/GLEW, or AGL.
(Keep in mind that there is no such thing as using GL "without libraries". OpenGL is itself a library, as is libX11; there's nothing at all wrong with using extra utility libraries to cut out some of the OS-specific setup and make your application easier to port.)
Third: You are currently learning how to use OpenGL immediate mode, which was used prior to OpenGL 3.0. Modern OpenGL — that is, OpenGL 3.0 or later, as well as OpenGL ES — uses a significantly different API which has very little in common with immediate mode. I'd strongly recommend that you skip immediate mode entirely; it's a dead technology at this point. There are a number of good tutorials out there for OpenGL 3+, including:
http://www.opengl-tutorial.org/
http://www.arcsynthesis.org/gltut/
https://open.gl/
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;
}
I am trying to draw the shape shown below (in black) in OpenGL (for desktops, not mobile). I'd prefer it in 3D, but 2D would suffice as well. I will be mapping a texture to it as well. I've used triangle fans/strips for other things in the past and I imagine that's what I'd need to use here but I'm just not sure where to start on it. I've drawn the WHITE part before, but never the inverse (the black part). Any thoughts or guidance on what to use (triangle fan, triangle strip, some other odd OpenGL shape I probably didn't know existed, etc...)
Final Solution:
void draw_arch(GLfloat width, GLfloat height, GLint slices)
{
glPushMatrix();
GLfloat offset = 0.5f;
glScalef(width/2,height/(1+offset),1.0f);
glBegin(GL_QUADS);
for( unsigned int i = 0; i < slices; ++i ) {
float curAngle = ( ( i + 0 ) / (float)slices ) * 3.14159;
float nxtAngle = ( ( i + 1 ) / (float)slices ) * 3.14159;
glVertex2f( cos( curAngle ), sin( curAngle ) );
glVertex2f( cos( curAngle ), 1.0f + offset );
glVertex2f( cos( nxtAngle ), 1.0f + offset );
glVertex2f( cos( nxtAngle ), sin( nxtAngle ) );
}
glEnd();
glPopMatrix();
}
I can adjust the "offset" variable to make different looking arches, however in this application, I choose 0.5 to make it look the way I wanted it to!
Generate the top half of a circle and an offset above it and link the two with quads/triangles:
#include <GL/glut.h>
#include <cmath>
void glShape( const float height, unsigned int segs )
{
glBegin( GL_QUADS );
for( unsigned int i = 0; i < segs; ++i )
{
float curAngle = ( ( i + 0 ) / (float)segs ) * 3.14159;
float nxtAngle = ( ( i + 1 ) / (float)segs ) * 3.14159;
glVertex2f( cos( curAngle ), sin( curAngle ) );
glVertex2f( cos( curAngle ), 1 + height );
glVertex2f( cos( nxtAngle ), 1 + height );
glVertex2f( cos( nxtAngle ), sin( nxtAngle ) );
}
glEnd();
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glOrtho( -2 * ar, 2 * ar, -2, 2, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3ub( 255, 0, 0 );
glShape( 0.1f, 20 );
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
Probably not the minimal number of quads/triangles but it's quick and easy :)