Răsfoiți Sursa

Improve Camera by adding world_to_screen()/screen_to_world() and some fix/additions here and there

Daniele Bartolini 12 ani în urmă
părinte
comite
1a5cee59ae
2 a modificat fișierele cu 80 adăugiri și 22 ștergeri
  1. 59 14
      engine/Camera.cpp
  2. 21 8
      engine/Camera.h

+ 59 - 14
engine/Camera.cpp

@@ -30,20 +30,16 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Quaternion.h"
 #include "Unit.h"
 #include "Assert.h"
+#include "Vector4.h"
 
 namespace crown
 {
 
-//-----------------------------------------------------------------------
-void Camera::create(UnitId unit, int32_t node, const Vector3& pos, const Quaternion& rot)
+//-----------------------------------------------------------------------------
+void Camera::create(int32_t node, const Vector3& /*pos*/, const Quaternion& /*rot*/)
 {
-	m_unit = unit;
 	m_node = node;
 	m_projection_type = ProjectionType::PERSPECTIVE;
-
-	set_local_position(pos);
-	set_local_rotation(rot);
-	update_projection_matrix();
 }
 
 //-----------------------------------------------------------------------------
@@ -83,25 +79,31 @@ Matrix4x4 Camera::world_pose() const
 }
 
 //-----------------------------------------------------------------------------
-void Camera::set_local_position(const Vector3& pos)
+void Camera::set_local_position(Unit* unit, const Vector3& pos)
 {
 	m_local_pose.set_translation(pos);
+
+	unit->set_local_position(pos, m_node);
 }
 
 //-----------------------------------------------------------------------------
-void Camera::set_local_rotation(const Quaternion& rot)
+void Camera::set_local_rotation(Unit* unit, const Quaternion& rot)
 {
 	Matrix4x4& local_pose = m_local_pose;
 
 	Vector3 local_translation = local_pose.translation();
 	local_pose = rot.to_mat4();
 	local_pose.set_translation(local_translation);
+
+	unit->set_local_rotation(rot, m_node);
 }
 
 //-----------------------------------------------------------------------------
-void Camera::set_local_pose(const Matrix4x4& pose)
+void Camera::set_local_pose(Unit* unit, const Matrix4x4& pose)
 {
 	m_local_pose = pose;
+
+	unit->set_local_pose(pose, m_node);
 }
 
 //-----------------------------------------------------------------------
@@ -170,13 +172,56 @@ void Camera::set_far_clip_distance(float far)
 }
 
 //-----------------------------------------------------------------------------
-void Camera::set_orthographic_metrics(uint16_t width, uint16_t height)
+void Camera::set_orthographic_metrics(float left, float right, float bottom, float top)
 {
-	m_width = width;
-	m_height = height;
+	m_left = left;
+	m_right = right;
+	m_bottom = bottom;
+	m_top = top;
+
 	update_projection_matrix();
 }
 
+//-----------------------------------------------------------------------------
+void Camera::set_viewport_metrics(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+{
+	m_view_x = x;
+	m_view_y = y;
+	m_view_width = width;
+	m_view_height = height;
+}
+
+//-----------------------------------------------------------------------------
+Vector3 Camera::screen_to_world(const Vector3& pos)
+{
+	Matrix4x4 world_inv = m_world_pose;
+	world_inv.invert();
+	Matrix4x4 mvp = m_projection * world_inv;
+	mvp.invert();
+
+	Vector4 ndc( (2 * (pos.x - 0)) / m_view_width - 1,
+				 (2 * (pos.y - 0)) / m_view_height - 1,
+				 (2 * pos.z) - 1, 1);
+
+	Vector4 tmp = mvp * ndc;
+	tmp *= 1.0 / tmp.w;
+
+	return Vector3(tmp.x, tmp.y, tmp.z);
+}
+
+//-----------------------------------------------------------------------------
+Vector3 Camera::world_to_screen(const Vector3& pos)
+{
+	Matrix4x4 world_inv = m_world_pose;
+	world_inv.invert();
+
+	Vector3 ndc = (m_projection * world_inv) * pos;
+
+	return Vector3( (m_view_x + m_view_width * (ndc.x + 1.0)) / 2.0,
+					(m_view_y + m_view_height * (ndc.y + 1.0)) / 2.0,
+					(ndc.z + 1.0) / 2.0);
+}
+
 //-----------------------------------------------------------------------------
 void Camera::update_projection_matrix()
 {
@@ -184,7 +229,7 @@ void Camera::update_projection_matrix()
 	{
 		case ProjectionType::ORTHOGRAPHIC:
 		{
-			m_projection.build_projection_ortho_rh(m_width, m_height, m_near, m_far);
+			m_projection.build_projection_ortho_rh(m_left, m_right, m_bottom, m_top, m_near, m_far);
 			break;
 		}
 		case ProjectionType::PERSPECTIVE:

+ 21 - 8
engine/Camera.h

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Frustum.h"
 #include "Matrix4x4.h"
+#include "Vector3.h"
 #include "IdTable.h"
 
 namespace crown
@@ -50,7 +51,7 @@ class Unit;
 /// Represents the point of view into the game world.
 struct Camera
 {
-	void					create(UnitId unit, int32_t node, const Vector3& pos, const Quaternion& rot);
+	void					create(int32_t node, const Vector3& pos, const Quaternion& rot);
 
 	Vector3					local_position() const;
 	Quaternion				local_rotation() const;
@@ -60,9 +61,9 @@ struct Camera
 	Quaternion				world_rotation() const;
 	Matrix4x4				world_pose() const;
 
-	void					set_local_position(const Vector3& pos);
-	void					set_local_rotation(const Quaternion& rot);
-	void					set_local_pose(const Matrix4x4& pose);
+	void					set_local_position(Unit* unit, const Vector3& pos);
+	void					set_local_rotation(Unit* unit, const Quaternion& rot);
+	void					set_local_pose(Unit* unit, const Matrix4x4& pose);
 
 	void					set_projection_type(ProjectionType::Enum type);
 	ProjectionType::Enum	projection_type() const;
@@ -78,7 +79,11 @@ struct Camera
 	float					far_clip_distance() const;
 	void					set_far_clip_distance(float far);
 
-	void					set_orthographic_metrics(uint16_t width, uint16_t height);
+	void					set_orthographic_metrics(float left, float right, float bottom, float top);
+	void 					set_viewport_metrics(uint16_t x, uint16_t y, uint16_t width, uint16_t height);
+
+	Vector3					screen_to_world(const Vector3& pos);
+	Vector3					world_to_screen(const Vector3& pos);
 
 public:
 
@@ -87,7 +92,6 @@ public:
 
 public:
 
-	UnitId					m_unit;
 	int32_t					m_node;
 	Matrix4x4				m_local_pose;
 	Matrix4x4				m_world_pose;
@@ -100,8 +104,17 @@ public:
 	float					m_aspect;
 	float					m_near;
 	float					m_far;
-	uint16_t				m_width;
-	uint16_t				m_height;
+
+	// Orthographic projection only
+	float					m_left;
+	float					m_right;
+	float					m_bottom;
+	float					m_top;
+
+	uint16_t				m_view_x;
+	uint16_t				m_view_y;
+	uint16_t				m_view_width;
+	uint16_t				m_view_height;
 };
 
 } // namespace crown