Browse Source

Scene: Some more serializer code

Panagiotis Christopoulos Charitos 3 days ago
parent
commit
c14b555a07

+ 34 - 1
AnKi/Scene/SceneGraph.cpp

@@ -467,7 +467,7 @@ void SceneGraph::updateNode(U32 tid, SceneNode& node, UpdateSceneNodesCtx& ctx)
 	// Update children
 	node.visitChildrenMaxDepth(0, [&](SceneNode& child) {
 		updateNode(tid, child, ctx);
-		return true;
+		return FunctorContinue::kContinue;
 	});
 
 	ctx.m_perThread[tid].m_sceneMin = ctx.m_perThread[tid].m_sceneMin.min(componentUpdateInfo.m_sceneMin);
@@ -585,6 +585,39 @@ Error SceneGraph::saveToTextFile(CString filename)
 	}
 #include <AnKi/Scene/Components/SceneComponentClasses.def.h>
 
+	// Scene nodes
+	Error err = Error::kNone;
+
+	visitNodes([&](SceneNode& node) {
+		if(node.getParent() != nullptr)
+		{
+			// Skip non-root nodes
+			return FunctorContinue::kContinue;
+		}
+
+		node.visitThisAndChildren([&](SceneNode& node) {
+			err = node.serializeCommon(serializer);
+			if(err)
+			{
+				return FunctorContinue::kStop;
+			}
+
+			return FunctorContinue::kContinue;
+		});
+
+		if(err)
+		{
+			return FunctorContinue::kStop;
+		}
+
+		return FunctorContinue::kContinue;
+	});
+
+	if(err)
+	{
+		return err;
+	}
+
 	return Error::kNone;
 }
 

+ 50 - 2
AnKi/Scene/SceneNode.cpp

@@ -83,7 +83,7 @@ void SceneNode::markForDeletion()
 {
 	visitThisAndChildren([](SceneNode& obj) {
 		obj.m_markedForDeletion = true;
-		return true;
+		return FunctorContinue::kContinue;
 	});
 }
 
@@ -152,7 +152,7 @@ Bool SceneNode::updateTransform()
 			{
 				childNode.m_localTransformDirty = true;
 			}
-			return true;
+			return FunctorContinue::kContinue;
 		});
 	}
 
@@ -166,4 +166,52 @@ void SceneNode::setName(CString name)
 	SceneGraph::getSingleton().sceneNodeChangedName(*this, oldName);
 }
 
+Error SceneNode::serializeCommon(SceneSerializer& serializer)
+{
+	ANKI_SERIALIZE(m_uuid, 1);
+	ANKI_SERIALIZE(m_name, 1);
+
+	Vec3 origin = m_ltrf.getOrigin().xyz();
+	ANKI_SERIALIZE(origin, 1);
+	m_ltrf.setOrigin(origin);
+
+	Mat3 rotation = m_ltrf.getRotation().getRotationPart();
+	ANKI_SERIALIZE(rotation, 1);
+	m_ltrf.setRotation(rotation);
+
+	Vec3 scale = m_ltrf.getScale().xyz();
+	ANKI_SERIALIZE(scale, 1);
+	m_ltrf.setScale(scale);
+
+	U32 componentCount = m_components.getSize();
+	ANKI_SERIALIZE(componentCount, 1);
+
+	SceneDynamicArray<U32> componentUuids;
+	if(serializer.isInWriteMode())
+	{
+		for(SceneComponent* comp : m_components)
+		{
+			componentUuids.emplaceBack(comp->getUuid());
+		}
+	}
+	else
+	{
+		ANKI_ASSERT(!"TODO");
+	}
+
+	ANKI_SERIALIZE(componentUuids, 1);
+
+	// Parent
+	SceneNode* parent = getParent();
+	U32 parentUuid = (parent) ? parent->getUuid() : 0;
+	ANKI_SERIALIZE(parentUuid, 1);
+
+	if(serializer.isInReadMode())
+	{
+		ANKI_ASSERT(!"TODO");
+	}
+
+	return Error::kNone;
+}
+
 } // end namespace anki

