Zeiger-Werte ändern sich??
-
Hallo zusammen,
ich setze mich gerade ein bisschen mit OpenGL auseinander und möchte die Position einer Lichtquelle abrufen bzw. ändern. Dazu folgende Klasse:
Light.h
#pragma once #include <freeglut.h> #include <iostream> using namespace std; class Light { public: Light(GLenum light, GLfloat *position, GLfloat *ambient, GLfloat *diffuse, GLfloat *specular); ~Light(void); void setVisible(bool); bool isVisible(); void setPosition(GLfloat *position); GLfloat *getPosition(); void translate(GLfloat *direction); private: GLenum light; GLfloat *position; GLfloat *ambient; GLfloat *diffuse; GLfloat *specular; bool visible; };Light.cpp
#include "Light.h" #define DEBUG Light::Light(GLenum light, GLfloat *position, GLfloat *ambient, GLfloat *diffuse, GLfloat *specular) { this->light = light; this->position = position; this->ambient = ambient; this->diffuse = diffuse; this->specular = specular; visible = true; glLightfv(this->light, GL_POSITION, this->position); glLightfv(this->light, GL_AMBIENT, this->ambient); glLightfv(this->light, GL_DIFFUSE, this->diffuse); glLightfv(this->light, GL_SPECULAR, this->specular); glEnable(this->light); #ifdef DEBUG cout << "Licht initialisiert bei:" << endl; cout << "position[0]=" << this->position[0] << endl; cout << "position[1]=" << this->position[1] << endl; cout << "position[2]=" << this->position[2] << endl; cout << "position[3]=" << this->position[3] << endl; #endif } Light::~Light(void) { glDisable(this->light); delete position; delete ambient; delete diffuse; delete specular; } void Light::setVisible(bool visible) { this->visible = visible; if(this->visible) glEnable(light); else glDisable(light); } bool Light::isVisible() { return visible; } void Light::setPosition(GLfloat *position) { this->position = position; glLightfv(light, GL_POSITION, position); #ifdef DEBUG cout << "Licht bei:" << endl; cout << "position[0]" << position[0] << endl; cout << "position[1]" << position[1] << endl; cout << "position[2]" << position[2] << endl; cout << "position[3]" << position[3] << endl; #endif } GLfloat *Light::getPosition() { cout << "position[0]=" << position[0] << endl; cout << "position[1]=" << position[1] << endl; cout << "position[2]=" << position[2] << endl; cout << "position[3]=" << position[3] << endl; return position; } void Light::translate(GLfloat *direction) { for(int i = 0;i < 4;i++) { position[i] += direction[i]; } glLightfv(light, GL_POSITION, position); }Wenn ich nun eine Lichtquelle erzeuge, dann werden mir die Werte bei der Initialisierung korrekt angezeigt. Sobald ich aber nun folgendes mache:
light1->setPosition(light1->getPosition());Dann stimmen die Werten im Positions-Array nicht mehr. (Siehe Bild)
-
Das Problem ist entweder, der Funktionsparameter (
GLfloat *position) vonsetPositionist irgendwie ungültig - oderglLightfv(light, GL_POSITION, position);verändert
positionzu einem ungültigen Zeiger.Andererseits liegt es, soweit man vom Bild her erkennen kann, nicht an
setPosition(da die Werte schon vorher, vor einem Aufruf vongetPosition, irgendwie verändert wurden). Zeig mal den Code, mit dem dulight1definierst und was damit gemacht wird.
-
An
glLightfv(light, GL_POSITION, position);kann es nicht liegen, da beim initialisieren die Werte Korrekt ausgegeben werden (Ausgabe findet nach glLightfv statt)
Anbei der gewünschte Code:
Hauptprogramm:
#include "Device.h" #include "Camera.h" #include "Light.h" void initFunc(); void displayFunc(); void reshapeFunc(int, int); void mouseFunc(int, int, int, int); void mouseWheelFunc(int, int, int, int); void keyboardFunc(unsigned char, int, int); Device *device; Camera *camera; Light *light1; float angle = 0.0; int main(int argc, char **argv) { int winS[] = {800, 600}; int winP[] = {1920/2-800/2, 1080/2-600/2}; GLclampf clrColor[] = {0.0, 0.0, 0.0, 0.0}; device = new Device(argc, argv, winS, winP, "Rendering a Lit Sphere", GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH, clrColor, initFunc, displayFunc, reshapeFunc, mouseFunc, mouseWheelFunc, keyboardFunc); device->setIdleFunc(displayFunc); camera = new Camera(); camera->translate(-3,2,10); device->run(); return 0; } void initFunc() { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glShadeModel(GL_SMOOTH); GLfloat position[4] = {1.0, 0.0, 0.0, 0.0}; GLfloat ambient[4] = {0.0, 0.0, 0.0, 1.0}; GLfloat diffuse[4] = {1.0, 1.0, 1.0, 1.0}; GLfloat specular[4] = {1.0, 0.0, 0.0, 1.0}; light1 = new Light(GL_LIGHT0, position, ambient, diffuse, specular); } void displayFunc() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glPushMatrix(); glutSolidSphere(1.0, 20, 16); glPopMatrix(); angle += 0.01f; glutSwapBuffers(); } void reshapeFunc(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLdouble) w / (GLdouble) h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); camera->update(); } void mouseFunc(int, int, int, int) { } void mouseWheelFunc(int, int, int, int) { } void keyboardFunc(unsigned char key, int x, int y) { switch(key) { case 'a': light1->setPosition(light1->getPosition()); break; case 's': if(light1->isVisible()) light1->setVisible(false); else light1->setVisible(true); break; default: break; } }
-
Vorab ein kleiner Tipp:
if(light1->isVisible()) light1->setVisible(false); else light1->setVisible(true);Ist dasselbe wie
light1->setVisible( !light1->isVisible() );Zum Problem:
void initFunc() { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glShadeModel(GL_SMOOTH); GLfloat position[4] = {1.0, 0.0, 0.0, 0.0}; //Hier deklariert GLfloat ambient[4] = {0.0, 0.0, 0.0, 1.0}; GLfloat diffuse[4] = {1.0, 1.0, 1.0, 1.0}; GLfloat specular[4] = {1.0, 0.0, 0.0, 1.0}; light1 = new Light(GL_LIGHT0, position, ambient, diffuse, specular); //Deine light-Instanz behält den Zeiger auf das lokale Objekt }//Hier wird der Speicher freigegeben und das Array zerstörtHaha! Du übergibst natürlich einen Zeiger auf ein Funktionslokales Array an die Funktion! Sein Speicher wird, da es ein Stackobjekt ist, am Ende des Scopes in dem es deklariert wurde freigegeben.
Nimm am besten für alles einfach einen
std::vectorund wenn du die Adresse auf das C-Array brauchst, schreibst duv.data(); //C++11 oder &v[0]Wenn es dir zu ungemütlich ist, schreib einfach ein
staticvorGLfloatin Zeile 7.
Allerdings frag ich mich, ob du wirklich den Speicher für deine ganzen Objekte selbst allokieren musst.
Ganz abgesehen davon, dass du die Dreier-Regel für deine Klasse misachtest, überall C-Arrays verwendest und keine Initialisierungslisten im Konstruktor verwendest; Ich meine, wenn du wirklich allokieren musst, nimm Smartpointer o. ä.
-
Danke für deine Hilfe!

Ganz abgesehen davon, dass du die Dreier-Regel für deine Klasse misachtest, überall C-Arrays verwendest und keine Initialisierungslisten im Konstruktor verwendest; Ich meine, wenn du wirklich allokieren musst, nimm Smartpointer o. ä.
Ich komme aus der JAVA-Ecke und habe C/C++ mit nur 2 Büchern (bisher) gelernt

Daher sagt mir die Dreier-Regel nichts ^^.Und was sind Initialisierungslisten?
Ich bin für jeden Tipp hilfreich, wenn dadurch meine Programmierung effizienter und einfacher wird.
-
aptem schrieb:
Ich bin für jeden Tipp hilfreich, wenn dadurch meine Programmierung effizienter und einfacher wird.

aptem schrieb:
Ich komme aus der JAVA-Ecke und habe C/C++ mit nur 2 Büchern (bisher) gelernt

Großer Fehler: Kaufe und lerne nie aus einem Buch, in dessen Titel C/C++ vorkommt. Entweder du willst C oder C++ lernen, aber bloß kein Mischmasch.
aptem schrieb:
Daher sagt mir die Dreier-Regel nichts ^^.
aptem schrieb:
Und was sind Initialisierungslisten?
-
Großer Fehler: Kaufe und lerne nie aus einem Buch, in dessen Titel C/C++ vorkommt. Entweder du willst C oder C++ lernen, aber bloß kein Mischmasch.
Nene
, die waren jeweils nur auf C bzw. C++ gerichtet.
-
aptem schrieb:
Großer Fehler: Kaufe und lerne nie aus einem Buch, in dessen Titel C/C++ vorkommt. Entweder du willst C oder C++ lernen, aber bloß kein Mischmasch.
Nene
, die waren jeweils nur auf C bzw. C++ gerichtet.Noch schlechter, C++ mit C-Büchern zu lernen!

-
Ich sag lieber nichts mehr. Sonst erwecke ich noch einen zu schlechten Eindruck

-
aptem schrieb:
Ich sag lieber nichts mehr. Sonst erwecke ich noch einen zu schlechten Eindruck

Schwachsinn, im Gegenteil.
Sag lieber mehr, man muss dir helfen.
-
Gut, dann melde ich mich wieder wenn ich auf weitere Schwierigkeiten stoße.