Marko Pintera 13 år sedan
förälder
incheckning
b20b654b64

+ 2 - 0
CamelotClient/CamelotClient.vcxproj

@@ -87,12 +87,14 @@
     <Text Include="ReadMe.txt" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="CmDebugCamera.h" />
     <ClInclude Include="stdafx.h" />
     <ClInclude Include="targetver.h" />
     <ClInclude Include="TestingGround.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="CamelotClient.cpp" />
+    <ClCompile Include="CmDebugCamera.cpp" />
     <ClCompile Include="stdafx.cpp" />
     <ClCompile Include="TestingGround.cpp" />
   </ItemGroup>

+ 6 - 0
CamelotClient/CamelotClient.vcxproj.filters

@@ -27,6 +27,9 @@
     <ClInclude Include="TestingGround.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="CmDebugCamera.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
@@ -38,5 +41,8 @@
     <ClCompile Include="TestingGround.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="CmDebugCamera.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 116 - 0
CamelotClient/CmDebugCamera.cpp

@@ -0,0 +1,116 @@
+#include "CmDebugCamera.h"
+#include "CmInput.h"
+#include "CmVector3.h"
+#include "CmTime.h"
+#include "CmMath.h"
+#include "CmGameObject.h"
+#include "CmCamera.h"
+
+namespace CamelotEngine
+{
+	const float DebugCamera::START_SPEED = 40.0f;
+	const float DebugCamera::TOP_SPEED = 130.0f;
+	const float DebugCamera::ACCELERATION = 10.0f;
+	const float DebugCamera::FAST_MODE_MULTIPLIER = 2.0f;
+	const float DebugCamera::ROTATION_SPEED = 0.5f; // Degrees/pixel
+
+	DebugCamera::DebugCamera(GameObjectPtr parent)
+		:Component(parent), mGoingForward(false), mGoingBack(false), mGoingLeft(false), mGoingRight(false), mFastMove(false), mCameraRotating(false)
+	{
+		mCamera = getGO()->getComponent<Camera>();
+
+		mCamera->getGO()->setPosition(Vector3(0,0,80));
+		mCamera->getGO()->lookAt(Vector3(0,0,-300));
+		mCamera->setNearClipDistance(5);
+
+		gInput().onKeyDown.connect(boost::bind(&DebugCamera::keyDown, this, _1));
+		gInput().onKeyUp.connect(boost::bind(&DebugCamera::keyUp, this, _1));
+
+		gInput().onMouseDown.connect(boost::bind(&DebugCamera::mouseDown, this, _1, _2));
+		gInput().onMouseUp.connect(boost::bind(&DebugCamera::mouseUp, this, _1, _2));
+	}
+
+	void DebugCamera::keyDown(KeyCode keyCode)
+	{
+		if (keyCode == KC_W || keyCode == KC_UP) 
+			mGoingForward = true;
+		else if (keyCode == KC_S || keyCode== KC_DOWN) 
+			mGoingBack = true;
+		else if (keyCode == KC_A || keyCode == KC_LEFT) 
+			mGoingLeft = true;
+		else if (keyCode == KC_D || keyCode == KC_RIGHT) 
+			mGoingRight = true;
+		else if (keyCode == KC_LSHIFT) 
+			mFastMove = true;
+	}
+
+	void DebugCamera::keyUp(KeyCode keyCode)
+	{
+		if (keyCode == KC_W || keyCode == KC_UP) 
+			mGoingForward = false;
+		else if (keyCode == KC_S || keyCode== KC_DOWN) 
+			mGoingBack = false;
+		else if (keyCode == KC_A || keyCode == KC_LEFT) 
+			mGoingLeft = false;
+		else if (keyCode == KC_D || keyCode == KC_RIGHT) 
+			mGoingRight = false;
+		else if (keyCode == KC_LSHIFT) 
+			mFastMove = false;
+	}
+
+	void DebugCamera::mouseDown(const MouseEvent& event, MouseButton buttonID)
+	{
+		if(buttonID == MB_Right)
+		{
+			mCameraRotating = true;
+		}
+	}
+
+	void DebugCamera::mouseUp(const MouseEvent& event, MouseButton buttonID)
+	{
+		if(buttonID == MB_Right)
+		{
+			mCameraRotating = false;
+		}
+	}
+
+	void DebugCamera::update()
+	{
+		Vector3 direction = Vector3::ZERO;
+		if (mGoingForward) direction += mCamera->getGO()->getForward();
+		if (mGoingBack) direction -= mCamera->getGO()->getForward();
+		if (mGoingRight) direction += mCamera->getGO()->getRight();
+		if (mGoingLeft) direction -= mCamera->getGO()->getRight();
+
+		if (direction.squaredLength() != 0)
+		{
+			direction.normalise();
+
+			float multiplier = 1.0f;
+			if(mFastMove)
+				multiplier = FAST_MODE_MULTIPLIER;
+
+			mCurrentSpeed = Math::Clamp(mCurrentSpeed + ACCELERATION * gTime().getFrameDelta(), START_SPEED, TOP_SPEED);
+			mCurrentSpeed *= multiplier;
+		}
+		else
+		{
+			mCurrentSpeed = 0.0f;
+		}
+
+		float tooSmall = std::numeric_limits<float>::epsilon();
+		if(mCurrentSpeed > tooSmall)
+		{
+			Vector3 velocity = direction * mCurrentSpeed;
+			mCamera->getGO()->move(velocity * gTime().getFrameDelta());
+		}
+
+		if(mCameraRotating)
+		{
+			//float horizontalSpeed = event.relX / gTime().getFrameDelta();
+
+			mCamera->getGO()->yaw(Degree(gInput().getHorizontalAxis() * ROTATION_SPEED));
+			mCamera->getGO()->pitch(Degree(gInput().getVerticalAxis() * ROTATION_SPEED));
+		}
+	}
+}