+ 37 - 37
AnKi/Scene/SceneNode.h

@@ -14,24 +14,22 @@
 
 namespace anki {
 
-/// @addtogroup scene
-/// @{
-
-/// Interface class backbone of scene
+// Base class of the scene
 class SceneNode : public SceneHierarchy<SceneNode>, public IntrusiveListEnabled<SceneNode>
 {
 	friend class SceneComponent;
+	friend class SceneGraph;
 
 public:
 	using Base = SceneHierarchy<SceneNode>;
 
-	/// The one and only constructor.
-	/// @param name The unique name of the node. If it's empty the the node is not searchable.
+	// The one and only constructor.
+	// name: The unique name of the node. If it's empty the the node is not searchable.
 	SceneNode(CString name);
 
 	virtual ~SceneNode();
 
-	/// Return the name. It may be empty for nodes that we don't want to track.
+	// Return the name. It may be empty for nodes that we don't want to track.
 	CString getName() const
 	{
 		return (!m_name.isEmpty()) ? m_name.toCString() : "Unnamed";
@@ -72,14 +70,20 @@ public:
 		Base::setParent(obj);
 	}
 
-	/// This is called by the scenegraph every frame after all component updates. By default it does nothing.
-	/// @param prevUpdateTime Timestamp of the previous update
-	/// @param crntTime Timestamp of this update
+	// This is called by the scenegraph every frame after all component updates. By default it does nothing.
+	// prevUpdateTime: Timestamp of the previous update
+	// crntTime: Timestamp of this update
 	virtual void frameUpdate([[maybe_unused]] Second prevUpdateTime, [[maybe_unused]] Second crntTime)
 	{
 	}
 
-	/// Iterate all components.
+	// Extra serialization for the derived classes
+	virtual Error serialize([[maybe_unused]] SceneSerializer& serializer)
+	{
+		return Error::kNone;
+	}
+
+	// Iterate all components.
 	template<typename TFunct>
 	void iterateComponents(TFunct func) const
 	{
@@ -89,7 +93,7 @@ public:
 		}
 	}
 
-	/// Iterate all components.
+	// Iterate all components.
 	template<typename TFunct>
 	void iterateComponents(TFunct func)
 	{
@@ -99,7 +103,7 @@ public:
 		}
 	}
 
-	/// Iterate all components of a specific type
+	// Iterate all components of a specific type
 	template<typename TComponent, typename TFunct>
 	void iterateComponentsOfType(TFunct func) const
 	{
@@ -115,7 +119,7 @@ public:
 		}
 	}
 
-	/// Iterate all components of a specific type
+	// Iterate all components of a specific type
 	template<typename TComponent, typename TFunct>
 	void iterateComponentsOfType(TFunct func)
 	{
@@ -131,7 +135,7 @@ public:
 		}
 	}
 
-	/// Try geting a pointer to the first component of the requested type
+	// Try geting a pointer to the first component of the requested type
 	template<typename TComponent>
 	const TComponent* tryGetFirstComponentOfType() const
 	{
@@ -148,7 +152,7 @@ public:
 		return nullptr;
 	}
 
-	/// Try geting a pointer to the first component of the requested type
+	// Try geting a pointer to the first component of the requested type
 	template<typename TComponent>
 	TComponent* tryGetFirstComponentOfType()
 	{
@@ -156,7 +160,7 @@ public:
 		return const_cast<TComponent*>(c);
 	}
 
-	/// Get a pointer to the first component of the requested type
+	// Get a pointer to the first component of the requested type
 	template<typename TComponent>
 	const TComponent& getFirstComponentOfType() const
 	{
@@ -165,7 +169,7 @@ public:
 		return *out;
 	}
 
