Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 11:43

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: [OpenGL]Wie gehe ich an sowas ran?
BeitragVerfasst: Sa Apr 03, 2010 14:01 
Offline
DGL Member

Registriert: Mi Nov 18, 2009 10:55
Beiträge: 20
Programmiersprache: C++
Hallo.
Ich bin seit gestern dabei mir Konzepte für die Umsetzung einer Map-Klasse für ein Spiel zu überlegen.
Das Problem ist, dass ich nicht weiß, wie ich es am besten umsetzte.
Also die Kamera soll isometrisch über der Karte angebracht sein und man soll sie drehen - das ist ja auch nicht das Problem. Aber die Karte soll in gleichgroße Felder unterteilt werden.
Es folgen jetzt einige Bilder, an denen die Eingeschaften der Karte erklärt werden sollen.
Dieses Bild zeigt erstmal nur die Unterteilung in Felder, die rote Auswahl ist hierbei ein (besetztes) Feld.
Auf einem besetzten Feld steht (logischerweise) irgendetwas. Hierzu wollte ich ein 3D-Objekt-Klassen-Objekt aus einer Liste laden und an die richtigen Weltkoordinaten setzten. Diese 3DOKOs haben als membervariable einen const char* Dateinamen, dessen inhalt geladen und als mesh-Datei angegeben werden kann. Zusätzlich soll die 3DOK noch verschiedene Werte haben wie Ausrichtung (Nord/Süd/West/Ost), damit wird das Mesh entweder garnicht, um 90°, um 180° oder um -90° gedreht. Ein anderer Wert wäre die Position im Raum z.B. 10x6, das wäre dann halt das Feld an den Koordinaten für das 10x6te Feldobjekt der Karte.
Nun haben wir also sagen wir ein solches Objekt, z.B. einen Tisch gesetzt. Der Tisch ist allerdings so groß wie 2 Felder, nun müsste die Map also eine Wahrnehmung bekommen, und der Tisch der Map übermitteln, dass 2 Felder besetzt sind, wobei das zweite Feld im normalfall nördlich des Anfangsfeldes ist. Wird der Tisch dann nach süd/west/ost gedreht, muss das 2. besetzte Feld ermittelt werden.

Doch das eigentliche Problem, bei dem ganzen werden die Wände/Türfelder/Räume sein. Diese sehen nämlich so aus. Die roten Linien stellen Mauern dar und die grüne Linie ist eine anfang noch geschlossene Tür.

Habt ihr vielleicht Tipps oder am besten Codeschnippsel, die mir helfen können damit klar zu kommen.
Dann ist da noch die Frage des Desings: Sollte ich die Mauern in OpenGL als primitive "hochziehen", nachdem bekannt ist, wo sie stehen sollen - oder soll ich einige Mauer-Meshes haben und diese Plazieren?
Dann zu den Türen, was auch ein Problem sein könnte:
Sollte ich hier eine Textur verwenden, die im "Tür-ist-offen"-Modus anders aussieht, als im "Tür-ist-zu"-Modus? Oder Soll ich an den Türstellen einfach keine Mauer setzen, sondern ein Türobjekt, das eine "Aufschwungs-Seite" besitzt, die sich bewegt während die andere immer still steht?

Ich hoffe auf detailierte Antworten.

mfg Klabauter


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Apr 03, 2010 15:12 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Ich hab mal gerade 15 Minuten invertiert und mir was überlegt. Das folgende ist UML-Notation mit C++, also wenn etwas unklar ist einfach fragen.
Dateianhang:
uml.png


Ein Mesh ist einfach nur eine Klasse die irgendwie Geometrie kapselt und rendern kann. Angenommen du hast einen Stuhl oder ähnliches mehrfach in deiner Map, so gäbe es nur ein Mesh-Objekt mit der Geometrie des Stuhls. Für jeden Stuhl in deiner Map gibt es aber dann ein MapObject, welches die Position/Ausrichtung [3] sowie einen Pointer auf das Mesh enthält.
Ein Aufruf von MapObject.render() macht nichts weiter als die Position/Ausrichtung an OpenGL zu übergeben (glTranslate, glRotate, ...) und dann mesh->render() aufzurufen. Da es nur vier verschiedene Ausrichtungen gibt habe ich das mal als Enumeration [2] realisiert, man könnte hier aber auch einen Winkel nehmen.

Das zentrale Objekt ist das "Map" Singleton [1], es kennt alle Objekte auf deiner Karte. Deine Map besteht aus n mal n Feldern. Es gibt drei große Arrays die deine Map darstellen:
  • field : Pointer auf das Objekt das auf dem jeweiligen Feld steht
  • wallsNorthSouth : Pointer auf die Wand-Objekt die in Nord-Süd-Richtung verlaufen. Da die Map n Felder breit ist gibt es n+1 Wände dazwischen.
  • wallsWestEast : Wände in West-Ost-Richtung