+ 48 - 0
CamelotClient/CmDebugCamera.h

@@ -0,0 +1,48 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmComponent.h"
+#include "CmInputHandler.h"
+
+namespace CamelotEngine
+{
+	class DebugCamera : public Component
+	{
+	private:
+		float mCurrentSpeed;
+
+		bool mGoingForward;
+		bool mGoingBack;
+		bool mGoingLeft;
+		bool mGoingRight;
+		bool mFastMove;
+		bool mCameraRotating;
+
+		CameraPtr mCamera;
+
+		void keyDown(CamelotEngine::KeyCode keyCode);
+		void keyUp(CamelotEngine::KeyCode keyCode);
+
+		void mouseDown(const CamelotEngine::MouseEvent& event, CamelotEngine::MouseButton buttonID);
+		void mouseUp(const CamelotEngine::MouseEvent& event, CamelotEngine::MouseButton buttonID);
+
+		static const float START_SPEED;
+		static const float TOP_SPEED;
+		static const float ACCELERATION;
+		static const float FAST_MODE_MULTIPLIER;
+		static const float ROTATION_SPEED; // Degrees/second
+
+		/************************************************************************/
+		/* 						COMPONENT OVERRIDES                      		*/
+		/************************************************************************/
+	private:
+		friend class GameObject;
+
+		/** Standard constructor.
+        */
+		DebugCamera(GameObjectPtr parent);
+
+	public:
+		virtual void update();
+	};
+}

+ 13 - 4
CamelotRenderer/Include/CmCamera.h

