#include "M3Datei.h" #include "Datei.h" #include "GraphicsApi.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(Bone* 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->getRotation().x; zDat->schreibe((char*)&f, 4); f = k->getRotation().y; zDat->schreibe((char*)&f, 4); f = k->getRotation().z; zDat->schreibe((char*)&f, 4); saveKnochen(k->zFirstSibling(), zDat); saveKnochen(k->zFirstChild(), zDat); } } Bone* Framework::M3Datei::readKnochen(Datei* zDat) const { bool c; zDat->lese((char*)&c, 1); if (c) { int id; zDat->lese((char*)&id, 4); Bone* k = new Bone(id); Vec3 pos; zDat->lese((char*)&pos.x, 4); zDat->lese((char*)&pos.y, 4); zDat->lese((char*)&pos.z, 4); k->setPosition(pos); Vec3 rot; zDat->lese((char*)&rot.x, 4); zDat->lese((char*)&rot.y, 4); zDat->lese((char*)&rot.z, 4); k->setRotation(rot); k->addSiblingBone(readKnochen(zDat)); k->addChildBone(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(); 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); Skeleton* skelet = zMdr->copySkelett(); if (skelet) { bool b = 1; neu.schreibe((char*)&b, 1); int nId = skelet->getNextBoneId(); neu.schreibe((char*)&nId, 4); saveKnochen(skelet->zRootBone(), &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; } else { removedLength = d.getSize() - removedPosition; } } } 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, GraphicsApi* zApi, Text* uniqueName) const { Model3DData* d = ladeModel(name->getText(), zApi, uniqueName->getText()); name->release(); uniqueName->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, GraphicsApi* zApi, const char* uniqueName) const { if (!modelName || !pfad.getLength()) return 0; __int64 pos = -1; auto p = modelPos->begin(); for (auto n = modelName->begin(); 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 = zApi->createModel(uniqueName); 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) { Skeleton* s = new Skeleton(); int nId; d.lese((char*)&nId, 4); s->nextId = nId; s->rootBone = 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->begin(); 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); }