Wenn es großes Objekt (dein Beispiel war ein Tisch) mehrere Felder bedeckt zeigen einfach alle Pointer auf das selbe MapObject. Aus diesem Grund ist auch die Position im MapObject gespeichert, ob wohl sich das aus der Array-Positon berechnen ließe.

Da MapObjecte mehrfach verlinkt sein könnten, gibt es die Methode updateVisibleList(). Diese findet zuerst alle Objekte im Sichtbereich der Kamera und eliminiert dann mehrfach vorkommende Objekte. Das geht am einfachsten indem man die Liste der Pointer zuerst sortiert und dann testet ob an einer Stelle zweimal hintereinander der gleiche Pointer zu finden ist. Die Methode updateVisibleList() muss nur dann aufgerufen werden wenn sich die Objekte und/oder die Kameraansicht verändert haben.

Mit Map.render() ruft man dann einfach die Methode render() aller Objekte in der Visible-Liste auf.

[Edit]
Zitat:
Sollte ich hier eine Textur verwenden, die im "Tür-ist-offen"-Modus anders aussieht, als im "Tür-ist-zu"-Modus? Oder Soll ich an den Türstellen einfach keine Mauer setzen, sondern ein Türobjekt, das eine "Aufschwungs-Seite" besitzt, die sich bewegt während die andere immer still steht?

Die Frage ist mir nicht ganz klar. Natürlich kannst du dem MapObject noch etwas mehr Funktionalität geben, z.B. eine Klasse DoorObject die von MapObject abgeleitet wird. Dieses ist dann in der Lage einen statischen Türrahmen sowie eine darin eingehängte bewegliche Tür zu rendern. Wenn dir Auf/Zu reicht gibt es einfach nur zwei Stellungen für die Tür. Wenn die Tür wirklich animiert aufgehen soll wird es komplizierter.
[/Edit]


[1] Singleton ist eine Bezeichnung für ein sogenanntes Design-Pattern bei dem von einer Klasse nur eine einzige Instanz (Objekt) erzeugt wird. Dies stellt man durch einen privaten Konstruktor sicher. Ein Pointer auf diese einzige Instanz wird in einem statischen Attribut gehalten, welches man mit einer ebenfalls statischen Methode (z.B. getInstance) zugreifen kann. Die Instanz wird erzeugt, wenn die statische Methode das erste mal aufgerufen wird.

[2] Ich weiß nicht ob es in Delphi Enums gibt, letztlich ist das aber nur ein Integer den man bequem mit Namen ansprechen kann.

[3] Im Bild besteht die Position aus einem Vector3....das soll ein Record sein der x,y und z Koordinaten enthält. Sorry, war Gewohnheit...du brauchst natürlich nur zwei Koordinaten. Ich hatte keine Lust das Bild neu zu machen.


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 02:50 
Offline
DGL Member

