Panning in a MFC Control using OpenGL - visual-c++

I'm very new to OpenGL so this might be a very silly question.
What I'm using: Visual Studio 2010, MFC framework, Windows 7.
What I'm trying to do: A MFC control based on OpenGL that can show some files preview with zooming, panning and rotation.
What I've already done:
Derived a class from CButton to handle all events and having a easy access to CClientDC;
Following a less or more recent tutorial I've encapsulated the creation of the OpenGL Device in a class.I don't know if it's good or if I've understood what I've done, but it works.
Let me show you some code:
int COpenGLCtrl::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
if( CButton::OnCreate( lpCreateStruct ) == -1 )
return -1;
m_pDC = new CClientDC( this );
// This is my encapsulated device.
m_GLDevice.Create( m_pDC->m_hDC );
InitGL();
return 0;
}
void COpenGLCtrl::InitGL( void )
{
glShadeModel( GL_SMOOTH );
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
}
// Drawing inside button.
void COpenGLCtrl::OnPaint( void )
{
m_GLDevice.MakeCurrent();
DrawGLScene();
}
// This function is called before DrawGLScene the first time the control is being redrawed.
void COpenGLCtrl::ZoomOut( int nVal )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0f, nVal * 1.0f, 0.0f, nVal * 1.0f, nVal * 1.0f, 0.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
void COpenGLCtrl::DrawGLScene( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
glRotatef( m_fRotation_X, 1.0f, .0f, 0.0f );
glRotatef( m_fRotation_Y, 0.0f, 1.0f, 0.0f );
glTranslatef( m_fTraslation_X, m_fTraslation_Y, 0.0f );
glScalef( 1.0f, 1.0f, 0.0f );
glBegin( GL_TRIANGLES );
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3f( 0.0f, 0.0f, 0.0f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex3f( 0.5f, 1.0f, 0.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex3f( 1.0f, 0.0f, 0.0f );
glEnd();
SwapBuffers( m_pDC->m_hDC );
}
All this code is sufficient to draw a small triangle in my control with low-left vertex centered in OpenGL axis origin. All good, I showed you all this stuff to see if there are some error somewhere.
Now I want to pan around my triangle: from what I've understood, I've to modify the value of m_fTranslation_X and m_fTranslation_Y. I've decided to pan the view when the user holds down the mouse left button and moves it around:
void COpenGLCtrl::OnMouseMove( UINT nFlags, CPoint point )
{
int nRes;
CString strOut;
GLfloat winX, winY, winZ;
GLint viewport[4];
GLdouble vPos[3], modelview[16], projection[16];
// Converting CPoint MFC coordinates to OpenGL viewport coordinates.
m_p2dPosMouse = point;
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
winX = (GLfloat)point.x;
winY = (GLfloat)viewport[3] - (GLfloat)point.y;
glReadPixels( point.x, int( winY ), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
nRes = gluUnProject( winX, winY, winZ, modelview, projection, viewport, &vPos[0], &vPos[1], &vPos[2] );
m_vPosMouse[0] = (GLfloat)vPos[0];
m_vPosMouse[1] = (GLfloat)vPos[1];
m_vPosMouse[2] = (GLfloat)vPos[2];
if( nFlags == MK_LBUTTON )
{
if( !m_bTrasla )
{
ATLTRACE2( _T("\nInizio traslazione\n\n") );
memcpy( m_vPosMouse_ult, m_vPosMouse, 3 * sizeof( GLfloat ) );
m_p2dUltPos = point;
m_bTrasla = true;
}
/*OPENGL-WAY
m_fTraslation_X += m_vPosMouse[0] - m_vPosMouse_ult[0];
m_fTraslation_Y += m_vPosMouse[1] - m_vPosMouse_ult[1];
*/
/*MFC-WAY*/
m_fTraslation_X += ( point.x - m_p2dUltPos.x ) / 5000.0f;
m_fTraslation_Y += ( m_p2dUltPos.y - point.y ) / 5000.0f;
CString strBuf;
strBuf.Format( _T("%f - %f || CPoint.x: %ld CPoint.y: %ld\n"), m_fTraslation_X, m_fTraslation_Y, point.x, point.y );
ATLTRACE2( strBuf );
///////////////////////
// EDIT: Added in edit to solve MFC-WAY
m_p2dUltPos = point;
///////////////////////
memcpy( m_vPosMouse_ult, m_vPosMouse, 3 * sizeof( GLfloat ) );
}
if( m_CB_PosAgg.Valid() )
m_CB_PosAgg.Execute();
Invalidate();
}
In short words: I keep track of mouse last position and calculate how much I've moved on X and on Y. These differences are my traslations.
Finally my problems:
If I use OpenGL coordinate (commented and labelled OPENGL-WAY) the pan is smooth and precise but shakes. This is because even if my CPoint coordinates increase (or decrease) and so the difference, the OpenGL don't. Here's some values:
m_fTraslate_X m_fTraslate_Y CPoint.x CPoint.y
0.000000 0.000000 274 328
0.014377 0.141573 283 265
0.020767 0.152809 287 260
0.001597 0.002247 288 259
0.007987 0.020225 292 251
0.025559 0.164045 295 246
0.027157 0.170786 296 243
As you can see, while mouse control position increases (in MFC Y axis is inverted), at step 3 the values for X-axis are suddenly decreased from 0.02 to 0.002 and then back to 0.02! Why this?
EDIT: solved in my answer. If I use MFC coordinate, labelled MFC-WAY, I've got no shakes but a strong inertia. Sometimes happen that if I start moving my mouse to the right (assuming no up-down) then change the direction back to left, my view continues to move to the right. Where is the error?
Thanks in advance, hope you won't ban me for this noobish essay.

Problem 1)
The first problem was that when the view gets invalidated and then redrawed, the traslation has still to be performed! Solution:
if( nFlags == MK_RBUTTON && m_bTrasla )
{
// Converting MFC coordinates to OpenGL System.
ConversioneCoordinateMFC_A_OPENGL( m_vPosMouse_ult, m_p2dUltPos );
m_fTraslation_X += m_vPosMouse[0] - m_vPosMouse_ult[0];
m_fTraslation_Y += m_vPosMouse[1] - m_vPosMouse_ult[1];
Problem 2)
MFC-STYLE panning is not updating the last position of mouse pointer. Adding this line:
m_p2dUltPos = point; solved the problem.

Related

Relating vertex buffers and vertex attributes in openGL

My entire code that is supposed to draw a triangle on the screen is:
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string.h>
const GLint WIDTH=800, HEIGHT=600;
GLuint VAO, VBO, shader;
//Vertex Shader
/*static const char**/
const GLchar* vShader = "\n"
"\n"
"#version 330 \n"
"layout (location=0) in vec3 pos;\n"
"void main(){\n"
"gl_Position = vec4(pos.x,pos.y,pos.z,1.0);\n"
"\n"
"}\n"
"";
// fragment shader
const GLchar* fShader = "\n"
"#version 330 \n"
"out vec4 colour;\n"
"void main(){\n"
"colour = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"
"\n"
"\n";
void CreateTriangle(){
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
// vertex arrays
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// vertex buffers
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*9,vertices,GL_STATIC_DRAW);
glVertexAttribPointer(0,3, GL_FLOAT,GL_FALSE,0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void AddShader(GLuint theProgram, const GLchar* shaderCode, GLenum shaderType){
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result=0;
GLchar eLog[1024]={};
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if(!result){
glGetShaderInfoLog(theShader,sizeof(eLog),NULL, eLog);
std::cout<< "Error compiling"<<shaderType<<" "<<eLog <<std::endl;
return;
}
glAttachShader(theProgram,theShader);
}
void CompileShader(){
shader = glCreateProgram();
if(!shader){
std::cout<<"Error Creating Shader Program";
return;
}
AddShader(shader, vShader,GL_VERTEX_SHADER);
AddShader(shader, fShader,GL_FRAGMENT_SHADER);
// getting error codes
GLint result=0;
GLchar eLog[1024]={0};
// Creates the executables in the graphic card
glLinkProgram(shader);
// get information if program is linked properly
glGetProgramiv(shader, GL_LINK_STATUS, &result);
if(!result){
glGetProgramInfoLog(shader,sizeof(eLog),NULL,eLog);
std::cout<<"Error linking program"<<eLog<<std::endl;
return;
}
glValidateProgram(shader);
glGetProgramiv(shader,GL_VALIDATE_STATUS,&result);
if(!result){
glGetProgramInfoLog(shader, sizeof(eLog),NULL, eLog);
std::cout<<"Error validating program"<<eLog<<std::endl;
return;
}
}
int main(void){
if(!glfwInit()){
std::cout << "glfw initialization failed" << std::endl;
glfwTerminate();
return 1;
}
// 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);
GLFWwindow *mainWindow = glfwCreateWindow(WIDTH, HEIGHT, "NEW WINDOW", NULL, NULL);
if(!mainWindow){
std::cout<< "Window creation failed" <<std::endl;
glfwTerminate();
return 1;
}
int bufferWidth, bufferHeight;
glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
glfwMakeContextCurrent(mainWindow);
if(glewInit() != GLEW_OK){
std::cout << "GLEW Initialization failed" << std::endl;
glfwDestroyWindow(mainWindow);
glfwTerminate();
return 1;
}
glViewport(0,0,bufferWidth, bufferHeight);
CreateTriangle();
CompileShader();
while(!glfwWindowShouldClose(mainWindow)){
glfwPollEvents();
glUseProgram(shader);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
glBindVertexArray(0);
glUseProgram(0);
glfwSwapBuffers(mainWindow);
std::cout<<"something"<<std::endl;
}
return 0;
}
It essentially draws a black screen and there's no error whatsoever but is supposed to draw a red triangle so I'm trying to debug this code and there is essentially some parts in the code that I don't understand.
1) How does the VBO (Vertex Buffer Object) relate to the VAO (Vertex Attribute object), we basically defined these using the following inside of the CreateTriangles() function:
...
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// vertex buffers
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*9,vertices,GL_STATIC_DRAW);
glVertexAttribPointer(0,3, GL_FLOAT,GL_FALSE,0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
...
Note that we already unbind both the VAO and VBO, but during the drawing call inside the while loop:
while(!glfwWindowShouldClose(mainWindow)){
glfwPollEvents();
glUseProgram(shader);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
glBindVertexArray(0);
glUseProgram(0);
glfwSwapBuffers(mainWindow);
std::cout<<"something"<<std::endl;
}
we only rebind the VAO and not the VBO, which I think may be the result of the error, but I don't know for sure.
Also, the tutorial says that the VBO is bound inside the VAO but I don't see there being any linking or anything that related VBO to the VAO in the code, so I'm really being confused on how is it that we're binding them together and why we're only binding back the VAO and not the VBO during the drawing stage?
I'm using Linux OS and used the following to compile:
g++ -std=c++17 main.cpp -o main -lGL -lGLEW -lglfw && ./main
From comments above, credit to #Rabbid76:
When glVertexAttribPointer is called than the a name reference of the current VBO is stored in the current VAO. The current VAO is bound by glBindVertexArray(VAO); and the current VBO is bound by glBindBuffer(GL_ARRAY_BUFFER,VBO);. glVertexAttribPointer associates VBO to the resource index 0 in VAO. This association is stored in the state vector of VAO. So it is sufficient to bind VAO(glBindVertexArray(VAO)) before the draw call. Hence, only binding the VAO is sufficient.
As for the problem stated in the comments regarding the black screen try
Updating the glew version and your graphic card drive. If updating glew is not possible, then just set the glExperimental=GL_TRUE.

creat colored cube consisting triangles in android studio

I only managed to fix a triangle. This is the code but do not know what to do to get it as a cube.
I tried to fix the code but did not get the cube, so this code is before I destroyed it. Will try to get it to rotate too.
public class Triangle {
static final int VERTEX_POS_SIZE = 4;
static final int COLOR_SIZE = 4;
static final int VERTEX_POS_INDEX = 0;
static final int COLOR_INDEX = 1;
static final int VERTEX_POS_OFFSET = 0;
static final int COLOR_OFFSET = 0;
static final int VERTEX_ATTRIB_SIZE = VERTEX_POS_SIZE;
static final int COLOR_ATTRIB_SIZE = COLOR_SIZE;
private final int VERTEX_COUNT = triangleData.length / VERTEX_ATTRIB_SIZE;
private FloatBuffer vertexDataBuffer;
private FloatBuffer colorDataBuffer;
static float triangleData[] = { // in counterclockwise order:
0.0f, 0.0f, 0.0f, 1.0f, // top
1.0f, 0.0f, 0.0f, 1.0f, // bottom left
1.0f, 0.0f, -1.0f, 1.0f, // bottom right
0.0f, 0.0f, -1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f,
0.0f, 1.0f, -1.0f, 1.0f,
};
static float colorData[] = { // in counterclockwise order:
1.0f, 0.0f, 0.0f, 1.0f, // Red
0.0f, 1.0f, 0.0f, 1.0f, // Green
0.0f, 0.0f, 1.0f, 1.0f// Blue
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
private final int mProgram;
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"attribute vec4 vPosition; \n" +
"attribute vec4 vColor; \n" +
"uniform mat4 uMVPMatrix;\n" +
"varying vec4 c; \n" +
"void main() { \n" +
" c = vColor; \n" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;\n" +
"}";
private final String fragmentShaderCode =
"precision mediump float;\n" +
"varying vec4 c;\n" +
"void main() {\n" +
" gl_FragColor = c;\n" +
"}";
// Use to access and set the view transformation
private int mMVPMatrixHandle;
private int positionHandle;
private int colorHandle;
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bbv = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleData.length * 4);
// use the device hardware's native byte order
bbv.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexDataBuffer = bbv.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexDataBuffer.put(triangleData);
// set the buffer to read the first coordinate
vertexDataBuffer.position(0);
// initialize vertex byte buffer for shape coordinates
ByteBuffer bbc = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
colorData.length * 4);
// use the device hardware's native byte order
bbc.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
colorDataBuffer = bbc.asFloatBuffer();
// add the coordinates to the FloatBuffer
colorDataBuffer.put(colorData);
// set the buffer to read the first coordinate
colorDataBuffer.position(0);
int vertexShader = CGRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = CGRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(positionHandle, VERTEX_POS_SIZE,
GLES20.GL_FLOAT, false,
VERTEX_ATTRIB_SIZE * 4, vertexDataBuffer);
colorHandle = GLES20.glGetAttribLocation(mProgram, "vColor");
GLES20.glEnableVertexAttribArray(colorHandle);
GLES20.glVertexAttribPointer(colorHandle, COLOR_SIZE,
GLES20.GL_FLOAT, false,
COLOR_ATTRIB_SIZE * 4, colorDataBuffer);
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_COUNT);
// Disable vertex array
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(colorHandle);
}
}