@@ -539,10 +539,6 @@ namespace CamelotEngine {
 		vector<Vector4>::type getRayForwardIntersect(const Vector3& anchor, const Vector3 *dir, float planeOffset) const;
 
     public:
-		/** Standard constructor.
-        */
-		Camera(GameObjectPtr parent);
-
         /** Standard destructor.
         */
         virtual ~Camera();
@@ -621,6 +617,19 @@ namespace CamelotEngine {
 		*/
 		void forwardIntersect(const Plane& worldPlane, vector<Vector4>::type* intersect3d) const;
 
+		/************************************************************************/
+		/* 						COMPONENT OVERRIDES                      		*/
+		/************************************************************************/
+	private:
+		friend class GameObject;
+
+		/** Standard constructor.
+        */
+		Camera(GameObjectPtr parent);
+
+	public:
+		virtual void update() {}
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 11 - 4
CamelotRenderer/Include/CmComponent.h

@@ -8,15 +8,22 @@ namespace CamelotEngine
 	class CM_EXPORT Component : public IReflectable
 	{
 	public:
-		GameObjectPtr getGameObject() const { return mParent.lock(); }
+		/**
+		 * @brief	Returns the GameObject this Component is assigned to.
+		 */
+		GameObjectPtr getGO() const { return mParent.lock(); }
+
+		/**
+		 * @brief	Called once per frame on all components.
+		 */
+		virtual void update() = 0;
 
-		// TODO - This shouldn't really be public since only GameObject should be allowed to add components.
-		// But then I have a problem that all derived classes need to have GameObject as a friend class.
-		Component(GameObjectPtr parent);
 		virtual ~Component();
 	protected:
 		friend class GameObject;
 
+		Component(GameObjectPtr parent);
+
 		/**
 		 * @brief	Destroys the Component and makes it unusable, without actually deleting it.
 		 * 			

+ 92 - 0
CamelotRenderer/Include/CmGameObject.h

@@ -4,6 +4,7 @@
 #include "CmMatrix4.h"
 #include "CmVector3.h"
 #include "CmQuaternion.h"
+#include "CmRTTIType.h"
 
 #include "boost/static_assert.hpp"
 
@@ -47,6 +48,64 @@ namespace CamelotEngine
 		const Matrix4& getWorldTfrm() const;
 		const Matrix4& getLocalTfrm() const;
 
+		/** Moves the object's position by the vector offset provided along world axes.
+        */
+        void move(const Vector3& vec);
+
+        /** Moves the object's position by the vector offset provided along it's own axes (relative to orientation).
+        */
+        void moveRelative(const Vector3& vec);
+
+		/**
+		 * @brief	Gets the Z (forward) axis of the object, in world space.
+		 *
+		 * @return	Forward axis of the object.
+		 */
+		Vector3 getForward() const { return mRotation * Vector3::UNIT_Z; }
+
+		/**
+		 * @brief	Gets the Y (up) axis of the object, in world space.
+		 *
+		 * @return	Up axis of the object.
+		 */
+		Vector3 getUp() const { return mRotation * Vector3::UNIT_Y; }
+
+		/**
+		 * @brief	Gets the X (right) axis of the object, in world space.
+		 *
+		 * @return	Right axis of the object.
+		 */
+		Vector3 getRight() const { return mRotation * Vector3::UNIT_X; }
+
+		/** Rotate the object around an arbitrary axis.
+        */
+        void rotate(const Vector3& axis, const Radian& angle);
+
+        /** Rotate the object around an arbitrary axis using a Quaternion.
+        */
+        void rotate(const Quaternion& q);
+
+		/**
+		 * @brief	Rotates around local Z axis.
+		 *
+		 * @param	angle	Angle to rotate by.
+		 */
+		void roll(const Radian& angle);
+
+		/**
+		 * @brief	Rotates around Y axis.
+		 *
+		 * @param	angle	Angle to rotate by.
+		 */
+		void yaw(const Radian& angle);
+
+		/**
+		 * @brief	Rotates around X axis
+		 *
+		 * @param	angle	Angle to rotate by.
+		 */
+		void pitch(const Radian& angle);
+
 	private:
 		String mName;
 
@@ -154,6 +213,39 @@ namespace CamelotEngine
 			return newComponent;
 		}
 
+		/**
+		 * @brief	Searches for a component with the specific type and returns the first one
+		 * 			it finds. 
+		 * 			
+		 * @note	Don't call this too often as it is relatively slow. It is more efficient 
+		 * 			to call it once and store the result for further use.
+		 *
+		 * @tparam	typename T	Type of the component.
+		 *
+		 * @return	Component if found, nullptr otherwise.
+		 */
+		template <typename T>
+		std::shared_ptr<T> getComponent()
+		{
+			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::Component, T>::value), 
+				"Specified type is not a valid Component.");
+
+			return std::static_pointer_cast<T>(getComponent(T::getRTTIStatic()->getRTTIId()));
+		}
+
+		/**
+		 * @brief	Searches for a component with the specified type id and returns the first one it
+		 * 			finds.
+		 * 			
+		 * 			@note	Don't call this too often as it is relatively slow. It is more efficient to
+		 * 			call it once and store the result for further use.
+		 *
+		 * @param	typeId	Identifier for the type.
+		 *
+		 * @return	Component if found, nullptr otherwise.
+		 */
+		ComponentPtr getComponent(UINT32 typeId) const;
+
 		/**
 		 * @brief	Removes the component from this GameObject, and deallocates it.
 		 *

+ 5 - 0
CamelotRenderer/Include/CmRenderable.h

@@ -7,6 +7,11 @@ namespace CamelotEngine
 {
 	class Renderable : public Component
 	{
+		/************************************************************************/
+		/* 							COMPONENT OVERRIDES                    		*/
+		/************************************************************************/
+		virtual void update() {}
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 4 - 4
CamelotRenderer/Source/CmCamera.cpp