Registriert: Mi Nov 18, 2009 10:55
Beiträge: 20
Programmiersprache: C++
Besten Dank, Coolcat.
Leider stecke ich schon am Anfang fest und ich schätze, dass es diesmal an rudimentären C++-Kentnissen hapert. :(
Also ich versuche gerade den etwas zum Laden eines Meshes zu schreiben.
Das Ganze ist noch sehr einfach und ist noch auf kein Datei-Format (außer eventuell mein eigenes) angepasst, aber hier erstmal, wieweit ich damit bin:

Code:
struct s_Textur {
    const char* Name;
    const double X; //Positionierungen
    const double Y;
    s_Textur(const double x=TexDefaKoor_X, const double y=TexDefaKoor_Y, const char* name=TexDefaNa): X(x), Y(y), Name(name) {};
};

struct s_Material {
    //! const int ID;
    int ID;
    s_Textur *Tex;
    s_Material(const int id): ID(id) { Tex = new s_Textur(); } //Default-Values
    s_Material(const int id, double x, double y, char* Name): ID(id) {
        Tex = new s_Textur(x,y,Name);
    }
};

struct s_Vertex {
    double X;
    double Y;
    double Z;
    //s_Vertex(double x, double y, double z): X(x), Y(y), Z(z) {};
};

struct s_Mesh {
      std::vector<s_Vertex> Points;
      std::vector<s_Material> Mat;
      void createAndAddPoint (double x=-51.25, double y=-51.25, double z=-51.25);
        void Render();
};
void s_Mesh::createAndAddPoint (double x, double y, double z) {
    Points.push_back( ((struct s_Vertex){x,y,z}) );
}

void s_Mesh::Render() { //es folgen OpenGL-Befehle zum Zeichnen
}

class c_MeshLoader {
   private:
      ///std::vector <s_Mesh*> Meshes;//! Kira... Das, was du da machst, ist BÖSE!
      std::vector <s_Mesh> Meshes;
   public:
      inline s_Mesh &get_Mesh(const int ID) {
            Infos << "[c_MeshLoader]Get Mesh with ID '" << ID << "'." << std::endl;
          return Meshes[ID];
      }
      void load_Mesh(const char* Name);
};
void c_MeshLoader::load_Mesh(const char* Name) {
    std::ifstream File;File.open(Name, std::ios::in);
    if(File.good()) {
        Infos << "[c_MeshLoader]Read File '" << Name << "'." << std::endl;
      s_Mesh *currentMesh = new s_Mesh();
      //Hier kommt eine Schleife zum Dateieinleisen.
        File.close();
        Infos << "[c_MeshLoader]Reading completed." << std::endl;

        /*Infos << &currentMesh->Points[0].X << std::endl; //Adresse
        Infos << currentMesh->Points[0].X << std::endl; //Wert

        /Infos << *&currentMesh->Points[0].X << std::endl; //Wert
        */
        Infos << "[c_MeshLoader]Meshes-Size: " << std::endl;

        ///Meshes.push_back(currentMesh);
        if(Meshes.empty()) {
            Infos << "Leer" << std::endl;
            ///Meshes.reserve(1);
        }
        else {
            Infos << "Nicht leer" << std::endl;
            ///Infos << Meshes.size() << std::endl;
        }

        //! Meshes.push_back(*(new s_Mesh()));

        Meshes.reserve(Meshes.size()+1);
        Infos << "[c_MeshLoader]Mesh added." << std::endl;
        s_Mesh temp;
        Meshes[Meshes.size()-1]=*currentMesh;
        //delete currentMesh;
        ///currentMesh = NULL;
    }else
        Infos << "[c_MeshLoader]Cant load '" << Name << "'." << std::endl;
}


Mein Problem ist, dass das Programm einfach abstürzt, wenn ich load_Mesh ausführe. Genauergesagt sind die letzten beiden Einträge in die Log-Datei:
Zitat:
[c_MeshLoader]Reading completed.
[c_MeshLoader]Meshes-Size:

Gibt es jemanden, der mir sagen kann, was um alles in der Projektionsmatrix da schief läuft?
Ich vermute, dass die Strukturen da einfach nicht mitmachen wollen, - aber es kann doch nicht sein, dass ich nichtmal abfragen kann, wie groß Meshes ist...

Naja wie auch immer, ich bedanke mich jetzt erstmal bei Coolcat. Ich denke damit komme ich erstmal klar. Übrigens wollte ich noch kurz anmerken, dass mir bereits klar war, dass ich jedes Mesh nur einmal zu laden brauche. (Sowie die meisten verwendeten Fachbegriffe - aber es gab ganzklar auch neues, was ich vorher nicht gekannt habe ;))

Tut mir Leid, dass ich noch so neu bin und mich so unwissend benehme - aber das bin ich ja noch... (Programmiere nur privat.)

Gruß Klabauter


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 09:25 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jan 31, 2007 18:32
Beiträge: 150
Programmiersprache: Pascal
Nur ein Schnellschussmeinerseits, aber hast du vll vergessen etwas zu initialisieren?
Meshes würde sich da als guter Kanidat anbieten.
Ich nehme mal an es handelt sich dabeium irgendeine Art List-Klasse...
Vermutung ist nun das das ganze and der Stelle Meshes.Empty() abstürtzt.

Nur mal so am Rande besitzt die IDE mit der du arbeitest einen Debugger? wenn ja wäre diesen hier zu benutzen kein schlechter Anfang da du direkt herausfinden kannst in welcher Zeile das ganze nicht mehr will.(macht das finden von Fehlern durchaus einfacher^^)

ich hoffe das hilft weiter mfg FrenK


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 10:21 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Achso...du arbeitest unter C++....sag das doch ;)

Zitat:
Vermutung ist nun das das ganze and der Stelle Meshes.Empty() abstürtzt.

Also das kann eigentlich nicht sein, da Meshes kein Pointer ist. Aber man weiß ja nie ;)

Es kann sein das die Standardausgabe nicht vollständig ausgegeben wurde. Da hilft ein explizites std::cout.flush(). Ich benutze gerne dieses nette Tierchen:
Code:
// debug.h
#ifndef INCLUDE_GUARD_DEBUG
#define INCLUDE_GUARD_DEBUG

#ifdef DEBUG
   #define DEBUG_OUT std::cout << __FILE__ << ": line " << __LINE__ << ": "
   #define DEBUG_LINE DEBUG_OUT << "\n"; std::cout.flush()
   #define DEBUG_GL_ERROR {unsigned err = glGetError(); if(err != GL_NO_ERROR) DEBUG_OUT << "OpenGL Error: 0x" << std::hex << err << std::dec << "\n"; std::cout.flush(); }
#endif // DEBUG
#ifndef DEBUG
   #define DEBUG_OUT
   #define DEBUG_LINE
   #define DEBUG_GL_ERROR
#endif // DEBUG

