PDA

View Full Version : Drawing a sphere and recoloring and/or deleting it



LReiter
09-19-2013, 09:48 AM
Hey all,
for an university project I am trying to write a program that shows a couple of white spheres that turn red one by one, each time the mouse is clicked. However, I can't get it to work properly. Specifically, the spheres just won't recolor.
I am writing in c++ using the Qt framework and Qt Creator. Also, I use glut.
The (I believe relevant) principle of my code is as follows:
- I have the functions initializeGL(), resizeGL() and paintGL(). These are part of my GLWidget (responsible for the 3D Window). The names are pretty straightforward, I think.
- In the paintGL() function, I instantiate an array of objects of the type "sphere" (custom type). The constructor of "sphere" calls my function sphere::drawsphere().
- drawsphere() uses glutsolidsphere() to do its job. It gets input on position and color of the glutsolidsphere from "sphere"'s constructor, which is called from paintGL(). If the variable "colo" is 'w', it's supposed to draw a white sphere. 'r' is for red. It uses an if/else construct for that.
- Also in paintGL, I count the clicks from the mouse. If it has been clicked, say, 2 times, I give the command sphaere[1]->colo='r'; . However, nothing changes, which is my primary problem.
I hope I have made myself clear enough (English is not my first language).
I'm new to OpenGL and still have poblems figuring out how it all works. If anyone could help me simply based on principle, I would greatly appreciate it. Thanks.
ps. I tried to post some of my code alongside this question, but it just denied me the post.

Carmine
09-19-2013, 12:00 PM
If the variable "colo" is 'w', it's supposed to draw a white sphere. 'r' is for red. A simple experiment I would do first is to initialize 'colo' to 'r' (i.e. no mouse clicks required). Does this make the sphere red? This should help you narrow down the problem. Good luck.

LReiter
09-19-2013, 12:39 PM
Thanks for the tip! However, if I call the constructor with an 'r', it does produce a red sphere.
I also attached a qDebug to the drawSphere() function to see which color sphere is drawn when.
It appears that since the sphere is already drawn when I use setSphereColor() the change doesn't affect it in the next iteration of paintGL().

paintGL


void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, 0.0f); //Placeholder
sphere **sphaere = new sphere*[10];
for(iii=0;iii<MyWindow::N-1;iii++) {
sphaere[iii] = new sphere(MyWindow::fX[iii], MyWindow::fY[iii], MyWindow::fZ[iii], 'w', true);
qDebug() << "sphaere[" << iii << "].colo ist: " << sphaere[iii]->getSphereColor();
}
switch(klick) {
case 1:
sphaere[0]->setSphereColor('r');
qDebug() << "sphaere[0].colo ist: " << sphaere[0]->getSphereColor();
qDebug() << "sphaere[1].colo ist: " << sphaere[1]->getSphereColor();
break;
case 2: sphaere[1]->setSphereColor('r');
qDebug() << "sphaere[0].colo ist: " << sphaere[0]->getSphereColor();
qDebug() << "sphaere[1].colo ist: " << sphaere[1]->getSphereColor();
break;
default:break;
}

//glFlush(); //necessary?
//glutSwapBuffers(); //necessary?
qDebug() << "paintGL fertig in Durchlauf Nr." << counter; // Zum Debuggen.
counter ++;
}


sphere.cpp


#include "glwidget.h"
#include "sphere.h"
char colo = 'w';

sphere::sphere() {
qDebug() << "Sphere init.";
colo = 'w';
}

sphere::sphere(float fX, float fY, float fZ, char colo, bool zeichne) {
drawsphere(fX, fY, fZ, colo, zeichne);
qDebug() << "drawsphere ausm constructor gecalled";
}

void sphere::drawsphere(float fX, float fY, float fZ, char colo, bool zeichne) {
if(zeichne==true){
if(colo == 'w') {
glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
glTranslatef(fX, fY, fZ);
glutSolidSphere(0.5,16,16);
qDebug() << "weiße Sphäre gedrawed";
glPopMatrix();
glFlush();
}

else if(colo == 'r') {
glColor3f(1.0f, 0.2f, 0.2f);
glPushMatrix();
glTranslatef(fX, fY, fZ);
glutSolidSphere(0.5,16,16);
qDebug() << "rote Sphäre gedrawed";
glPopMatrix();
glFlush();
}
else {
qDebug() << "colo ist weder w noch r!!!";
}
}
}

void sphere::setSphereColor(char col) {
sphere::colo = col;
qDebug() << "sphere::colo ist" << sphere::colo << "und col ist" << col << "in setSphereColor";
}

char sphere::getSphereColor() {
qDebug() << colo << "ist colo in getSphereColor";
return sphere::colo;
}

Apologies if it's messy.

mhagain
09-19-2013, 12:50 PM
Single buffered context on Windows Vista or higher? Try using double buffered instead (with the appropriate SwapBuffers call at the end of your paint function).

LReiter
09-19-2013, 01:19 PM
Thank you. A swapBuffers() call as well as a SwapBuffers(hDC) call will result in a completely black background (as opposed to my default glClearColor() grey). I think I'm only drawing in one buffer as opposed to two. How do I draw into the second buffer as well?
ps. I'm using Windows 7 via BootCamp on a MacBook.

mhagain
09-19-2013, 05:30 PM
Using GLUT, look for your glutInitDisplayMode call, and either replace the GLUT_SINGLE parameter with GLUT_DOUBLE, or if neither are specified just add GLUT_DOUBLE. Then add glutSwapBuffers at the end of your display function.

There is a way of getting single-buffered contexts to work (just adding a glFlush) but to be honest double-buffered is so easy - just one changed parameter and one extra line of code - that you're better off doing it right. It's puzzling that so much GLUT material still creates a single-buffered context; one would almost think that double-buffered was seen as some kind of advanced topic, whereas it's clearly not (and has more robust support too).

LReiter
09-24-2013, 12:39 AM
Okay, thanks for the tip, but adding
glutInitDisplayMode(GLUT_DOUBLE);
in my initializeGL() function and
glutSwapBuffers();
in my paintGL() function simply causes the program to crash.
After that, I tried glDrawBuffer(GL_BACK) at the beginning of my paintGL() function and swapBuffers() at the end as well as several places for makecurrent(), but nothing has worked so far. I get the debug error "QOpenGLContext::swapBuffers() called without corresponding makeCurrent()" and don't know what to make of it. :( I simply get a flickering screen (normally black, just my drawings when paintGL() is called, for example while resizing). Thank you so much for taking your time.

LReiter
09-26-2013, 08:00 AM
Well, for now I decided to not focus on the double buffering (might as well do it as soon as I get the "simpler" way to work, I think).
My problem is still that I'm initializing the array of spheres in my paintGL function. Since I'm doing this, the recoloring to red has no effect (it's already drawn in this iteration of paintGL and when drawn the next time it's initalized in white).
So basically I (think I) know what my problem is. I just don't know how to fix it! Does anyone have any idea where I could initialize the array? I tried in the constructor of my GLWidget and in the initalizeGL function, but it either doesn't compile (constructor) or just crashes when it's supposed to draw (initializeGL).
Help me please, I'm desparate you guys :(