Skip to content

Commit

Permalink
detect cyclic hierarchies
Browse files Browse the repository at this point in the history
  • Loading branch information
nem0 committed Aug 27, 2023
1 parent 756d9b2 commit f967b40
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
52 changes: 46 additions & 6 deletions src/ofbx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,8 @@ struct Scene : IScene
}
}

bool finalize();
Object* findParent(Object& child) const;

Element* m_root_element = nullptr;
Root* m_root = nullptr;
Expand Down Expand Up @@ -4191,15 +4193,14 @@ Object* Object::resolveObjectLink(Object::Type type, const char* property, int i
}


Object* Object::getParent() const
{
Object* Scene::findParent(Object& child) const {
Object* parent = nullptr;
for (auto& connection : scene.m_connections)
for (auto& connection : m_connections)
{
if (connection.from_object == id)
if (connection.from_object == child.id)
{
Object* obj = scene.m_object_map.find(connection.to_object)->second.object;
if (obj && obj->is_node && obj != this && connection.type == Scene::Connection::OBJECT_OBJECT) {
Object* obj = m_object_map.find(connection.to_object)->second.object;
if (obj && obj->is_node && obj != &child && connection.type == Scene::Connection::OBJECT_OBJECT) {
assert(parent == nullptr);
parent = obj;
}
Expand All @@ -4209,6 +4210,44 @@ Object* Object::getParent() const
}


bool Scene::finalize() {
for (Object* object : m_all_objects) {
object->parent = findParent(*object);
}
for (Object* object : m_all_objects) {
if (object->depth != 0xffFFffFF) continue;
if (object->parent == object) {
Error::s_message = "Cyclic node hierarchy";
return false;
}
if (!object->parent) {
object->depth = 0;
continue;
}

object->depth = 0;

Object* parent = object->parent;
while (parent) {
if (parent == object) {
Error::s_message = "Cyclic node hierarchy";
return false;
}
++object->depth;
parent = parent->parent;
}

Object* p = object->parent;
Object* child = object;
while (p) {
p->depth = child->depth - 1;
child = p;
p = p->parent;
}
}
return true;
}

IScene* load(const u8* data, int size, u16 flags, JobProcessor job_processor, void* job_user_ptr)
{
std::unique_ptr<Scene> scene(new Scene());
Expand Down Expand Up @@ -4245,6 +4284,7 @@ IScene* load(const u8* data, int size, u16 flags, JobProcessor job_processor, vo
if (!parseTakes(*scene.get())) return nullptr;
if (!parseObjects(*root.getValue(), *scene.get(), flags, scene->m_allocator, job_processor, job_user_ptr)) return nullptr;
parseGlobalSettings(*root.getValue(), scene.get());
if (!scene->finalize()) return nullptr;

return scene.release();
}
Expand Down
5 changes: 4 additions & 1 deletion src/ofbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ struct Object
Object* resolveObjectLink(int idx) const;
Object* resolveObjectLink(Type type, const char* property, int idx) const;
Object* resolveObjectLinkReverse(Type type) const;
Object* getParent() const;
Object* getParent() const { return parent; }

RotationOrder getRotationOrder() const;
Vec3 getRotationOffset() const;
Expand All @@ -242,11 +242,14 @@ struct Object
}

u64 id;
u32 depth = 0xffFFffFF;
Object* parent = nullptr;
char name[128];
const IElement& element;
const Object* node_attribute;

protected:
friend struct Scene;
bool is_node;
const Scene& scene;
};
Expand Down

0 comments on commit f967b40

Please sign in to comment.