#endif // INCLUDE_GUARD_DEBUG


Du schreibst einfach in eine Zeile "DEBUG_LINE;" und der gibt dir Dateiname und Zeilennummer aus, mit der Garantie das es auch wirklich in der Standardausgabe angekommen ist sobald das DEBUG_LINE ausgeführt wurde. DEBUG_GL_ERROR ist sowas ähnliches, fragt aber OpenGL-Fehlermeldungen ab. Über ein #define DEBUG bzw. #undef DEBUG vor dem inkludieren des Headers kannst du steuern ob du die Debugausgabe nutzen willst oder nicht. Bei ausgeschalteter Debug-Ausgabe wird der Debug-Code vom Compiler entfernt, es gibt also keinen Performance-Nachteil. Möglicherweise musst du das ganze von "std::cout" auf dein "Infos" umbauen.

Es ist übrigens empfehlenswert einen fertigen Loader zu benutzen. Die Dateiformate sind zum Teil recht kompliziert. Unter C++ wäre z.B. lib3ds empfehlenswert. Siehe auch hier:
http://wiki.delphigl.com/index.php/Mode ... ader_Liste

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 12:44 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Meshes.push_back(...) ist auskommentiert, darum ist der std::vector leer und size() somit 0. Der Fehler kommt dann beim Zugriff auf Meshes[Meshes.size()-1]. Die Ausgabe "Leer" siehst du nicht, weil eben das genannte flush() fehlt.

Der Aufruf von reserve() macht übrigens nur dann Sinn, wenn du mehrere (viele) Objekte hinzufügen willst und du im voraus genau weißt wie viele es werden. Passt bei einem push_back() das Objekt nicht mehr in den Vektor, vergrößert sich der Vektor automatisch um einen gewissen Prozentsatz (z.B. 50%).


Edit: Mist...das ist es nicht. std::endl macht ja ein flush... :roll:

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 14:56 
Offline
DGL Member

Registriert: Mi Nov 18, 2009 10:55
Beiträge: 20
Programmiersprache: C++
Hmmm das ist komisch - es stürzt tatsächlich genau beim Ansprechen des Vektors "Mehses" ab. Es ist egal, ob ich eine Abfrage wie z.B. if(Meshes.empty(), oder andere Funktionen des Vektors aufrufe ab: Es ist, als würde er außerhalb des Speichers stehen :shock:
Code:
        DEBUG_OUT << "[c_MeshLoader]capacity: "  << Meshes.capacity() << std::endl;
        DEBUG_OUT << "[c_MeshLoader]max_size: "  << Meshes.max_size() << std::endl;

Beide Zeilen verursachen einen totalabsturz des Programmes (Reihenfolge der Befehle ist irrelevant).

Währned ich diesen Post verfasse überprüfe ich noch mehrere Fehlerquellen:
1) Ich habe mal aus s_Mesh den Vektor für s_Material entfernt - Absturz an der gleichen Stelle
2) Auflösung vom "Points"-Vektor in dies
Code:
      std::vector<double> X;
      std::vector<double> Y;
      std::vector<double> Z;

Ergebnis: Keine Besserung.
3) Ich habe einfach mal (ohne weiter damit zu arbeiten) den Befehl Meshes.size(); verwendet - das wird ohne Probleme geschluckt...

So und zum Abschluss möchte ich festhalten: Meine Welt steht gerade Kopf.

P.S.:
Einen Loader werde ich wohl auch letztendlich nehmen, aber Übung schadet nie. ^^'
Außerdem mag ich es (noch) nicht sehr fremde Arbeit zu benutzen (außer wirklich wichtige Sachen wie Fenster-Erzeugung, OpenGL, und Sounds).


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 15:38 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Wie jetzt Meshes.empty() gibt einen Crash, aber Meshes.size() funktioniert? Da ist was GANZ faul.

Welche Platform und welchen Compiler benutzt du? Poste mal bitte den kompletten Code bzw. wenn das zu viel ist schicke mir das ganze als PM.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 15:56 
Offline
DGL Member

Registriert: Mi Nov 18, 2009 10:55
Beiträge: 20
Programmiersprache: C++
Vielleicht habe ich mich da etwas unklar ausgedrückt, habe dem Code ab Zeile 201 aber etwas zur Verdeutlichung hinzugefügt, was ich mit Meshes.size(); gemeint habe.
Code:
#include <string>
#include <vector>
#include <GL/glew.h>

#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#define DEBUG
#include "Debug.hpp"

#define TexDefaNa "[d]"
#define TexDefaKoor_X 0
#define TexDefaKoor_Y 1

class c_Applikation;
c_Applikation *App;

enum orientation {
    N, //North
    S, //South
    E, //East
    W  //West
};

struct s_Textur {
    const char* Name;
    const double X; //Positionierungen
    const double Y;
    s_Textur(const double x=TexDefaKoor_X, const double y=TexDefaKoor_Y, const char* name=TexDefaNa): X(x), Y(y), Name(name) {};
};

