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)

    http://s1.directupload.net/images/120728/temp/bm2ph7pm.png



  • Das Problem ist entweder, der Funktionsparameter ( GLfloat *position ) von setPosition ist irgendwie ungültig - oder

    glLightfv(light, GL_POSITION, position);
    

    verändert position zu 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 von getPosition , irgendwie verändert wurden). Zeig mal den Code, mit dem du light1 definierst 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ört
    

    Haha! 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::vector und wenn du die Adresse auf das C-Array brauchst, schreibst du

    v.data(); //C++11
    oder
    &v[0]
    

    Wenn es dir zu ungemütlich ist, schreib einfach ein static vor GLfloat in 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 ^^.

    Rule of three

    aptem schrieb:

    Und was sind Initialisierungslisten?

    Initialisierungsliste



  • 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.


Anmelden zum Antworten