@@ -656,8 +656,8 @@ namespace CamelotEngine {
 		if (!mCustomViewMatrix)
 		{
 			Matrix3 rot;
-			const Quaternion& orientation = getGameObject()->getWorldRotation();
-			const Vector3& position = getGameObject()->getWorldPosition();
+			const Quaternion& orientation = getGO()->getWorldRotation();
+			const Vector3& position = getGO()->getWorldPosition();
 
 			mViewMatrix = Math::makeViewMatrix(position, orientation, 0);
 		}
@@ -1154,7 +1154,7 @@ namespace CamelotEngine {
 		mWindowClipPlanes.clear();
         if (mProjType == PT_PERSPECTIVE)
         {
-            Vector3 position = getGameObject()->getWorldPosition();
+            Vector3 position = getGO()->getWorldPosition();
             mWindowClipPlanes.push_back(Plane(position, vw_bl, vw_ul));
             mWindowClipPlanes.push_back(Plane(position, vw_ul, vw_ur));
             mWindowClipPlanes.push_back(Plane(position, vw_ur, vw_br));
@@ -1315,7 +1315,7 @@ namespace CamelotEngine {
 		Quaternion invPlaneRot = pval.normal.getRotationTo(Vector3::UNIT_Z);
 
 		// get rotated light
-		Vector3 lPos = invPlaneRot * getGameObject()->getWorldPosition();
+		Vector3 lPos = invPlaneRot * getGO()->getWorldPosition();
 		Vector3 vec[4];
 		vec[0] = invPlaneRot * trCorner - lPos;
 		vec[1] = invPlaneRot * tlCorner - lPos; 

+ 61 - 0
CamelotRenderer/Source/CmGameObject.cpp

@@ -142,6 +142,56 @@ namespace CamelotEngine
 		return mCachedLocalTfrm;
 	}
 
+	void GameObject::move(const Vector3& vec)
+	{
+		setPosition(mPosition + vec);
+	}
+
+	void GameObject::moveRelative(const Vector3& vec)
+	{
+		// Transform the axes of the relative vector by camera's local axes
+		Vector3 trans = mRotation * vec;
+
+		setPosition(mPosition + trans);
+	}
+
+	void GameObject::rotate(const Vector3& axis, const Radian& angle)
+	{
+		Quaternion q;
+		q.FromAngleAxis(angle,axis);
+		rotate(q);
+	}
+
+	void GameObject::rotate(const Quaternion& q)
+	{
+		// Note the order of the mult, i.e. q comes after
+
+		// Normalize the quat to avoid cumulative problems with precision
+		Quaternion qnorm = q;
+		qnorm.normalise();
+		setRotation(qnorm * mRotation);
+	}
+
+	void GameObject::roll(const Radian& angle)
+	{
+		// Rotate around local Z axis
+		Vector3 zAxis = mRotation * Vector3::UNIT_Z;
+		rotate(zAxis, angle);
+	}
+
+	void GameObject::yaw(const Radian& angle)
+	{
+		Vector3 yAxis = mRotation * Vector3::UNIT_Y;
+		rotate(yAxis, angle);
+	}
+
+	void GameObject::pitch(const Radian& angle)
+	{
+		// Rotate around local X axis
+		Vector3 xAxis = mRotation * Vector3::UNIT_X;
+		rotate(xAxis, angle);
+	}
+
 	void GameObject::markTfrmDirty() const
 	{
 		mIsCachedLocalTfrmUpToDate = false;
@@ -265,6 +315,17 @@ namespace CamelotEngine
 		}
 	}
 
+	ComponentPtr GameObject::getComponent(UINT32 typeId) const
+	{
+		for(auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
+		{
+			if((*iter)->getRTTI()->getRTTIId() == typeId)
+				return *iter;
+		}
+
+		return nullptr;
+	}
+
 	void GameObject::destroyComponent(ComponentPtr component)
 	{
 		if(component == nullptr)