struct s_Material {
    //! const int ID;
    int ID;
    s_Textur *Tex;
    s_Material(const int id): ID(id) { Tex = new s_Textur(); } //Default-Values
    s_Material(const int id, double x, double y, char* Name): ID(id) {
        Tex = new s_Textur(x,y,Name);
    }
};

struct s_Vertex {
    double X;
    double Y;
    double Z;
    //s_Vertex(double x, double y, double z): X(x), Y(y), Z(z) {};
};

//! Not in use ...
/**
class c_Polygon {
    private:
        std::vector<s_Vertex> *Vtx;
    public:
        c_Polygon (const int Vertexes) {
            Vtx->reserve(Vertexes);
        }
};**/

struct s_Mesh {
        //Vertexes
      std::vector<s_Vertex> Points;
      std::vector<s_Material> Mat;
      void createAndAddPoint (double x=-51.25, double y=-51.25, double z=-51.25);
        void Render();
        int Render_Infos;
};

void s_Mesh::createAndAddPoint (double x, double y, double z) {
    DEBUG_OUT << "[s_Mesh]Define Vertex at (" << x << ", " << y << ", " << z << ")." << std::endl;
    DEBUG_FOUT << "[s_Mesh]Define Vertex at (" << x << ", " << y << ", " << z << ")." << std::endl;
    //s_Vertex *Vec = new s_Vertex;
    //Vec->X=x; Vec->Y=y; Vec->Z=z;


    Points.push_back( ((struct s_Vertex){x,y,z}) );
    /*
    s_Vertex Vec;
    Vec.X=x; Vec.Y=y; Vec.Z=z;
    DEBUG_OUT << "[s_Mesh]Pointerbody ready." << std::endl;
    DEBUG_FOUT << "[s_Mesh]Pointerbody ready." << std::endl;
    s_Vertex *XyZ;XyZ=&Vec;
    DEBUG_OUT << "[s_Mesh]Pointer has got a value." << std::endl;
    DEBUG_FOUT << "[s_Mesh]Pointer has got a value." << std::endl;

    //&Points->push_back(*XyZ);
    Points.push_back(Vec);
    */
}

void s_Mesh::Render() {
    if(Render_Infos!=2)
    Render_Infos++;
    /** ///Unnötiger Schleifenbalast!
    DEBUG_OUT << "[s_Mesh]Render the Mesh.\n";
    DEBUG_FOUT << "[s_Mesh]Render the Mesh.\n";
    DEBUG_OUT << "[s_Mesh]Anzahl der Punktevektoren: " << Points.size() << std::endl;
    DEBUG_FOUT << "[s_Mesh]Anzahl der Punktevektoren: " << Points.size() << std::endl;
    **/
    const int Anz=Points.size();
    ///glMatrixMode(GL_MODELVIEW);   // Select The Modelview Matrix
    ///glPushMatrix();             // Store The Modelview Matrix
    ///glLoadIdentity();         // Reset The Modelview Matrix

    ///glTranslatef(0.f, 0.f, -200.f);
    /*if( !(Anz%3) && !(Anz%4) )
        glBegin(GL_LINE_LOOP);
    else {
        if(Anz%3)
            glBegin(GL_TRIANGLE_STRIP);
        else if(Anz%4)
            glBegin(GL_QUAD_STRIP);
    }*/
        glBegin(GL_TRIANGLE_STRIP);
    if(Mat.size() > 0)
        for(int i=0; i<Anz; i++) {
            if(i >= Mat.size() ) {
                glVertex3f(Points[i].X, Points[i].Y, Points[i].Z);
                ///Unnötiger Schleifenbalast!
                if(Render_Infos==1) {
                DEBUG_OUT << "[s_Mesh]Vertex created.[" << i+1 << "/" <<Anz << "]" << std::endl;
                DEBUG_FOUT << "[s_Mesh]Vertex created.[" << i+1 << "/" <<Anz << "]" << std::endl;
                }

                continue;
            } else {
            glVertex3f(Points[i].X, Points[i].Y, Points[i].Z);
            glColor3f(Mat[i].Tex->X, Mat[i].Tex->Y,0); //Eigentlich glTexPos
            if(Render_Infos==1) {
             ///Unnötiger Schleifenbalast!
            DEBUG_OUT << "[s_Mesh]Vertex with Color/Texture created.[" << i+1 << "/" <<Anz << "]" << std::endl;
            DEBUG_FOUT << "[s_Mesh]Vertex with Color/Texture created.[" << i+1 << "/" <<Anz << "]" << std::endl;
            }
            }
        }
    else {
        for(int i=0; i<Anz; i++) {
            glVertex3f(Points[i].X, Points[i].Y, Points[i].Z);
            ///Unnötiger Schleifenbalast!
            if(Render_Infos==1) {
            DEBUG_OUT << "[s_Mesh]Vertex (" << i+1 << "/" <<Anz << ") created at [" << Points[i].X << "," << Points[i].Y << "," << Points[i].Z << "]" << std::endl;
            DEBUG_FOUT << "[s_Mesh]Vertex (" << i+1 << "/" <<Anz << ") created at [" << Points[i].X << "," << Points[i].Y << "," << Points[i].Z << "]" << std::endl;
            }
        }
    }
    glEnd();
};