-	/// Get a pointer to the first component of the requested type
+	// Get a pointer to the first component of the requested type
 	template<typename TComponent>
 	TComponent& getFirstComponentOfType()
 	{
@@ -173,7 +177,7 @@ public:
 		return const_cast<TComponent&>(c);
 	}
 
-	/// Try geting a pointer to the nth component of the requested type.
+	// Try geting a pointer to the nth component of the requested type.
 	template<typename TComponent>
 	const TComponent* tryGetNthComponentOfType(U32 nth) const
 	{
@@ -191,7 +195,7 @@ public:
 		return nullptr;
 	}
 
-	/// Try geting a pointer to the nth component of the requested type.
+	// Try geting a pointer to the nth component of the requested type.
 	template<typename TComponent>
 	TComponent* tryGetNthComponentOfType(U32 nth)
 	{
@@ -215,7 +219,7 @@ public:
 		return *out;
 	}
 
-	/// Get the nth component.
+	// Get the nth component.
 	template<typename TComponent>
 	TComponent& getComponentAt(U32 idx)
 	{
@@ -224,7 +228,7 @@ public:
 		return *static_cast<TComponent*>(c);
 	}
 
-	/// Get the nth component.
+	// Get the nth component.
 	template<typename TComponent>
 	const TComponent& getComponentAt(U32 idx) const
 	{
@@ -248,7 +252,7 @@ public:
 		return count;
 	}
 
-	/// Create and append a component to the components container. The SceneNode has the ownership.
+	// Create and append a component to the components container. The SceneNode has the ownership.
 	template<typename TComponent>
 	TComponent* newComponent();
 
@@ -263,10 +267,9 @@ public:
 		return m_componentTypeMask;
 	}
 
-	/// @name Movement
-	/// @{
+	// Movement methods //
 
-	/// Ignore parent nodes's transform.
+	// Ignore parent nodes's transform.
 	void setIgnoreParentTransform(Bool ignore)
 	{
 		m_ignoreParentNodeTransform = ignore;
@@ -395,10 +398,11 @@ public:
 	{
 		return m_localTransformDirty;
 	}
-	/// @}
+
+	// End movement methods //
 
 private:
-	SceneString m_name; ///< A unique name.
+	SceneString m_name; // A unique name.
 	U32 m_uuid;
 
 	SceneComponentTypeMask m_componentTypeMask = SceneComponentTypeMask::kNone;
@@ -407,14 +411,9 @@ private:
 
 	Timestamp m_maxComponentTimestamp = 0;
 
-	/// The transformation in local space.
-	Transform m_ltrf = Transform::getIdentity();
-
-	/// The transformation in world space (local combined with parent's transformation).
-	Transform m_wtrf = Transform::getIdentity();
-
-	/// Keep the previous transformation for checking if it moved.
-	Transform m_prevWTrf = Transform::getIdentity();
+	Transform m_ltrf = Transform::getIdentity(); // The transformation in local space
+	Transform m_wtrf = Transform::getIdentity(); // The transformation in world space (local combined with parent's transformation)
+	Transform m_prevWTrf = Transform::getIdentity(); // Keep the previous transformation for checking if it moved
 
 	// Flags
 	Bool m_markedForDeletion : 1 = false;
@@ -423,7 +422,8 @@ private:
 	Bool m_transformUpdatedThisFrame : 1 = true;
 
 	void newComponentInternal(SceneComponent* newc);
+
+	Error serializeCommon(SceneSerializer& serializer);
 };
-/// @}
 
 } // end namespace anki

+ 37 - 0
AnKi/Scene/SceneSerializer.cpp

