From cc3c5bce0ca6b50ef0195d893d5142833c107fec Mon Sep 17 00:00:00 2001
From: Joseph Walton-Rivers <joseph@walton-rivers.uk>
Date: Tue, 7 Sep 2021 20:54:04 +0100
Subject: [PATCH] enable camera scrolling

---
 demo/main.cpp       | 100 ++++++++++++++++++++++++++++++--------------
 fggl/gfx/input.cpp  |   2 +-
 fggl/gfx/window.cpp |   5 +++
 3 files changed, 75 insertions(+), 32 deletions(-)

diff --git a/demo/main.cpp b/demo/main.cpp
index 4394cc8..4013fa0 100644
--- a/demo/main.cpp
+++ b/demo/main.cpp
@@ -60,9 +60,10 @@ struct CameraHacks {
 
 void CameraArcball(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c);
 void CameraFree(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c);
+void CameraEdgeScroll(fggl::gfx::Input& input, fggl::components::Transform& t, fggl::components::Camera& c);
 
 //TODO proper input system
-void process_camera(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c) {
+void CameraInput(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c) {
 	CameraHacks* hacks = (CameraHacks*)( it.ctx() );
 	fggl::gfx::Window& window = hacks->window;
 	fggl::gfx::Input& input = hacks->input;
@@ -74,27 +75,27 @@ void process_camera(fggl::ecs2::impl::iter& it, fggl::components::Transform* t,
 		cam_mode = cam_arcball;
 	}
 
-	if ( cam_mode == cam_arcball ) {
+	if ( cam_mode == cam_arcball || input.mouseDown( fggl::gfx::MOUSE_2 ) ) {
 		CameraArcball(it, t, c);
 	} else if ( cam_mode == cam_free ) {
-//		CameraFree(it, t, c);
+		CameraFree(it, t, c);
 	}
 
-	/*	
-		auto camTransform = ecs.getComponent<fggl::math::Transform>(cam);
-		auto camComp = ecs.getComponent<fggl::gfx::Camera>(cam);
+	// scroll wheel
+	auto& camTransform = t[0];
+	auto& camComp = c[0];
 
-		const glm::vec3 dir = ( camTransform->origin() - camComp->target );
-		const glm::vec3 forward = glm::normalize( dir );
+	CameraEdgeScroll(input, camTransform, camComp);
+
+	const glm::vec3 dir = ( camTransform.origin() - camComp.target );
+	const glm::vec3 forward = glm::normalize( dir );
 
-	// scroll wheel
 	glm::vec3 motion(0.0f);
 	float delta = (float)input.scrollDeltaY();
 	if ( (glm::length( dir ) < 25.0f && delta < 0.0f) || (glm::length( dir ) > 2.5f && delta > 0.0f) )
-	motion -= (forward * delta);
+		motion -= (forward * delta);
 
-	camTransform->origin( camTransform->origin() + motion );
-	*/
+	camTransform.origin( camTransform.origin() + motion );
 }
 
 void CameraArcball(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c) {
@@ -102,21 +103,10 @@ void CameraArcball(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, f
 	const fggl::gfx::Window& window = hacks->window;
 	const fggl::gfx::Input& input = hacks->input;
 
-
 	auto& camTransform = t[0];
 	auto& camComp = c[0];
 
-	// scroll wheel
-	const glm::vec3 dir = ( camTransform.origin() - camComp.target );
-	const glm::vec3 forward = glm::normalize( dir );
-
-	glm::vec3 motion(0.0f);
-	float delta = (float)input.scrollDeltaY();
-	if ( (glm::length( dir ) < 25.0f && delta < 0.0f) || (glm::length( dir ) > 2.5f && delta > 0.0f) )
-		motion -= (forward * delta);
-
 	auto finalPos = camTransform.origin();
-	if ( input.mouseDown( fggl::gfx::MOUSE_2 ) ) {
 		// see https://asliceofrendering.com/camera/2019/11/30/ArcballCamera/
 		glm::vec4 position(camTransform.origin(), 1.0f);
 		glm::vec4 pivot(camComp.target, 1.0f);
@@ -143,19 +133,18 @@ void CameraArcball(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, f
 		glm::mat4x4 rotationMatrixY(1.0f);
 		rotationMatrixY = glm::rotate(rotationMatrixY, yAngle, rightDir );
 		finalPos = ( rotationMatrixY * ( position - pivot ) ) + pivot;
-	}
 
-	camTransform.origin( finalPos + motion );
+	camTransform.origin( finalPos );
 }
 
 constexpr float ROT_SPEED = 0.05f;
 constexpr float PAN_SPEED = 0.05f;
 constexpr glm::mat4 MAT_IDENTITY(1.0f);
 
-void process_freecam(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c) {
+void CameraFree(fggl::ecs2::impl::iter& it, fggl::components::Transform* t, fggl::components::Camera* c) {
 	CameraHacks* hacks = (CameraHacks*)( it.ctx() );
-	const fggl::gfx::Window& window = hacks->window;
-	const fggl::gfx::Input& input = hacks->input;
+	fggl::gfx::Window& window = hacks->window;
+	fggl::gfx::Input& input = hacks->input;
 
 	auto& camTransform = t[0];
 	auto& camComp = c[0];
@@ -164,7 +153,7 @@ void process_freecam(fggl::ecs2::impl::iter& it, fggl::components::Transform* t,
 	glm::vec3 translation(0.0f);
 
 	// calulate rotation (user input)
-/*	if ( glfwGetKey(window.handle(), GLFW_KEY_Q) == GLFW_PRESS ) {
+	if ( glfwGetKey(window.handle(), GLFW_KEY_Q) == GLFW_PRESS ) {
 		rotationValue = ROT_SPEED; 
 	} else if ( glfwGetKey(window.handle(), GLFW_KEY_E) == GLFW_PRESS ) {
 		rotationValue = -ROT_SPEED;
@@ -185,7 +174,7 @@ void process_freecam(fggl::ecs2::impl::iter& it, fggl::components::Transform* t,
 
 	if ( glfwGetKey(window.handle(), GLFW_KEY_A) == GLFW_PRESS ) {
 		translation -= fggl::math::FORWARD;
-	}*/
+	}
 
 	glm::vec4 position( camTransform.origin(), 1.0f );
 	glm::vec4 pivot( camComp.target, 1.0f );
@@ -213,6 +202,55 @@ void process_freecam(fggl::ecs2::impl::iter& it, fggl::components::Transform* t,
 	camComp.target = pivot;
 }
 
+void CameraEdgeScroll(fggl::gfx::Input& input, fggl::components::Transform& t, fggl::components::Camera& c) {
+	auto cursor = input.mousePos();
+
+	float rotationValue = 0.0f;
+	glm::vec3 translation(0.0f);
+
+	// calulate movement (user input)
+	if ( cursor[1] > 0.95f ) {
+		translation += fggl::math::RIGHT;
+	}
+
+	if ( cursor[1] < -0.95f ) {
+		translation -= fggl::math::RIGHT;
+	}
+
+	if ( cursor[0] > 0.95f ) {
+		translation += fggl::math::FORWARD;
+	}
+
+	if ( cursor[0] < -0.95f ) {
+		translation -= fggl::math::FORWARD;
+	}
+
+	glm::vec4 position( t.origin(), 1.0f );
+	glm::vec4 pivot( c.target, 1.0f );
+
+	// apply movement
+	if ( translation != glm::vec3(0.0f) ) {
+		const auto rotation = (position - pivot);
+		const float angle = atan2( rotation.x, rotation.z );
+		const auto rotationMat = glm::rotate( MAT_IDENTITY, angle, fggl::math::UP );
+
+		auto deltaMove = (rotationMat * glm::vec4( translation, 1.0f )) * PAN_SPEED;
+		deltaMove.w = 0.0f;
+
+		position += deltaMove;
+		pivot += deltaMove;
+	}
+
+	// apply rotation
+	if ( rotationValue != 0.0f ) {
+		glm::mat4 rotation = glm::rotate( MAT_IDENTITY, rotationValue, fggl::math::UP );
+		position = ( rotation * ( position - pivot ) ) + pivot;
+	}
+
+	t.origin( position );
+	c.target = pivot;
+}
+
 void loadShader(fggl::gfx::ShaderCache& cache, const char* name, bool hasGeom) {
 	fggl::gfx::ShaderConfig config;
 	config.name = name;
@@ -326,7 +364,7 @@ int main(int argc, char* argv[]) {
 
 	world.ecs().system<fggl::components::Transform, fggl::components::Camera>()
 		.ctx( &hacks )
-		.iter( CameraArcball );
+		.iter( CameraInput );
 
 	bool joystickWindow = true;
 	bool gamepadWindow = true;
diff --git a/fggl/gfx/input.cpp b/fggl/gfx/input.cpp
index 8be1ecb..0d14108 100644
--- a/fggl/gfx/input.cpp
+++ b/fggl/gfx/input.cpp
@@ -52,7 +52,7 @@ double Input::cursorDeltaY() const {
 }
 
 const double* Input::mousePos() const {
-	return m_mouse_curr.scroll.data();
+	return m_mouse_curr.cursor.data();
 }
 
 void Input::mouseScroll(double deltaX, double deltaY) {
diff --git a/fggl/gfx/window.cpp b/fggl/gfx/window.cpp
index f1aa1b5..168d2df 100644
--- a/fggl/gfx/window.cpp
+++ b/fggl/gfx/window.cpp
@@ -22,7 +22,12 @@ static void framebuffer_resize(GLFWwindow* window, int width, int height) {
 }
 
 static void fggl_input_cursor(GLFWwindow* window, double x, double y) {
+	auto fgglWindow = reinterpret_cast<Window*>(glfwGetWindowUserPointer( window ));
 	Input& input = Input::instance();
+
+	// set coords in [-1, 1]
+	x = ((x / fgglWindow->width()) - 0.5f) * 2;
+	y = ((y / fgglWindow->height()) - 0.5f) * 2;
 	input.mousePos(x, y);
 }
 
-- 
GitLab