s_Mesh *NeuesMesh;
class c_MeshLoader {
   private:
      ///std::vector <s_Mesh*> Meshes;//! Sören... Das, was du da machst, ist BÖSE!
      std::vector <s_Mesh> Meshes;
   public:
      //2 Funktionen: Eine zum Laden eines Meshes über den Dateinamen und eine andere zum Auswerten der Mesh-Dateidaten. Bei Erfolgreichem Laden+Auswerten würde ein 'currentMesh' über 'new' erzeugt, mit den ausgewerteten Werten befüllt und in den Vektor geschoben wird. ('delete nicht vergessen')
      inline s_Mesh &get_Mesh(const int ID) {
            DEBUG_OUT << "[c_MeshLoader]Get Mesh with ID '" << ID << "'." << std::endl;
            DEBUG_FOUT << "[c_MeshLoader]Get Mesh with ID '" << ID << "'." << std::endl;
          return Meshes[ID];
      }
      void load_Mesh(const char* Name);
};

bool schrott(false);
//Diese Funktion kann noch kein Mesh verarbeiten. (Es wird noch garnicht ausgelesen, die Datei sollte aber vorhanden sein)
void c_MeshLoader::load_Mesh(const char* Name) {
    std::ifstream File;File.open(Name, std::ios::in);
    if(File.good()) {
        DEBUG_OUT << "[c_MeshLoader]Read File '" << Name << "'." << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]Read File '" << Name << "'." << std::endl;
      s_Mesh *currentMesh = new s_Mesh();
      //s_Mesh currentMesh;
        ///File.close();
        ///File.open(Name);
        while(!schrott/*File.eof()*/) {
        DEBUG_OUT << "[c_MeshLoader]..." << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]..." << std::endl;
            if(!schrott) {
            currentMesh->createAndAddPoint(-50.f, -50.f, -50.f);
            currentMesh->createAndAddPoint(-50.f,  50.f, -50.f);
            currentMesh->createAndAddPoint( 50.f,  50.f, -50.f);
            currentMesh->createAndAddPoint( 50.f, -50.f, -50.f);
            schrott=true;
            }
        }
        File.close();
        DEBUG_OUT << "[c_MeshLoader]Reading completed." << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]Reading completed." << std::endl;

        /*DEBUG_FOUT << &currentMesh->Points[0].X << std::endl; //Adresse
        DEBUG_FOUT << currentMesh->Points[0].X << std::endl; //Wert

        /DEBUG_FOUT << *&currentMesh->Points[0].X << std::endl; //Wert

        */

        DEBUG_OUT << "[c_MeshLoader]Prüfe auf Funktionsaufrufe ohne Auswertung: " << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]Pruefe auf Funktionsaufrufe ohne Auswertung: " << std::endl;
        ///Normale Funktionsaufrufe...
        Meshes.empty();
        Meshes.size();
        Meshes.capacity();
        DEBUG_OUT << "[c_MeshLoader]Pruefung OK." << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]Pruefung OK." << std::endl;

        DEBUG_OUT << "[c_MeshLoader]Meshes-Size: ";
        DEBUG_FOUT << "[c_MeshLoader]Meshes-Size: ";

        ///Meshes.push_back(currentMesh);
        if(Meshes.empty()) {
            DEBUG_OUT << "Leer" << std::endl;
            DEBUG_FOUT << "Leer" << std::endl;
            ///Meshes.reserve(1);
        }
        else {
            DEBUG_OUT << "Nicht leer\n";
            DEBUG_FOUT << "Nicht leer\n";
            DEBUG_OUT << "\t\t" << Meshes.size() << std::endl;
            DEBUG_FOUT << "\t\t" << Meshes.size() << std::endl;
            ///DEBUG_FOUT << Meshes.size() << std::endl;
        }

        //! Meshes.push_back(*(new s_Mesh()));

        Meshes.reserve(Meshes.size()+1); //Als Ersatz für push_back
        DEBUG_OUT << "[c_MeshLoader]Mesh added." << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]Mesh added." << std::endl;
        s_Mesh temp;
        Meshes[Meshes.size()-1]=*currentMesh;
        //delete currentMesh;
        ///currentMesh = NULL;
    }else {
        DEBUG_OUT << "[c_MeshLoader]Cant load '" << Name << "'." << std::endl;
        DEBUG_FOUT << "[c_MeshLoader]Cant load '" << Name << "'." << std::endl;
    }
}

