Panagiotis Christopoulos Charitos 14 rokov pred
rodič
commit
ffa438f189

+ 8 - 3
anki/scene/Camera.cpp

@@ -20,7 +20,10 @@ void Camera::lookAtPoint(const Vec3& point)
 	Vec3 vdir = (point - getLocalTransform().getOrigin()).getNormalized();
 	Vec3 vdir = (point - getLocalTransform().getOrigin()).getNormalized();
 	Vec3 vup = j - vdir * j.dot(vdir);
 	Vec3 vup = j - vdir * j.dot(vdir);
 	Vec3 vside = vdir.cross(vup);
 	Vec3 vside = vdir.cross(vup);
-	getLocalTransform().getRotation().setColumns(vside, vup, -vdir);
+
+	Mat3 rot = getLocalTransform().getRotation();
+	rot.setColumns(vside, vup, -vdir);
+	setLocalRotation(rot);
 }
 }
 
 
 
 
@@ -34,7 +37,8 @@ PerspectiveCamera::PerspectiveCamera(const char* name, Scene* scene,
 	: Camera(CT_PERSPECTIVE, name, scene, movableFlags, movParent, &frustum)
 	: Camera(CT_PERSPECTIVE, name, scene, movableFlags, movParent, &frustum)
 {
 {
 	Property<PerspectiveFrustum>& prop =
 	Property<PerspectiveFrustum>& prop =
-		addProperty("frustum", &frustum, PropertyBase::PF_READ_WRITE);
+		addNewProperty(new ReadWritePointerProperty<PerspectiveFrustum>(
+		"frustum", &frustum));
 	ANKI_CONNECT(&prop, valueChanged, this, updateFrustumSlot);
 	ANKI_CONNECT(&prop, valueChanged, this, updateFrustumSlot);
 }
 }
 
 
@@ -49,7 +53,8 @@ OrthographicCamera::OrthographicCamera(const char* name, Scene* scene,
 	: Camera(CT_ORTHOGRAPHIC, name, scene, movableFlags, movParent, &frustum)
 	: Camera(CT_ORTHOGRAPHIC, name, scene, movableFlags, movParent, &frustum)
 {
 {
 	Property<OrthographicFrustum>& prop =
 	Property<OrthographicFrustum>& prop =
-		addProperty("frustum", &frustum, PropertyBase::PF_READ_WRITE);
+		addNewProperty(new ReadWritePointerProperty<OrthographicFrustum>(
+		"frustum", &frustum));
 	ANKI_CONNECT(&prop, valueChanged, this, updateFrustumSlot);
 	ANKI_CONNECT(&prop, valueChanged, this, updateFrustumSlot);
 }
 }
 
 

+ 1 - 1
anki/scene/Camera.h

@@ -87,7 +87,7 @@ public:
 	/// @name Movable virtuals
 	/// @name Movable virtuals
 	/// @{
 	/// @{
 
 
-	/// Re-impements Movable::moveUpdate(). This does:
+	/// Overrides Movable::moveUpdate(). This does:
 	/// - Update view matrix
 	/// - Update view matrix
 	/// - Update frustum
 	/// - Update frustum
 	void moveUpdate()
 	void moveUpdate()

+ 1 - 0
anki/scene/MaterialRuntime.h

@@ -18,6 +18,7 @@ class MaterialVariable;
 
 
 
 
 /// Variable of runtime materials
 /// Variable of runtime materials
+///
 /// This holds a copy of the MaterialVariable's data in order to be read write
 /// This holds a copy of the MaterialVariable's data in order to be read write
 /// inside the main loop
 /// inside the main loop
 class MaterialRuntimeVariable
 class MaterialRuntimeVariable

+ 32 - 16
anki/scene/Movable.cpp

@@ -8,36 +8,52 @@ namespace anki {
 
 
 //==============================================================================
 //==============================================================================
 Movable::Movable(uint flags_, Movable* parent, PropertyMap& pmap)
 Movable::Movable(uint flags_, Movable* parent, PropertyMap& pmap)
-	: Base(this, parent), flags(flags_)
+	: Base(this, parent), shouldUpdateWTrf(true), flags(flags_)
 {
 {
-	pmap.addNewProperty(new ReadWritePointerProperty<Transform>("localTransform", &lTrf));
-	pmap.addNewProperty(new ReadPointerProperty<Transform>("worldTransform", &wTrf));
+	pmap.addNewProperty(
+		new ReadWritePointerProperty<Transform>("localTransform", &lTrf));
+	pmap.addNewProperty(
+		new ReadPointerProperty<Transform>("worldTransform", &wTrf));
 }
 }
 
 
 
 
 //==============================================================================
 //==============================================================================
 void Movable::updateWorldTransform()
 void Movable::updateWorldTransform()
 {
 {
-	prevWTrf = wTrf;
-
-	if(getParent())
+	if(shouldUpdateWTrf)
 	{
 	{
-		if(isFlagEnabled(MF_IGNORE_LOCAL_TRANSFORM))
+		prevWTrf = wTrf;
+
+		if(getParent())
+		{
+			if(isFlagEnabled(MF_IGNORE_LOCAL_TRANSFORM))
+			{
+				wTrf = getParent()->getWorldTransform();
+			}
+			else
+			{
+				wTrf = Transform::combineTransformations(
+					getParent()->getWorldTransform(), lTrf);
+			}
+		}
+		else // else copy
 		{
 		{
-			wTrf = getParent()->getWorldTransform();
+			wTrf = lTrf;
+		}
+
+		// Moved?
+		if(prevWTrf != wTrf)
+		{
+			enableFlag(MF_MOVED);
+			moveUpdate();
 		}
 		}
 		else
 		else
 		{
 		{
-			wTrf = Transform::combineTransformations(
-				getParent()->getWorldTransform(), lTrf);
+			disableFlag(MF_MOVED);
 		}
 		}
-	}
-	else // else copy
-	{
-		wTrf = lTrf;
-	}
 
 
-	enableFlag(MF_MOVED, prevWTrf != wTrf);
+		shouldUpdateWTrf = false;
+	}
 
 
 	BOOST_FOREACH(Movable* child, getChildren())
 	BOOST_FOREACH(Movable* child, getChildren())
 	{
 	{

+ 43 - 6
anki/scene/Movable.h

@@ -15,6 +15,12 @@ class PropertyMap;
 /// @{
 /// @{
 
 
 /// Interface for movable scene nodes
 /// Interface for movable scene nodes
+///
+/// When the local tranform changes we calculate the @a dummyWTrf for this
+/// movable and it's children. The @a dummyWTrf contains the final world
+/// transformation. Why dont we set the @a wTrf at once? Because we the local
+/// transformation may change in the logic part of the main loop and we dont
+/// want
 class Movable: public Object<Movable>
 class Movable: public Object<Movable>
 {
 {
 public:
 public:
@@ -46,6 +52,22 @@ public:
 	void setLocalTransform(const Transform& x)
 	void setLocalTransform(const Transform& x)
 	{
 	{
 		lTrf = x;
 		lTrf = x;
+		shouldUpdateWTrf = true;
+	}
+	void setLocalTranslation(const Vec3& x)
+	{
+		lTrf.setOrigin(x);
+		shouldUpdateWTrf = true;
+	}
+	void setLocalRotation(const Mat3& x)
+	{
+		lTrf.setRotation(x);
+		shouldUpdateWTrf = true;
+	}
+	void setLocalScale(float x)
+	{
+		lTrf.setScale(x);
+		shouldUpdateWTrf = true;
 	}
 	}
 
 
 	const Transform& getWorldTransform() const
 	const Transform& getWorldTransform() const
@@ -85,53 +107,68 @@ public:
 	void rotateLocalX(float angDegrees)
 	void rotateLocalX(float angDegrees)
 	{
 	{
 		lTrf.getRotation().rotateXAxis(angDegrees);
 		lTrf.getRotation().rotateXAxis(angDegrees);
+		shouldUpdateWTrf = true;
 	}
 	}
 	void rotateLocalY(float angDegrees)
 	void rotateLocalY(float angDegrees)
 	{
 	{
 		lTrf.getRotation().rotateYAxis(angDegrees);
 		lTrf.getRotation().rotateYAxis(angDegrees);
+		shouldUpdateWTrf = true;
 	}
 	}
 	void rotateLocalZ(float angDegrees)
 	void rotateLocalZ(float angDegrees)
 	{
 	{
 		lTrf.getRotation().rotateZAxis(angDegrees);
 		lTrf.getRotation().rotateZAxis(angDegrees);
+		shouldUpdateWTrf = true;
 	}
 	}
 	void moveLocalX(float distance)
 	void moveLocalX(float distance)
 	{
 	{
 		Vec3 x_axis = lTrf.getRotation().getColumn(0);
 		Vec3 x_axis = lTrf.getRotation().getColumn(0);
 		lTrf.getOrigin() += x_axis * distance;
 		lTrf.getOrigin() += x_axis * distance;
+		shouldUpdateWTrf = true;
 	}
 	}
 	void moveLocalY(float distance)
 	void moveLocalY(float distance)
 	{
 	{
 		Vec3 y_axis = lTrf.getRotation().getColumn(1);
 		Vec3 y_axis = lTrf.getRotation().getColumn(1);
 		lTrf.getOrigin() += y_axis * distance;
 		lTrf.getOrigin() += y_axis * distance;
+		shouldUpdateWTrf = true;
 	}
 	}
 	void moveLocalZ(float distance)
 	void moveLocalZ(float distance)
 	{
 	{
 		Vec3 z_axis = lTrf.getRotation().getColumn(2);
 		Vec3 z_axis = lTrf.getRotation().getColumn(2);
 		lTrf.getOrigin() += z_axis * distance;
 		lTrf.getOrigin() += z_axis * distance;
+		shouldUpdateWTrf = true;
 	}
 	}
 	/// @}
 	/// @}
 
 
-	/// This is called after the updateWorldTransform() and if the MF_MOVED is
-	/// true
+	/// This is called by the scene's main update method only when the object
+	/// had actually moved
 	virtual void moveUpdate()
 	virtual void moveUpdate()
+	{}
+
+	/// Update self and children world transform, if root node
+	void update()
 	{
 	{
-		ANKI_ASSERT(isFlagEnabled(MF_MOVED));
+		if(getParent() == NULL)
+		{
+			updateWorldTransform();
+		}
 	}
 	}
 
 
 protected:
 protected:
+	bool shouldUpdateWTrf; ///< Its true when we change the local transform
+
 	Transform lTrf; ///< The transformation in local space
 	Transform lTrf; ///< The transformation in local space
 
 
 	/// The transformation in world space (local combined with parent's
 	/// The transformation in world space (local combined with parent's
 	/// transformation)
 	/// transformation)
 	Transform wTrf;
 	Transform wTrf;
 
 
-	/// Keep the previous transformation for blurring calculations
+	/// Keep the previous transformation for checking if it moved
 	Transform prevWTrf;
 	Transform prevWTrf;
 
 
 	ulong flags; ///< The state flags
 	ulong flags; ///< The state flags
 
 
-	/// Called when the local transform changes. Then its called fpr all the
-	/// children. It updates the MF_MOVED flag
+	/// Called for every frame. It updates the @a wTrf if @a shouldUpdateWTrf
+	/// is true. Then it moves to the children.
 	void updateWorldTransform();
 	void updateWorldTransform();
 };
 };
 /// @}
 /// @}

+ 122 - 4
anki/scene/Property.h

@@ -7,6 +7,7 @@
 #include "anki/util/ConstCharPtrHashMap.h"
 #include "anki/util/ConstCharPtrHashMap.h"
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
 
 
 
 
 namespace anki {
 namespace anki {
@@ -18,7 +19,7 @@ class Property;
 
 
 
 
 /// Base class for property
 /// Base class for property
-class PropertyBase
+class PropertyBase: public boost::noncopyable
 {
 {
 public:
 public:
 	/// @name Constructors/Destructor
 	/// @name Constructors/Destructor
@@ -75,7 +76,7 @@ private:
 };
 };
 
 
 
 
-/// Property. It holds a pointer to a value
+/// Property interface
 template<typename T>
 template<typename T>
 class Property: public PropertyBase
 class Property: public PropertyBase
 {
 {
@@ -116,7 +117,74 @@ template<typename T>
 const uint Property<T>::TYPE_ID = 0;
 const uint Property<T>::TYPE_ID = 0;
 
 
 
 
-/// XXX
+/// Read only property
+template<typename T>
+class ReadProperty: public Property<T>
+{
+public:
+	typedef T Value;
+	typedef Property<T> Base;
+
+	/// @name Constructors/Destructor
+	/// @{
+	ReadProperty(const char* name, const Value& x_)
+		: Base(name), x(x_)
+	{}
+	/// @}
+
+	/// @name Accessors
+	/// @{
+
+	/// Overrides Property::getValue()
+	const Value& getValue() const
+	{
+		return x;
+	}
+	/// @}
+
+private:
+	Value x;
+};
+
+
+/// Read write property
+template<typename T>
+class ReadWriteProperty: public Property<T>
+{
+public:
+	typedef T Value;
+	typedef Property<T> Base;
+
+	/// @name Constructors/Destructor
+	/// @{
+	ReadWriteProperty(const char* name, const Value& x_)
+		: Base(name), x(x_)
+	{}
+	/// @}
+
+	/// @name Accessors
+	/// @{
+
+	/// Overrides Property::getValue()
+	const Value& getValue() const
+	{
+		return x;
+	}
+
+	/// Overrides Property::setValue()
+	virtual void setValue(const Value& x_)
+	{
+		x = x_;
+		ANKI_EMIT valueChanged(x);
+	}
+	/// @}
+
+private:
+	Value x;
+};
+
+
+/// Read only property that holds a reference to a value
 template<typename T>
 template<typename T>
 class ReadPointerProperty: public Property<T>
 class ReadPointerProperty: public Property<T>
 {
 {
@@ -124,9 +192,12 @@ public:
 	typedef T Value;
 	typedef T Value;
 	typedef Property<T> Base;
 	typedef Property<T> Base;
 
 
+	/// @name Constructors/Destructor
+	/// @{
 	ReadPointerProperty(const char* name, const Value* x)
 	ReadPointerProperty(const char* name, const Value* x)
 		: Base(name), ptr(x)
 		: Base(name), ptr(x)
 	{}
 	{}
+	/// @}
 
 
 	/// @name Accessors
 	/// @name Accessors
 	/// @{
 	/// @{
@@ -143,7 +214,7 @@ private:
 };
 };
 
 
 
 
-/// XXX
+/// Read write property that alters a reference to the value
 template<typename T>
 template<typename T>
 class ReadWritePointerProperty: public Property<T>
 class ReadWritePointerProperty: public Property<T>
 {
 {
@@ -151,9 +222,12 @@ public:
 	typedef T Value;
 	typedef T Value;
 	typedef Property<T> Base;
 	typedef Property<T> Base;
 
 
+	/// @name Constructors/Destructor
+	/// @{
 	ReadWritePointerProperty(const char* name, Value* x)
 	ReadWritePointerProperty(const char* name, Value* x)
 		: Base(name), ptr(x)
 		: Base(name), ptr(x)
 	{}
 	{}
+	/// @}
 
 
 	/// @name Accessors
 	/// @name Accessors
 	/// @{
 	/// @{
@@ -177,6 +251,50 @@ private:
 };
 };
 
 
 
 
+/// Read and Copy on Write property
+template<typename T>
+class ReadCowPointerProperty: public Property<T>
+{
+public:
+	typedef T Value;
+	typedef Property<T> Base;
+
+	/// @name Constructors/Destructor
+	/// @{
+	ReadCowPointerProperty(const char* name, const Value* x)
+		: Base(name), ptr(x)
+	{}
+	/// @}
+
+	/// @name Accessors
+	/// @{
+	/// Overrides Property::getValue()
+	const Value& getValue() const
+	{
+		return (sptr.get()) ? *sptr : *ptr;
+	}
+
+	/// Overrides Property::setValue()
+	virtual void setValue(const Value& x)
+	{
+		if(sptr.get())
+		{
+			*sptr = x;
+		}
+		else
+		{
+			sptr.reset(new Value(x));
+		}
+		ANKI_EMIT valueChanged(x);
+	}
+	/// @}
+
+private:
+	const Value* ptr;
+	boost::scoped_ptr sptr;
+};
+
+
 /// A set of properties
 /// A set of properties
 class PropertyMap
 class PropertyMap
 {
 {

+ 14 - 0
anki/scene/SceneNode.cpp

@@ -1,5 +1,6 @@
 #include "anki/scene/SceneNode.h"
 #include "anki/scene/SceneNode.h"
 #include "anki/scene/Scene.h"
 #include "anki/scene/Scene.h"
+#include "anki/scene/Movable.h"
 
 
 
 
 namespace anki {
 namespace anki {
@@ -22,4 +23,17 @@ SceneNode::~SceneNode()
 }
 }
 
 
 
 
+//==============================================================================
+void SceneNode::frameUpdate(float /*prevUpdateTime*/, float /*crntTime*/,
+	int /*frame*/)
+{
+	// Movable update
+	Movable* m = getMovable();
+	if(m)
+	{
+		m->update();
+	}
+}
+
+
 } // end namespace
 } // end namespace

+ 3 - 6
anki/scene/SceneNode.h

@@ -68,12 +68,9 @@ public:
 	}
 	}
 	/// @}
 	/// @}
 
 
-	/// This is called by the scene every frame. But default it does nothing
-	virtual void frameUpdate(float prevUpdateTime, float crntTime)
-	{
-		(void)prevUpdateTime;
-		(void)crntTime;
-	}
+	/// This is called by the scene every frame after logic and before
+	/// rendering. By default it does nothing
+	virtual void frameUpdate(float prevUpdateTime, float crntTime, int frame);
 
 
 private:
 private:
 	std::string name; ///< A unique name
 	std::string name; ///< A unique name