@@ -0,0 +1,37 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Scene/SceneSerializer.h>
+
+namespace anki {
+
+Error SceneSerializer::write(CString name, ConstWeakArray<F64> values)
+{
+	Array<F32, 32> tmpArray;
+	WeakArray<F32> arr;
+	if(values.getSize() < tmpArray.getSize())
+	{
+		arr = {tmpArray.getBegin(), values.getSize()};
+	}
+	else
+	{
+		ANKI_ASSERT(!"TODO");
+	}
+
+	for(U32 i = 0; i < values.getSize(); ++i)
+	{
+		arr[i] = F32(values[i]);
+	}
+
+	return write(name, arr);
+}
+
+Error SceneSerializer::read([[maybe_unused]] CString name, [[maybe_unused]] WeakArray<F64> values)
+{
+	ANKI_ASSERT(!"TODO");
+	return Error::kNone;
+}
+
+} // end namespace anki

+ 16 - 28
AnKi/Scene/SceneSerializer.h

@@ -48,12 +48,12 @@ public:
 	virtual Error write(CString name, ConstWeakArray<F32> values) = 0;
 	virtual Error read(CString name, WeakArray<F32> values) = 0;
 
+	Error write(CString name, ConstWeakArray<F64> values);
+	Error read(CString name, WeakArray<F64> values);
+
 	virtual Error write(CString name, CString value) = 0;
 	virtual Error read(CString name, SceneString& value) = 0;
 
-	virtual Error write(CString name, ConstWeakArray<U8> byteArray) = 0;
-	virtual Error read(CString name, SceneDynamicArray<U8>& byteArray, U32& arraySize) = 0;
-
 	// For resources
 	template<typename T>
 	Error serialize(String varName, U32 varVersion, Bool varDeprecated, ResourcePtr<T>& rsrc)
@@ -83,14 +83,12 @@ public:
 		return serializeInternal(varName, varVersion, varDeprecated, arr);
 	}
 
-	// For regular arithmetic
-	Error serialize(String varName, U32 varVersion, Bool varDeprecated, F64& varValue)
+	// SceneDynamicArray of numbers
+	template<typename T>
+	Error serialize(String varName, U32 varVersion, Bool varDeprecated, SceneDynamicArray<T>& array) requires(std::is_arithmetic_v<T>)
 	{
-		F32 val = F32(varValue);
-		WeakArray<F32> arr(&val, 1);
-		ANKI_CHECK(serializeInternal(varName, varVersion, varDeprecated, arr));
-		varValue = val;
-		return Error::kNone;
+		WeakArray<T> arr(array);
+		return serializeInternal(varName, varVersion, varDeprecated, arr);
 	}
 
 	// Vector 3
@@ -109,6 +107,14 @@ public:
 		return serializeInternal(varName, varVersion, varDeprecated, arr);
 	}
 
+	// Mat
+	template<typename T, U kTRowCount, U kTColumnCount>
+	Error serialize(String varName, U32 varVersion, Bool varDeprecated, TMat<T, kTRowCount, kTColumnCount>& varValue)
+	{
+		WeakArray<T> arr(&varValue[0], kTRowCount * kTColumnCount);
+		return serializeInternal(varName, varVersion, varDeprecated, arr);
+	}
+
 	// Enums
 	template<typename T>
 	Error serialize(String varName, U32 varVersion, Bool varDeprecated, T& varValue) requires(std::is_enum_v<T>)
@@ -264,24 +270,6 @@ public:
 		return Error::kNone;
 	}
 
-	Error write(CString name, ConstWeakArray<U8> byteArray) final
-	{
-		ANKI_CHECK(m_file.writeTextf("%s %u ", name.cstr(), byteArray.getSize()));
-
-		for(U32 i = 0; i < byteArray.getSize(); ++i)
-		{
-			ANKI_CHECK(m_file.writeTextf((i < byteArray.getSize() - 1) ? "%u " : "%u\n", byteArray[i]));
-		}
-
-		return Error::kNone;
-	}
-
-	Error read([[maybe_unused]] CString name, [[maybe_unused]] SceneDynamicArray<U8>& byteArray, [[maybe_unused]] U32& arraySize) final
-	{
-		ANKI_ASSERT(!"TODO");
-		return Error::kNone;
-	}
-
 private:
 	File& m_file;
 };