c_MeshLoader *MeshMan;



//class LifeformMapObject; //Hier erstmal total unnötig
class DeadMapObject {
   private:
        //Membervariablen wie z.B. einen Funktionszeiger auf die Funktion für die "KI" bzw. "Perception" des Objektes [an ID angepasst]
        double Coordinate_X;
        double Coordinate_Y;
        orientation Orientation;
        //std::vector <double> Coordinates; //STL-Vektoren kann man schlecht/garnicht über Initialisierungslisten mit x [in diesem Fall 2] reservieren.
   public:
        //Getter-Funktionen
        //Setter-Funktionen [für "künstliche" Positionsveränderungen während des Spieles]
        double extract_MeshXPos(); //Übermittelt X-Position auf der Karte
        double extract_MeshYPos();
        orientation extract_MeshOrientation();
        double get_XPosition();
        DeadMapObject(const int ID): Coordinate_X(extract_MeshXPos()),
            Coordinate_Y(extract_MeshYPos()),
            Orientation(extract_MeshOrientation()) {}; //Vielleicht etwas ungeschickt formuliert, aber es "dürfte" inetwa so funktionieren.
        void draw_Object(); //Zeichnet das Objekt und zusätzlich ruft die Funktion noch den Funktionspointer auf für Veränderungen an der Orientierung und der Position des Objektes.
};

double DeadMapObject::extract_MeshXPos() {
    ///MeshMan->get_Mesh(ID);
    //usw. usf.
}
orientation DeadMapObject::extract_MeshOrientation() {
    //orientation *Neue = new orientation::N;
    return ((orientation)0); //0 für N
    //usw. usf.
}

class Map {
};


sf::Clock *Clock;
//Zur Rotation der Szene
void roate_Cube() {
    glRotatef(Clock->GetElapsedTime() * 50, 1.f, 0.f, 0.f);
    glRotatef(Clock->GetElapsedTime() * 30, 0.f, 1.f, 0.f);
    glRotatef(Clock->GetElapsedTime() * 90, 0.f, 0.f, 1.f);
}

//Erzeugt einfach so ein CubeMesh, das auch angezeigt werden kann.
void create_CubeMesh() {
    NeuesMesh = new s_Mesh();
    DEBUG_FOUT << "[Start]" << std::endl;
    NeuesMesh->createAndAddPoint(-50.f, -50.f, -50.f);
    NeuesMesh->createAndAddPoint(-50.f,  50.f, -50.f);
    NeuesMesh->createAndAddPoint( 50.f,  50.f, -50.f);
    NeuesMesh->createAndAddPoint( 50.f, -50.f, -50.f);

    NeuesMesh->createAndAddPoint(-50.f, -50.f, 50.f);
    NeuesMesh->createAndAddPoint(-50.f,  50.f, 50.f);
    NeuesMesh->createAndAddPoint( 50.f,  50.f, 50.f);
    NeuesMesh->createAndAddPoint( 50.f, -50.f, 50.f);

    NeuesMesh->createAndAddPoint(-50.f, -50.f, -50.f);
    NeuesMesh->createAndAddPoint(-50.f,  50.f, -50.f);
    NeuesMesh->createAndAddPoint(-50.f,  50.f,  50.f);
    NeuesMesh->createAndAddPoint(-50.f, -50.f,  50.f);

    NeuesMesh->createAndAddPoint(50.f, -50.f, -50.f);
    NeuesMesh->createAndAddPoint(50.f,  50.f, -50.f);
    NeuesMesh->createAndAddPoint(50.f,  50.f,  50.f);
    NeuesMesh->createAndAddPoint(50.f, -50.f,  50.f);

    NeuesMesh->createAndAddPoint(-50.f, -50.f,  50.f);
    NeuesMesh->createAndAddPoint(-50.f, -50.f, -50.f);
    NeuesMesh->createAndAddPoint( 50.f, -50.f, -50.f);
    NeuesMesh->createAndAddPoint( 50.f, -50.f,  50.f);

    NeuesMesh->createAndAddPoint(-50.f, 50.f,  50.f);
    NeuesMesh->createAndAddPoint(-50.f, 50.f, -50.f);
    NeuesMesh->createAndAddPoint( 50.f, 50.f, -50.f);
    NeuesMesh->createAndAddPoint( 50.f, 50.f,  50.f);
}
//Erstellt aus vorher geladenem Mesh einen Kubus
void draw_CubeMesh() {
    roate_Cube();
    NeuesMesh->Render();
}