QGraphicsScene with a QGLWidget as the viewport not rendering QSvgRenderer antialiasing correctly

first I try to describe what I want:
I want a (qt 4.8 - based [can but must not]) Opengl-able context set in the background somewhere. Then the first layer has an Image with an transparent ROUND!! hole where you can see the OpenGl context. and on top of that static image there are buttons for some logic.
What I did:
I try to render a Svg with the QSvgRenderer in front of an opengl scenery.
The OpenGl Scenery is drawn in a QGraphicsView with an QGLWidget as Viewport.
int main(int argc, char **argv){
QApplication app(argc, argv);
GraphicsView view;
//trying to get the anitaliasing to work
view.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
QGLWidget* glwid = new QGLWidget( QGLFormat( QGL::SampleBuffers | QGL::AlphaChannel | QGL::Rgba ));
//Set Multisampling
QGLFormat frm = glwid->format();
glwid->format().setSamples(4);
glwid->setFormat(frm);
//set the GlViewport
view.setViewport(glwid); //--> SvgRendering works with no anti aliasing but glRendering does.
//view.setViewport(new QWidget); //--> SvgRendering with Antialiasing works
view.setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
view.setScene(new OpenGLScene(view.rect()));
view.show();
return app.exec();
}
The Scene Looks like this
#include "openglscene.h"
#include "PotentioMeter.h"
#include <QtGui>
#include <QtOpenGL>
#include <GL/glu.h>
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
OpenGLScene::OpenGLScene(const QRectF &rect)
: m_backgroundColor(0, 170, 255)
, m_distance(1.4f)
{
//One or more Widgets And buttons with svg special Looking (because of scaling)
PotentioMeter* pm = new PotentioMeter( );
pm->setAttribute(Qt::WA_TranslucentBackground, true);
pm->resize(500,500);
addWidget(pm);
QPushButton *backgroundButton = new QPushButton(tr("Choose background color"));
connect(backgroundButton, SIGNAL(clicked()), this, SLOT(setBackgroundColor()));
backgroundButton->move(900,20);
addWidget(backgroundButton);
//Where should be the gl things drawn
rGlViewport = QRectF(100, 100,rect.width()/2,rect.height()/2);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
const int UPDATE_RATE_25HZ_IN_MSEC = 40;
timer->start(UPDATE_RATE_25HZ_IN_MSEC);
}
//dummy gl drawing function
void OpenGLScene::pyramid(QColor* color)
{
glScalef(0.5,0.5,0.5);
glPushMatrix();
glRotatef(++angle, 0.0, 1.0, 0.0);
glBegin( GL_TRIANGLES );
glColor4f(color->redF(),color->greenF(),color->blueF(),1);
glColor3f( 1.0f, 0.0f, 0.0f ); glVertex3f( 0.0f, 1.f, 0.0f );
glColor3f( 0.0f, 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.0f );
glColor3f( 0.0f, 0.0f, 1.0f ); glVertex3f( 1.0f, -1.0f, 1.0f);
glColor4f(color->redF(),color->greenF(),color->blueF(),1);
glColor3f( 1.0f, 0.0f, 0.0f ); glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f( 0.0f, 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.0f);
glColor3f( 0.0f, 0.0f, 1.0f ); glVertex3f( 0.0f, -1.0f, -1.0f);
glColor4f(color->redF(),color->greenF(),color->blueF(),1);
glColor3f( 1.0f, 0.0f, 0.0f ); glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f( 0.0f, 1.0f, 0.0f ); glVertex3f( 0.0f, -1.0f, -1.0f);
glColor3f( 0.0f, 0.0f, 1.0f ); glVertex3f( 1.0f, -1.0f, 1.0f);
glColor4f(color->redF(),color->greenF(),color->blueF(),1);
glColor3f( 1.0f, 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.0f);
glColor3f( 0.0f, 1.0f, 0.0f ); glVertex3f( 0.0f, -1.0f, -1.0f);
glColor3f( 0.0f, 0.0f, 1.0f ); glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
glPopMatrix();
}
void
OpenGLScene::drawBackground(QPainter *painter, const QRectF & f)
{
//check painter
if (painter->paintEngine()->type() != QPaintEngine::OpenGL
&& painter->paintEngine()->type() != QPaintEngine::OpenGL2)
{
qWarning(
"OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
return;
}
//check viewport
if (f != myViewport)
{
myViewport = f;
}
//desperately trying to do antialiasing
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
glClearColor(m_backgroundColor.redF() + .2, m_backgroundColor.greenF() - .2, m_backgroundColor.blueF() + .2, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glFrustum(-1, 1, -1, 1, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_MULTISAMPLE);
glViewport(rGlViewport.x(), rGlViewport.y(), rGlViewport.width(),
rGlViewport.height());
//draw some gl stuff
pyramid(&m_backgroundColor);
glViewport(myViewport.x(), myViewport.y(), myViewport.width(),
myViewport.height());
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void
OpenGLScene::setBackgroundColor()
{
const QColor color = QColorDialog::getColor(m_backgroundColor);
if (color.isValid())
{
m_backgroundColor = color;
}
}
GL but no AA:
No GL but AA:
The Big Problem is now that when trying to render OpenGl and the Svg at the same time, either Opengl is not rendered - because of the missing context and the svg is rendered perfectly, or the opengl is rendered and the svg is not antialiased correctly.
So any ideas to get the antaliasing randering correctly?
The complete Project (ready for eclipse - made with cmake)
and Screenshots
and a prebuild executable
is in the link here:
https://www.dropbox.com/s/giqynqfuq2yl8li/SampleCode.zip

OpenScenegraph: Texture Mapping Quad

I am trying to do texture map a quad geometry object generated by createTexturedQuadGeometry with a texture that I load from an image. I then add this drawable to a node, add that node to root and render the hierarchy.
The code below is how I do it. The code compiles and runs but I only get a blank black screen instead of the specified image. Can someone please point out what is wrong?
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Texture2D> testTexture = new osg::Texture2D;
osg::ref_ptr<osg::Image> testImage = osgDB::readImageFile("testImage.png");
assert(testImage.valid());
int viewWidth = testImage->s();
int viewHeight = testImage->t();
testTexture->setImage(testImage);
osg::ref_ptr<osg::Geometry> pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f),
osg::Vec3(viewWidth,0.0f,0.0f),
osg::Vec3(0.0f,0.0f,viewHeight),
0.0f,
viewWidth,
viewHeight,
1.0f);
pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, testTexture.get());
pictureQuad->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
osg::ref_ptr<osg::Geode> textureHolder = new osg::Geode();
textureHolder->addDrawable(pictureQuad);
root->addChild(textureHolder);
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
viewer.run();
}
So, I happened to figure out the error.
createTexturedQuadGeometry expects normalised texture coordinates.
So,
osg::ref_ptr<osg::Geometry> pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f),
osg::Vec3(viewWidth,0.0f,0.0f),
osg::Vec3(0.0f,0.0f,viewHeight),
0.0f,
0.0f,
1.0f,
1.0f);
solves the problem.

