Der Tree-as-Array klingt für mich wie ein Gewinn. Führen Sie einfach eine Tiefenüberquerung Ihrer Hierarchie durch und füllen Sie ein Array aus. Beim Zurückspulen durch die Rekursion können Sie entweder das übergeordnete Element mit dem absoluten Index für das untergeordnete Element oder nur das Delta von mir aktualisieren, und die untergeordneten Indizes können die übergeordneten Indizes auch in beiden Richtungen speichern. Wenn Sie relative Offsets verwenden, müssen Sie die Stammadresse nicht mit sich herumtragen. Ich nehme an, dass die Struktur wahrscheinlich so aussehen würde
struct Transform
{
Matrix m; // whatever you like
int parent; // index or offset, you choose!
int sibling;
int firstchild;
};
... Sie benötigen also Knoten, um zu wissen, wie Sie auch zu Geschwistern gelangen, da Sie (einfach) keine Struktur mit variabler Größe haben können. Obwohl ich denke, wenn Sie Byte-Offsets anstelle von Transformations-Offsets verwenden, können Sie eine variable Anzahl von untergeordneten Elementen pro Transformation haben:
struct Transform
{
Matrix m; // whatever you like
int parent; // negative byte offest
int numchildren;
int child[0]; // can't remember if you put a 0 there or leave it empty;
// but it's an array of positive byte offsets
};
... dann müssen Sie nur noch sicherstellen, dass Sie aufeinanderfolgende Transformationen an der richtigen Stelle platzieren.
Hier erfahren Sie, wie Sie einen völlig eigenständigen Baum mit eingebetteten untergeordneten "Zeigern" erstellen.
int BuildTransforms(Entity* e, OutputStream& os, int parentLocation)
{
int currentLocation = os.Tell();
os.Write(e->localMatrix);
os.Write(parentLocation);
int numChildren = e->GetNumChildren();
os.Write(numChildren);
int childArray = os.Tell();
os.Skip(numChildren * sizeof(int));
os.AlignAsNecessary(); // if you need to align transforms
childLocation = os.Tell();
for (int i = 0; i < numChildren; ++i) {
os.Seek(childArray + (i * sizeof(int)));
os.Write(childLocation);
os.Seek(childLocation);
childLocation = BuildTransforms(e->GetChild(i), os, currentLocation);
}
return os.Tell();
}
void BuildTransforms(Entity* root)
{
OutputStream os;
BuildTransforms(root, os, -1, 0);
}
(Wenn Sie relative Speicherorte speichern möchten, fügen Sie einfach - currentLocation
die beiden "Standort" -Schreibvorgänge hinzu.)
Die Indizierung in ein Array von Matrizen wäre wahrscheinlich der einfachste und speichereffizienteste Ansatz.
Eine Kette von Transformationen könnte in einem LIFO als eine Reihe von Zeigern oder ganzen Zahlen oder einer anderen kleinen Struktur gehalten werden, die in das Matrixarray indiziert. Dies würde dazu beitragen, das Speichern redundanter Matrizen zu verhindern und den Datenspeichercode vom Datenzugriffscode zu trennen.
Letztendlich würden Sie nur Indexwerte aus dem LIFO pushen und einfügen, um Ihre Transformationskette zu speichern oder wiederzugeben.
Möglicherweise können Sie auch ein wenig Speicherplatz sparen, wenn Ihre Matrixstruktur auch den Transformationstyp ... Rotation, Translation usw. enthalten könnte. Andernfalls müsste der Typ mit dem Index gespeichert werden, was zu einer möglichen Duplizierung führen könnte.
quelle