+ 2 - 2
AnKi/Util/Hierarchy.h

@@ -96,7 +96,7 @@ public:
 
 	/// Visit the children and the children's children. Use it with lambda
 	template<typename TVisitorFunc>
-	Bool visitChildren(TVisitorFunc vis);
+	FunctorContinue visitChildren(TVisitorFunc vis);
 
 	/// Visit this object and move to the children. Use it with lambda
 	template<typename TVisitorFunc>
@@ -108,7 +108,7 @@ public:
 
 	/// Visit the children and limit the depth. Use it with lambda.
 	template<typename TVisitorFunc>
-	Bool visitChildrenMaxDepth(I maxDepth, TVisitorFunc vis);
+	FunctorContinue visitChildrenMaxDepth(I maxDepth, TVisitorFunc vis);
 
 private:
 	Value* m_parent = nullptr; ///< May be nullptr

+ 16 - 16
AnKi/Util/Hierarchy.inl.h

@@ -55,30 +55,30 @@ void Hierarchy<T, TMemoryPool>::removeChild(Value* child)
 
 template<typename T, typename TMemoryPool>
 template<typename TVisitorFunc>
-Bool Hierarchy<T, TMemoryPool>::visitChildren(TVisitorFunc vis)
+FunctorContinue Hierarchy<T, TMemoryPool>::visitChildren(TVisitorFunc vis)
 {
 	auto it = m_children.getBegin();
-	Bool continue_ = true;
-	for(; it != m_children.getEnd() && continue_; it++)
+	FunctorContinue cont = FunctorContinue::kContinue;
+	for(; it != m_children.getEnd() && cont == FunctorContinue::kContinue; it++)
 	{
-		continue_ = vis(*(*it));
+		cont = vis(*(*it));
 
-		if(continue_)
+		if(cont == FunctorContinue::kContinue)
 		{
-			continue_ = (*it)->visitChildren(vis);
+			cont = (*it)->visitChildren(vis);
 		}
 	}
 
-	return continue_;
+	return cont;
 }
 
 template<typename T, typename TMemoryPool>
 template<typename TVisitorFunc>
 void Hierarchy<T, TMemoryPool>::visitThisAndChildren(TVisitorFunc vis)
 {
-	const Bool continue_ = vis(*getSelf());
+	const FunctorContinue cont = vis(*getSelf());
 
-	if(continue_)
+	if(cont == FunctorContinue::kContinue)
 	{
 		visitChildren(vis);
 	}
@@ -100,24 +100,24 @@ void Hierarchy<T, TMemoryPool>::visitTree(TVisitorFunc vis)
 
 template<typename T, typename TMemoryPool>
 template<typename TVisitorFunc>
-Bool Hierarchy<T, TMemoryPool>::visitChildrenMaxDepth(I maxDepth, TVisitorFunc vis)
+FunctorContinue Hierarchy<T, TMemoryPool>::visitChildrenMaxDepth(I maxDepth, TVisitorFunc vis)
 {
 	ANKI_ASSERT(maxDepth >= 0);
 	--maxDepth;
 
-	Bool continue_ = true;
+	FunctorContinue cont = FunctorContinue::kContinue;
 	auto it = m_children.getBegin();
-	for(; it != m_children.getEnd() && continue_; ++it)
+	for(; it != m_children.getEnd() && cont == FunctorContinue::kContinue; ++it)
 	{
-		continue_ = vis(*(*it));
+		cont = vis(*(*it));
 
-		if(continue_ && maxDepth >= 0)
+		if(cont == FunctorContinue::kContinue && maxDepth >= 0)
 		{
-			continue_ = (*it)->visitChildrenMaxDepth(maxDepth, vis);
+			cont = (*it)->visitChildrenMaxDepth(maxDepth, vis);
 		}
 	}
 
-	return continue_;
+	return cont;
 }
 
 } // end namespace anki