#include "M3Datei.h" #include "Datei.h" #include "Model3D.h" using namespace Framework; // Inhalt der M3Datei Klasse // Konstruktor M3Datei::M3Datei() { modelName = 0; modelPos = 0; } // Konstruktor // pfad: Der Pfad zur Datei M3Datei::M3Datei( const char *pfad ) : M3Datei() { this->pfad = pfad; } // Konstruktor // pfad: Der Pfad zur Datei M3Datei::M3Datei( Text *pfad ) : M3Datei( pfad->getText() ) { pfad->release(); } // Destruktor M3Datei::~M3Datei() { if( modelName ) modelName->release(); if( modelPos ) modelPos->release(); } void M3Datei::saveKnochen( Knochen *k, Datei *zDat ) { bool c = k != 0; zDat->schreibe( (char *)& c, 1 ); if( c ) { int id = k->getId(); zDat->schreibe( (char *)& id, 4 ); float f = k->getPosition().x; zDat->schreibe( (char *)& f, 4 ); f = k->getPosition().y; zDat->schreibe( (char *)& f, 4 ); f = k->getPosition().z; zDat->schreibe( (char *)& f, 4 ); f = k->getDrehung().x; zDat->schreibe( (char *)& f, 4 ); f = k->getDrehung().y; zDat->schreibe( (char *)& f, 4 ); f = k->getDrehung().z; zDat->schreibe( (char *)& f, 4 ); saveKnochen( k->zGeschwister(), zDat ); saveKnochen( k->zKind(), zDat ); } } Knochen *Framework::M3Datei::readKnochen( Datei *zDat ) const { bool c; zDat->lese( (char *)& c, 1 ); if( c ) { int id; zDat->lese( (char *)& id, 4 ); Knochen *k = new Knochen( id ); Vec3< float > pos; zDat->lese( (char *)& pos.x, 4 ); zDat->lese( (char *)& pos.y, 4 ); zDat->lese( (char *)& pos.z, 4 ); k->setPosition( pos ); Vec3< float > rot; zDat->lese( (char *)& rot.x, 4 ); zDat->lese( (char *)& rot.y, 4 ); zDat->lese( (char *)& rot.z, 4 ); k->setDrehung( rot ); k->addGeschwisterKnochen( readKnochen( zDat ) ); k->addKind( id, readKnochen( zDat ) ); return k; } return 0; } // Setzt den Pfad zur Datei // pfad: Pfad zur Datei void M3Datei::setPfad( const char *pfad ) { this->pfad = pfad; if( modelName ) modelName = modelName->release(); if( modelPos ) modelPos = modelPos->release(); } // Ließt grundlegende Informationen aus der Datei, die für ihre Verwendung benötigt werden void M3Datei::leseDaten() { if( modelName ) modelName = modelName->release(); if( modelPos ) modelPos = modelPos->release(); modelName = new RCArray< Text >(); modelPos = new Array< __int64 >(); Datei d; d.setDatei( pfad ); if( !d.open( Datei::Style::lesen ) ) return; unsigned char anz = 0; d.lese( (char *)& anz, 1 ); for( int i = 0; i < anz; i++ ) { char len = 0; d.lese( &len, 1 ); char *n = new char[ len + 1 ]; n[ (int)len ] = 0; d.lese( n, len ); modelName->add( new Text( n ) ); delete[] n; __int64 p = 0; d.lese( (char *)& p, 8 ); modelPos->add( p ); } d.close(); } // Speichert 3D Modell Daten in der Datei // zMdr: Ein Zeiger auf die zu speichernden Daten ohne erhöhtem Reference Counter // name: Der Name, unter dem die Daten in der Datei gespeichert werden sollen // return: 1, falls das Modell gespeichert wurde. 0, falls ein fehler beim speichern auftrat bool M3Datei::saveModel( Model3DData *zMdr, Text *name ) { bool ret = saveModel( zMdr, name->getText() ); name->release(); return ret; } // Speichert 3D Modell Daten in der Datei // zMdr: Ein Zeiger auf die zu speichernden Daten ohne erhöhtem Reference Counter // name: Der Name, unter dem die Daten in der Datei gespeichert werden sollen // return: 1, falls das Modell gespeichert wurde. 0, falls ein fehler beim speichern auftrat bool M3Datei::saveModel( Model3DData *zMdr, const char *name ) { if( !modelName || !pfad.getLength() ) return 0; if( hatModel( name ) && !removeModel( name ) ) return 0; int anz = modelName->getEintragAnzahl(); anz = modelName->getEintragAnzahl(); Datei d; d.setDatei( pfad ); d.open( Datei::Style::lesen ); Datei neu; neu.setDatei( pfad ); neu.zPfad()->append( "0" ); while( neu.existiert() ) neu.zPfad()->append( "0" ); if( !neu.open( Datei::Style::schreiben ) ) { if( d.istOffen() ) d.close(); return 0; } modelName->add( new Text( name ) ); int offs = textLength( name ) + 9; for( int i = 0; i < anz; i++ ) modelPos->set( modelPos->get( i ) + offs, i ); if( d.getSize() < 0 ) modelPos->add( offs + 1 ); else modelPos->add( d.getSize() + offs ); anz++; char tmp = (char)anz; neu.schreibe( &tmp, 1 ); for( int i = 0; i < anz; i++ ) { char len = (char)modelName->z( i )->getLength(); neu.schreibe( &len, 1 ); neu.schreibe( modelName->z( i )->getText(), len ); __int64 pos = modelPos->get( i ); neu.schreibe( (char *)& pos, 8 ); } if( d.existiert() ) { d.setLPosition( modelPos->get( 0 ) - offs, 0 ); __int64 dl = d.getSize() - d.getLPosition(); char bytes[ 2048 ]; while( dl ) { int l = dl > 2048 ? 2048 : (int)dl; d.lese( bytes, l ); neu.schreibe( bytes, l ); dl -= l; } } d.close(); int vAnz = zMdr->getVertexAnzahl(); neu.schreibe( (char *)& vAnz, 4 ); for( int i = 0; i < vAnz; i++ ) { neu.schreibe( (char *)& zMdr->zVertexBuffer()[ i ].knochenId, 4 ); neu.schreibe( (char *)& zMdr->zVertexBuffer()[ i ].pos.x, 4 ); neu.schreibe( (char *)& zMdr->zVertexBuffer()[ i ].pos.y, 4 ); neu.schreibe( (char *)& zMdr->zVertexBuffer()[ i ].pos.z, 4 ); neu.schreibe( (char *)& zMdr->zVertexBuffer()[ i ].tPos.x, 4 ); neu.schreibe( (char *)& zMdr->zVertexBuffer()[ i ].tPos.y, 4 ); } int pAnz = zMdr->getPolygonAnzahl(); neu.schreibe( (char *)& pAnz, 4 ); for( int p = 0; p < pAnz; p++ ) { Polygon3D *pol = zMdr->getPolygon( p ); int anz = pol->indexAnz; neu.schreibe( (char *)& anz, 4 ); neu.schreibe( (char *)pol->indexList, anz * 4 ); } float factor = zMdr->getAmbientFactor(); neu.schreibe( (char *)& factor, 4 ); factor = zMdr->getDiffusFactor(); neu.schreibe( (char *)& factor, 4 ); factor = zMdr->getSpecularFactor(); neu.schreibe( (char *)& factor, 4 ); Skelett *skelet = zMdr->copySkelett(); if( skelet ) { bool b = 1; neu.schreibe( (char*)&b, 1 ); int nId = skelet->zNextKnochenId(); neu.schreibe( (char *)& nId, 4 ); saveKnochen( skelet->zKnochen(), &neu ); skelet->release(); } else { bool b = 0; neu.schreibe( (char *)& b, 1 ); } d.remove(); neu.close(); neu.umbenennen( pfad ); leseDaten(); return 1; } // Löscht ein 3D Modell aus der Datei // name: Der Name des Modells // return: 1, wenn das Modell gelöscht wurde. 0, wenn das Modell nicht gefunden wurde, oder ein fehler beim speichern auftrat bool M3Datei::removeModel( Text *name ) { bool res = removeModel( name->getText() ); name->release(); return res; } // Löscht ein 3D Modell aus der Datei // name: Der Name des Modells // return: 1, wenn das Modell gelöscht wurde. 0, wenn das Modell nicht gefunden wurde, oder ein fehler beim speichern auftrat bool M3Datei::removeModel( const char *name ) { // TODO: implement this return 0; } // Lähd ein 3D Modell aus der Datei // name: Der name des zu ladenden Modells // return: Die geladenen Daten Model3DData *M3Datei::ladeModel( Text *name ) const { Model3DData *d = ladeModel( name->getText() ); name->release(); return d; } // Lähd ein 3D Modell aus der Datei // name: Der name des zu ladenden Modells // return: Die geladenen Daten Model3DData *M3Datei::ladeModel( const char *name ) const { __int64 pos = -1; auto p = modelPos->getIterator(); for( auto n = modelName->getIterator(); n && p; n++, p++ ) { if( n->istGleich( name ) ) { pos = p; break; } } if( pos > 0 ) { Datei d; d.setDatei( pfad ); if( !d.open( Datei::Style::lesen ) ) { return 0; } d.setLPosition( pos, 0 ); Model3DData *model = new Model3DData(); int vAnz; d.lese( (char *)& vAnz, 4 ); Vertex3D *vertices = new Vertex3D[ vAnz ]; for( int i = 0; i < vAnz; i++ ) { d.lese( (char *)& vertices[ i ].knochenId, 4 ); d.lese( (char *)& vertices[ i ].pos.x, 4 ); d.lese( (char *)& vertices[ i ].pos.y, 4 ); d.lese( (char *)& vertices[ i ].pos.z, 4 ); d.lese( (char *)& vertices[ i ].tPos.x, 4 ); d.lese( (char *)& vertices[ i ].tPos.y, 4 ); } model->setVertecies( vertices, vAnz ); int pAnz; d.lese( (char *)& pAnz, 4 ); for( int i = 0; i < pAnz; i++ ) { Polygon3D *p = new Polygon3D(); d.lese( (char *)& p->indexAnz, 4 ); p->indexList = new int[ p->indexAnz ]; d.lese( (char *)p->indexList, pAnz * 4 ); model->addPolygon( p ); } float factor; d.lese( (char *)& factor, 4 ); model->setAmbientFactor( factor ); d.lese( (char *)& factor, 4 ); model->setDiffusFactor( factor ); d.lese( (char *)& factor, 4 ); model->setSpecularFactor( factor ); bool b; d.lese( (char *)& b, 1 ); if( b ) { Skelett *s = new Skelett(); int nId; d.lese( (char *)& nId, 4 ); s->setNextKnochenId( nId ); s->addKnochen( readKnochen( &d ) ); model->setSkelettZ( s ); } d.close(); return model; } return 0; } // überprft, ob ein bestimmtes 3D Modell in der Datei existiert // name: Der Name des zu suchenden 3D Modells // return: 1, wenn das Modell gefunden wurde. 0 sonst bool M3Datei::hatModel( const char *name ) const { for( auto n = modelName->getIterator(); n; n++ ) { if( n->istGleich( name ) ) return 1; } return 0; } // ügibt die Anzahl der gespeicherten Modelle zurück int M3Datei::getModelAnzahl() const { return modelName->getEintragAnzahl(); } // Gibt den Namen eines Bestimmten Modells zurück // i: Der Index des Modells // return: Ein Zeiger aud den Namen des Modells ohne erhöhten Reference Counter Text *M3Datei::zModelName( int i ) const { return modelName->z( i ); } // Erhöht den Reference Counting Zähler. // return: this. M3Datei *M3Datei::getThis() { ref++; return this; } // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht. // return: 0. M3Datei *M3Datei::release() { if( !--ref ) delete this; return 0; }