OpenGL sample particle simulation doesnt show up particles

I have created a simple particle simulation for a fountain from this source. I also wanted to implement this using C++ classes. So, tried to put the above part of the logic into classes at this source (This is a very nice framework). I just have to inherit the class and redefine the functionalities that I would like.
I defined the functions for display() in which I call my DrawObjects().
I am running into the following issues:
I am initializing the number of particles to as low as 50 or 100 or 500. Nothing visible.
I am trying to load a texture(BMP) for my particles. It is failing for some reason. I tried both relative and absolute paths. Then tried to load a RAW texture(using IrfanViewer) with no luck. Also tried to remove the texture code to make them simple OpenGL primitives. Again no luck.
I wrote a simple DrawAxis() function which actually needs to draw cyan colored axis with red colored strings. However, gray colored primitives are showing up. I checked the code for usage of grayscale configuration, but no such thing.
Note: Working on Windows VC++ 2010. Code can be found at NippyZip.
Minimal Code
Main.cpp
#include "ParticleSimulation.h"
int main(int argc, char *argv[]) {
ParticleSimulation particleSimulation(50);
particleSimulation.InitParticles();
particleSimulation.setLookAt(80.0, 80.0, 80.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
particleSimulation.startFramework(argc, argv);
// **Note** No code below startFramework() will get executed
return 0;
}
GlutFramework.cpp
#include "GlutFramework.h"
namespace glutFramework {
// Set constants
const double GlutFramework::FRAME_TIME = 1.0 / GlutFramework::FPS * 1000.0; // Milliseconds
GlutFramework *GlutFramework::instance = NULL;
GlutFramework::GlutFramework() {
elapsedTimeInSeconds = 0;
frameTimeElapsed = 0;
title = "GLUT Framework: Paul Solt 2010";
eyeVector = Vector<float>(0.0, 0.0, -10.0); // move the eye position back
position = 0.0f;
direction = 1.0 / FRAME_TIME;
}
GlutFramework::~GlutFramework() {
}
void GlutFramework::startFramework(int argc, char *argv[]) {
setInstance(); // Sets the instance to self, used in the callback wrapper functions
// Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(WINDOW_X_POSITION, WINDOW_Y_POSITION);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow(title.c_str());
// Function callbacks with wrapper functions
glutReshapeFunc(reshapeWrapper);
glutMouseFunc(mouseButtonPressWrapper);
glutMotionFunc(mouseMoveWrapper);
glutDisplayFunc(displayWrapper);
glutKeyboardFunc(keyboardDownWrapper);
glutKeyboardUpFunc(keyboardUpWrapper);
glutSpecialFunc(specialKeyboardDownWrapper);
glutSpecialUpFunc(specialKeyboardUpWrapper);
init(); // Initialize
glutIdleFunc(runWrapper); // The program run loop
glutMainLoop(); // Start the main GLUT thread
}
void GlutFramework::load() {
// Subclass and override this method
}
void GlutFramework::display(float dTime) {
// Subclass and override this method
static int frame = 0;
std::cout << "GlutFramework Display: Frame: " << frame << ", dt(sec): " << dTime << ", Position: " << position << std::endl;
++frame;
// DEMO: Create a teapot and move it back and forth on the x-axis
glTranslatef(position, 0.0f, 0.0f);
glutSolidTeapot(2.5);
if(position > 4 && direction > 0) {
direction = -1.0 / FRAME_TIME;
} else if(position < -4 && direction < 0) {
direction = 1.0 / FRAME_TIME;
}
position += direction;
}
void GlutFramework::reshape(int width, int height) {
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble) width, 0.0, (GLdouble) height);
}
void GlutFramework::mouseButtonPress(int button, int state, int x, int y) {
printf("MouseButtonPress: x: %d y: %d\n", x, y);
}
void GlutFramework::mouseMove(int x, int y) {
printf("MouseMove: x: %d y: %d\n", x, y);
}
void GlutFramework::keyboardDown( unsigned char key, int x, int y )
{
// Subclass and override this method
printf( "KeyboardDown: %c = %d\n", key, (int)key );
if (key==27) { //27 =- ESC key
exit (0);
}
keyStates.keyDown( (int)key );
}
void GlutFramework::keyboardUp( unsigned char key, int x, int y )
{
// Subclass and override this method
printf( "KeyboardUp: %c \n", key );
keyStates.keyUp( (int)key );
}
void GlutFramework::specialKeyboardDown( int key, int x, int y )
{
// Subclass and override this method
printf( "SpecialKeyboardDown: %d\n", key );
}
void GlutFramework::specialKeyboardUp( int key, int x, int y )
{
// Subclass and override this method
printf( "SpecialKeyboardUp: %d \n", key );
}
// ******************************
// ** Graphics helper routines **
// ******************************
// Initialize the projection/view matricies.
void GlutFramework::setDisplayMatricies() {
/* Setup the projection and model view matricies */
int width = glutGet( GLUT_WINDOW_WIDTH );
int height = glutGet( GLUT_WINDOW_HEIGHT );
float aspectRatio = width/height;
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60, aspectRatio, 1, 500.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt(eyeVector.x, eyeVector.y, eyeVector.z,
centerVector.x, centerVector.y, centerVector.z,
upVector.x, upVector.y, upVector.z);
}
void GlutFramework::setupLights() {
GLfloat light1_position[] = { 0.0, 1.0, 1.0, 0.0 };
GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
GLfloat ambient_light[] = { 0.8, 0.8, 0.8, 1.0 };
glLightfv( GL_LIGHT0, GL_POSITION, light1_position );
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient_light );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light );
glLightfv( GL_LIGHT0, GL_SPECULAR, white_light );
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
}
void GlutFramework::setLookAt(float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ, float upX, float upY, float upZ) {
eyeVector = Vector<float>(eyeX, eyeY, eyeZ);
centerVector = Vector<float>(centerX, centerY, centerZ);
upVector = Vector<float>(upX, upY, upZ);
}
Vector<float> GlutFramework::getEyeVector() const {
return eyeVector;
}
Vector<float> GlutFramework::getCenterVector() const {
return centerVector;
}
Vector<float> GlutFramework::getUpVector() const {
return upVector;
}
void GlutFramework::setTitle(std::string theTitle) {
title = theTitle;
}
// **************************
// ** GLUT Setup functions **
// **************************
void GlutFramework::init() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
load();
}
void GlutFramework::setInstance() {
//std::cout << "GlutFramework::setInstance()" << std::endl;
instance = this;
}
void GlutFramework::run() {
if(frameRateTimer.isStopped()) { // The initial frame has the timer stopped, start it once
frameRateTimer.start();
}
frameRateTimer.stop(); // stop the timer and calculate time since last frame
double milliseconds = frameRateTimer.getElapsedMilliseconds();
frameTimeElapsed += milliseconds;
if( frameTimeElapsed >= FRAME_TIME ) { // If the time exceeds a certain "frame rate" then show the next frame
glutPostRedisplay();
frameTimeElapsed -= FRAME_TIME; // remove a "frame" and start counting up again
}
frameRateTimer.start(); // start the timer
}
void GlutFramework::displayFramework() {
if(displayTimer.isStopped()) { // Start the timer on the initial frame
displayTimer.start();
}
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Clear once
displayTimer.stop(); // Stop the timer and get the elapsed time in seconds
elapsedTimeInSeconds = displayTimer.getElapsedSeconds(); // seconds
setupLights();
setDisplayMatricies();
display(elapsedTimeInSeconds);
glutSwapBuffers();
displayTimer.start(); // reset the timer to calculate the time for the next frame
}
// ******************************************************************
// ** Static functions which are passed to Glut function callbacks **
// ******************************************************************
void GlutFramework::displayWrapper() {
instance->displayFramework();
}
void GlutFramework::reshapeWrapper(int width, int height) {
instance->reshape(width, height);
}
void GlutFramework::runWrapper() {
instance->run();
}
void GlutFramework::mouseButtonPressWrapper(int button, int state, int x, int y) {
instance->mouseButtonPress(button, state, x, y);
}
void GlutFramework::mouseMoveWrapper(int x, int y) {
instance->mouseMove(x, y);
}
void GlutFramework::keyboardDownWrapper(unsigned char key, int x, int y) {
instance->keyboardDown(key,x,y);
}
void GlutFramework::keyboardUpWrapper(unsigned char key, int x, int y) {
instance->keyboardUp(key,x,y);
}
void GlutFramework::specialKeyboardDownWrapper(int key, int x, int y) {
instance->specialKeyboardDown(key,x,y);
}
void GlutFramework::specialKeyboardUpWrapper(int key, int x, int y) {
instance->specialKeyboardUp(key,x,y);
}
} // namespace
ParticleSimulation.h
#include "preheader.h"
#include "Particle.h"
#include "GlutFramework.h"
#ifndef ___PARTICLESIMULATION_H___
#define ___PARTICLESIMULATION_H___
using namespace glutFramework;
#ifndef ABS_IMAGE_LOCATION
#define ABS_IMAGE_LOCATION "E:/IIIT B/College/Sem 3/CG/GraphicAssignment3/images/particle.bmp"
#endif
class ParticleSimulation : virtual public GlutFramework{
private:
GLuint numParticles; // total number of particles in the system
Particle *particles;
GLuint textureParticle;
//static GLint textureCount;
//functions
void AllocateObjects(void );
void DeAllocateObjects(void );
public:
ParticleSimulation(void );
ParticleSimulation(GLuint numParticles);
~ParticleSimulation(void );
void InitParticles(void );
void EvolveParticle(void );
void DisplayObjects(void );
void LoadTextureRAW(const char * filename, int wrap);
void LoadTextureBMP(const char * filename, int wrap);
void FreeTexture(void );
void DrawAxis();
void RenderBitmapString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string);
//virtual functions
void display(float dTime);
};
#endif //___PARTICLESIMULATION_H___
ParticleSimulation.cpp
#include "ParticleSimulation.h"
using namespace std;
. . .
void ParticleSimulation::DisplayObjects(){
// rendering functions
glLoadIdentity();
//glRotatef(20.0, 1.0, 0.0, 0.0); // show scene from top front
//glBindTexture(GL_TEXTURE_2D, this->textureParticle); // choose particle texture
for (int i = 0; i <= this->numParticles; i++){
GLfloat xpos = 0.0f, ypos = 0.0f, zpos = 0.0f;
particles[i].getPosition(xpos, ypos, zpos);
if(ypos < 0.0)
particles[i].setLifeTime(0.0);
if(particles[i].getActiveStatus() && particles[i].getLifeTime() > 0.0) {
GLfloat red = 0.0f, green = 0.0f, blue = 0.0f;
particles[i].getColor(red, green, blue);
glColor3f(red, green, blue);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(0.0,1.0); glVertex3f(xpos + 0.002, ypos + 0.002, zpos + 0.0); // top right
glVertex2f(0.0,0.0); glVertex3f(xpos - 0.002, ypos + 0.002, zpos + 0.0); // top left
glVertex2f(1.0,1.0); glVertex3f(xpos + 0.002, ypos - 0.002, zpos + 0.0); // bottom right
glVertex2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0); // bottom left
//glTexCoord2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0); // bottom left
glEnd();
} else {
particles[i].CreateParticle();
}
}
EvolveParticle();
}
void ParticleSimulation::EvolveParticle()
{
for(int i = 0; i <= this->numParticles; i++){ // evolve the particle parameters
GLfloat xpos = 0.0f, ypos = 0.0f, zpos = 0.0f;
GLfloat green = 0.0f, red = 0.0f, blue = 0.0f;
GLfloat xVel = 0.0f, yVel = 0.0f, zVel = 0.0f;
particles[i].setLifeTime( particles[i].getLifeTime() - particles[i].getDecay() );
particles[i].getPosition(xpos, ypos, zpos);
particles[i].getSpeed(xVel, yVel, zVel);
particles[i].getPosition(xpos += xVel, ypos += yVel, zpos += zVel);
particles[i].getSpeed(xVel, yVel -= 0.00007, zVel);
}
}
// Texture ///////////////////////////////////////////////////////////
// load a 256x256 RGB .RAW file as a texture
void ParticleSimulation::LoadTextureBMP(const char * filename, int wrap)
{
int width = 0, height = 0;
BYTE *data = NULL;
FILE *file = NULL;
// open texture data
file = fopen( filename, "rb" );
if ( file == NULL ) {
cout << "\nFile could not be opened." << endl;
return;
}
// allocate buffer
width = 256;
height = 256;
data = (BYTE *) malloc( width * height * 3 );
// read texture data
fread( data, width * height * 3, 1, file );
fclose(file);
// allocate a texture name
this->textureParticle = 0;
glGenTextures( 1, &this->textureParticle );
// select our current texture
glBindTexture( GL_TEXTURE_2D, this->textureParticle );
// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// when texture area is small, bilinear filter the closest MIP map
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first MIP map
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
wrap ? GL_REPEAT : GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
wrap ? GL_REPEAT : GL_CLAMP );
// build our texture MIP maps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width,
height, GL_RGB, GL_UNSIGNED_BYTE, data );
// free buffer
free( data );
return;
}
void ParticleSimulation::FreeTexture(void )
{
glDeleteTextures(1, &this->textureParticle);
}
void ParticleSimulation::DrawAxis() {
char s1[10];
glPushMatrix();
glColor3f(1.0f, 0.0f, 0.0f);
sprintf(s1, "X-axis");
RenderBitmapString(50.0f, 0.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1);
sprintf(s1, "Y-axis");
RenderBitmapString(0.0f, 50.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1);
sprintf(s1, "Z-axis");
RenderBitmapString(0.0f, 0.0f, 50.0f, GLUT_BITMAP_HELVETICA_12, s1);
sprintf(s1, "Origin");
RenderBitmapString(0.0f, 0.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1);
glPointSize(4.0f);
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 50.0f, 0.0f);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(50.0f, 0.0f, 0.0f);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 50.0f);
glEnd();
glPopMatrix();
}
void ParticleSimulation::display(float dTime)
{
static int frame = 0;
//cout << "GlutFramework Display: Frame: " << frame << ", dt(sec): " << dTime << ", Position: " << position << endl;
++frame;
//cout << "Calling the DisplayObject Function" << endl;
//glTranslatef(0.0f, 0.0f, 0.0f);
//glutSolidTeapot(2.5);
DrawAxis(); //Aditya: Working with grayscale though
DisplayObjects(); //Aditya: Nothing is drawn
}
LoadTextureBMP() is being invoked (with its bevy of OpenGL calls) before you have an OpenGL context (via startFramework()).
You need a current context before issuing GL commands.
EDIT:
for(int i = 0; i <= this->numParticles; i++)
Stop that. You're accessing off the end of your allocated memory.
Do this:
for(int i = 0; i < this->numParticles; i++)
Notice the less-than instead of the less-than-or-equal. For C/C++ arrays of size N the only valid indexes are in the range [0, N-1]. Your <= will cause the for-loop to try to access element N.
That's bad.
EDIT2:
GlutFramework::init() enables lighting. This is altering the colors in your axis rendering in ParticleSimulation::DrawAxis(). Disable it in ParticleSimulation::display() via glDisable(GL_LIGHTING):
EDIT3:
This will do something but probably not what you expect:
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(0.0,1.0); glVertex3f(xpos + 0.002, ypos + 0.002, zpos + 0.0); // top right
glVertex2f(0.0,0.0); glVertex3f(xpos - 0.002, ypos + 0.002, zpos + 0.0); // top left
glVertex2f(1.0,1.0); glVertex3f(xpos + 0.002, ypos - 0.002, zpos + 0.0); // bottom right
glVertex2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0); // bottom left
glEnd();
You seem to think that glVertex2f() will somehow generate texture coordinates. It will not. You're looking for glTexCoord2f().
For drawing view-aligned triangles you'll want to look into billboarding.

Resources