답변:
배열로서의 나무는 나에게 승리처럼 들린다. 계층의 깊이 우선 탐색을 수행하고 배열을 채우십시오. 재귀를 되감기 할 때 절대 인덱스를 사용하여 부모를 자식이나 delta-from-me로 업데이트하고 자식은 부모 인덱스를 어느 쪽이든 저장할 수 있습니다. 실제로 상대 오프셋을 사용하는 경우 루트 주소를 옮길 필요가 없습니다. 나는 아마도 구조가 다음과 같이 보일 것이라고 생각합니다
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
하려면 두 개의 "위치"쓰기에 추가하십시오 .)
행렬 배열로 인덱싱하는 것은 아마도 가장 간단하고 메모리 효율적인 방법 일 것입니다.
일련의 포인터 또는 정수 또는 행렬 배열로 색인되는 다른 작은 구조체로 LIFO에 변환 체인을 보유 할 수 있습니다. 이를 통해 중복 매트릭스 저장을 방지하고 데이터 액세스 코드와 데이터 스토리지 코드를 분리 할 수 있습니다.
궁극적으로 LIFO에서 인덱스 값을 푸시 앤 팝하여 변환 체인을 저장하거나 재생할 수 있습니다.
행렬 구조에 변환 유형 ... 회전, 변환 등이 포함될 수있는 경우 약간의 메모리를 절약 할 수도 있습니다. 그렇지 않으면 유형이 색인과 함께 저장되어 중복 가능성이 높아집니다.