//Standartfunktion zum Zeichnen eines Kubus
void draw_Cube() {
    roate_Cube();
    // Draw a cube
    glBegin(GL_QUADS);

        glVertex3f(-50.f, -50.f, -50.f);
        glVertex3f(-50.f,  50.f, -50.f);
        glVertex3f( 50.f,  50.f, -50.f);
        glVertex3f( 50.f, -50.f, -50.f);

        glVertex3f(-50.f, -50.f, 50.f);
        glVertex3f(-50.f,  50.f, 50.f);
        glVertex3f( 50.f,  50.f, 50.f);
        glVertex3f( 50.f, -50.f, 50.f);

        glVertex3f(-50.f, -50.f, -50.f);
        glVertex3f(-50.f,  50.f, -50.f);
        glVertex3f(-50.f,  50.f,  50.f);
        glVertex3f(-50.f, -50.f,  50.f);

        glVertex3f(50.f, -50.f, -50.f);
        glVertex3f(50.f,  50.f, -50.f);
        glVertex3f(50.f,  50.f,  50.f);
        glVertex3f(50.f, -50.f,  50.f);

        glVertex3f(-50.f, -50.f,  50.f);
        glVertex3f(-50.f, -50.f, -50.f);
        glVertex3f( 50.f, -50.f, -50.f);
        glVertex3f( 50.f, -50.f,  50.f);

        glVertex3f(-50.f, 50.f,  50.f);
        glVertex3f(-50.f, 50.f, -50.f);
        glVertex3f( 50.f, 50.f, -50.f);
        glVertex3f( 50.f, 50.f,  50.f);

    glEnd();
}

int main() {

    // Create the main window
    sf::Window App(sf::VideoMode(800, 600, 32), "Testumgebung");

    // Create a clock for measuring time elapsed
    Clock= new sf::Clock;

    // Set color and depth clear value
    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);

    create_CubeMesh();
    ///MeshMan->load_Mesh("Cubetest.HQ2[lvl]");
    MeshMan->load_Mesh("Test.HQ2[lvl]");

    // Start game loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();

            // Escape key : exit
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
                App.Close();

            // Resize event : adjust viewport
            if (Event.Type == sf::Event::Resized)
                glViewport(0, 0, Event.Size.Width, Event.Size.Height);
        }

        // Set the active window before using OpenGL commands
        // It's useless here because active window is always the same,
        // but don't forget it if you use multiple windows or controls
        App.SetActive();


        // Clear color and depth buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Apply some transformations
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.f, 0.f, -200.f);

        ///draw_Cube();
        draw_CubeMesh();
        // Finally, display rendered frame on screen
        App.Display();
    }

    return EXIT_SUCCESS;
}


Ich verwende den GCC mit Code::Blocks unter Windows XP (Servicvepack 2 wenn mich nicht alles täuscht).


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Apr 04, 2010 16:30 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
*Hust, es ist ratsam pro Klasse eine Header-Datei und eine Cpp-Datei zu haben. Nur bei ganz einfachen Klassen oder Klassen die extrem eng zusammen arbeiten kannst du mehrere in einem zusammenfassen.

Die globale Variable MeshMan wird niemals initialisiert, wenn ich das richtig überblicke. Deine load_Mesh-Methode funktioniert genau so lange bis du den "this"-Pointer auf die Objektinstanz benötigst....das Attribut Meshes wird niemals erzeugt. Deine "Normalen Funktionsaufrufe" werden vom Compiler wegoptimiert, da sie das Objekt Meshes nicht verändern (Die Methoden sind in std::vector sicherlich als const markiert).

Genau aus diesem Grunde verwendet man für solche Dinge das oben erwähnte Singleton-Pattern. Dort wird sichergestellt das der Konstruktor genau einmal ausgeführt wird. So ein Singleton könnte z.B. wie folgt aussehen:

Code:
// ==== MySingleton.h ========================================
#ifndef MYSINGLETON_H
#define MYSINGLETON_H

class MySingleton
{
public:
   static inline MySingleton* instance() {
      if (!m_instance) {
         m_instance = new MySingleton();
      }
      return m_instance;
   }   
private:
   MySingleton();
   ~MySingleton();
   
   static MySingleton* m_instance;
};

#endif

// ==== MySingleton.cpp ========================================
MySingleton* MySingleton::m_instance = NULL;

MySingleton::MySingleton() {
   // Singleton sauber initialisieren
}

MySingleton::~MySingleton() {
   /* Achtung: Wird niemals aufgerufen!
      Speicher wird beim beenden des Programms aber sowieso komplett freigegeben.
      Aufpassen aber bei externen Dingen wie Dateien oder Datenbankverbindungen. */
}


Benutzen würdest du das so:
Code:
MySingleton::instance()->methode(a,b,c);

Wenn du mehrere Methoden hinter einander aufrufst kann es natürlich Sinn machen sich lokal (oder als Klassenattribut) einen Pointer anzulegen:
Code:
MySingleton* mys = MySingleton::instance();
mys->methode(a,b,c);
mys->methode2(a,b,c);
mys->methode3(a,b,c);
mys->methode4(a,b,c);

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 15 Queries | GZIP : On ]