#include "M3Datei.h" #include "Datei.h" #include "Model3D.h" using namespace Framework; // Inhalt der M3Datei Klasse // Konstruktor M3Datei::M3Datei() : ReferenceCounter() { 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 = ( RCArray* )modelName->release(); if( modelPos ) modelPos = ( Array<__int64>* )modelPos->release(); } // Ließt grundlegende Informationen aus der Datei, die für ihre Verwendung benötigt werden void M3Datei::leseDaten() { if( modelName ) modelName = ( RCArray* )modelName->release(); if( modelPos ) modelPos = ( Array<__int64>* )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 ); 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 ) { if( !modelName || !pfad.getLength() ) return 0; if( !hatModel( name ) ) return 0; Datei d; d.setDatei( pfad ); if( !d.open( Datei::Style::lesen ) ) return 0; __int64 startPosition = modelPos->get( 0 ); Datei neu; neu.setDatei( pfad ); neu.zPfad()->append( "0" ); while( neu.existiert() ) neu.zPfad()->append( "0" ); if( !neu.open( Datei::Style::schreiben ) ) { d.close(); return 0; } char anz = (char)( modelName->getEintragAnzahl() - 1 ); neu.schreibe( &anz, 1 ); __int64 offset = textLength( name ) + 9; __int64 removedLength = 0; __int64 removedPosition = 0; int removedIndex = 0; for( int i = 0; i < anz + 1; i++ ) { if( !modelName->z( i )->istGleich( name ) ) { char len = (char)modelName->z( i )->getLength(); neu.schreibe( &len, 1 ); neu.schreibe( modelName->z( i )->getText(), len ); modelPos->set( modelPos->get( i ) - offset, i ); __int64 pos = modelPos->get( i ); neu.schreibe( (char *)&pos, 8 ); } else { removedPosition = modelPos->get( i ); removedIndex = i; if( modelName->getEintragAnzahl() > i + 1 ) { removedLength = modelPos->get( i + 1 ) - modelPos->get( i ); offset += removedLength; } } } d.setLPosition( startPosition, 0 ); __int64 dl = removedPosition - startPosition; char bytes[ 2048 ]; while( dl ) { int l = dl > 2048 ? 2048 : (int)dl; d.lese( bytes, l ); neu.schreibe( bytes, l ); dl -= l; } d.setLPosition( removedPosition + removedLength, 0 ); dl = d.getSize() - removedPosition - removedLength; while( dl ) { int l = dl > 2048 ? 2048 : (int)dl; d.lese( bytes, l ); neu.schreibe( bytes, l ); dl -= l; } d.close(); d.remove(); neu.close(); neu.umbenennen( pfad ); modelName->remove( removedIndex ); modelPos->remove( removedIndex ); return 1; } // 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 { if( !modelName || !pfad.getLength() ) return 0; __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, p->indexAnz * 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 ); } model->calculateNormals(); 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 { if( !modelName || !pfad.getLength() ) return 0; 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 { if( !modelName || !pfad.getLength() ) return 0; 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 { if( !modelName || !pfad.getLength() ) return 0; return modelName->z( i ); }