Дерево як масив звучить для мене як виграш. Просто пройдіть першу глибину вашої ієрархії та заповніть масив; під час перемотування через рекурсію ви можете або оновити батьківський з абсолютним індексом для дитини, або просто дельта-від-мене, і діти також можуть зберігати батьківські індекси. Дійсно, якщо ви використовуєте відносні компенсації, вам не потрібно носити кореневу адресу навколо. Я гадаю, що структура, мабуть, виглядала б приблизно
struct Transform
{
Matrix m; // whatever you like
int parent; // index or offset, you choose!
int sibling;
int firstchild;
};
... тож вам знадобляться вузли, щоб знати, як потрапити до братів і сестер, оскільки ви не можете (легко) мати структуру змінних розмірів. Хоча я здогадуюсь, якщо ви використовували байтове зміщення замість зсуву "Трансформація", ви могли мати змінну кількість дітей за перетворення:
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
};
... тоді вам просто потрібно переконатися, що ви поставите послідовні перетворення в потрібне місце.
Ось як ви будуєте цілком автономне дерево із вбудованими дочірніми «покажчиками».
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);
}
(Якщо ви хочете зберігати відносні місця, просто додайте - currentLocation
до двох записів "location".)