From cfcac1b43554d30e7d1c51e5d296b29d1947bbc0 Mon Sep 17 00:00:00 2001
From: Joseph Walton-Rivers <joseph@walton-rivers.uk>
Date: Tue, 7 Sep 2021 20:21:28 +0100
Subject: [PATCH] move scroll wheel code into arcball controller

---
 demo/main.cpp | 89 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 55 insertions(+), 34 deletions(-)

diff --git a/demo/main.cpp b/demo/main.cpp
index f02bb32..4394cc8 100644
--- a/demo/main.cpp
+++ b/demo/main.cpp
@@ -53,8 +53,19 @@ void discover(std::filesystem::path base) {
 enum camera_type { cam_free, cam_arcball };
 camera_type cam_mode = cam_free;
 
+struct CameraHacks {
+	fggl::gfx::Window& window;
+	fggl::gfx::Input& input;
+};
+
+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);
+
 //TODO proper input system
-void process_camera(fggl::gfx::Window& window, fggl::ecs2::World& ecs, fggl::gfx::Input& input) {
+void process_camera(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;
 
 	if ( glfwGetKey(window.handle(), GLFW_KEY_F2) == GLFW_PRESS ) {
 		cam_mode = cam_free; 
@@ -63,6 +74,12 @@ void process_camera(fggl::gfx::Window& window, fggl::ecs2::World& ecs, fggl::gfx
 		cam_mode = cam_arcball;
 	}
 
+	if ( cam_mode == cam_arcball ) {
+		CameraArcball(it, t, c);
+	} else if ( cam_mode == cam_free ) {
+//		CameraFree(it, t, c);
+	}
+
 	/*	
 		auto camTransform = ecs.getComponent<fggl::math::Transform>(cam);
 		auto camComp = ecs.getComponent<fggl::gfx::Camera>(cam);
@@ -80,51 +97,55 @@ void process_camera(fggl::gfx::Window& window, fggl::ecs2::World& ecs, fggl::gfx
 	*/
 }
 
-struct CameraHacks {
-	fggl::gfx::Window& window;
-	fggl::gfx::Input& input;
-};
-
 void CameraArcball(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;
 
-	if ( !input.mouseDown( fggl::gfx::MOUSE_2 ) ) {
-		return;
-	}
 
 	auto& camTransform = t[0];
 	auto& camComp = c[0];
 
-	// see https://asliceofrendering.com/camera/2019/11/30/ArcballCamera/
-	glm::vec4 position(camTransform.origin(), 1.0f);
-	glm::vec4 pivot(camComp.target, 1.0f);
-	glm::mat4 view = glm::lookAt( camTransform.origin(), camComp.target, camTransform.up() );
-	glm::vec3 viewDir = -glm::transpose(view)[2];
-	glm::vec3 rightDir = glm::transpose(view)[0];
-
-	float deltaAngleX = ( 2 * M_PI / window.width() ); 
-	float deltaAngleY = ( M_PI / window.height() );
-	float xAngle = ( input.cursorDeltaX() ) * deltaAngleX;
-	float yAngle = ( input.cursorDeltaY() ) * deltaAngleY;
-
-	auto cosAngle = glm::dot( viewDir, fggl::math::UP );
-	if ( cosAngle * sgn(deltaAngleY) > 0.99f ) {
-		deltaAngleY = 0;
-	}
+	// scroll wheel
+	const glm::vec3 dir = ( camTransform.origin() - camComp.target );
+	const glm::vec3 forward = glm::normalize( dir );
 
-	// rotate the camera around the pivot on the first axis
-	glm::mat4x4 rotationMatrixX(1.0f);
-	rotationMatrixX = glm::rotate( rotationMatrixX, xAngle, fggl::math::UP );
-	position = ( rotationMatrixX * ( position - pivot ) ) + pivot;
+	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);
+		glm::mat4 view = glm::lookAt( camTransform.origin(), camComp.target, camTransform.up() );
+		glm::vec3 viewDir = -glm::transpose(view)[2];
+		glm::vec3 rightDir = glm::transpose(view)[0];
+
+		float deltaAngleX = ( 2 * M_PI / window.width() ); 
+		float deltaAngleY = ( M_PI / window.height() );
+		float xAngle = ( input.cursorDeltaX() ) * deltaAngleX;
+		float yAngle = ( input.cursorDeltaY() ) * deltaAngleY;
+
+		auto cosAngle = glm::dot( viewDir, fggl::math::UP );
+		if ( cosAngle * sgn(deltaAngleY) > 0.99f ) {
+			deltaAngleY = 0;
+		}
 
-	// rotate the camera aroud the pivot on the second axis
-	glm::mat4x4 rotationMatrixY(1.0f);
-	rotationMatrixY = glm::rotate(rotationMatrixY, yAngle, rightDir );
-	glm::vec3 finalPos = ( rotationMatrixY * ( position - pivot ) ) + pivot;
+		// rotate the camera around the pivot on the first axis
+		glm::mat4x4 rotationMatrixX(1.0f);
+		rotationMatrixX = glm::rotate( rotationMatrixX, xAngle, fggl::math::UP );
+		position = ( rotationMatrixX * ( position - pivot ) ) + pivot;
+
+		// rotate the camera aroud the pivot on the second axis
+		glm::mat4x4 rotationMatrixY(1.0f);
+		rotationMatrixY = glm::rotate(rotationMatrixY, yAngle, rightDir );
+		finalPos = ( rotationMatrixY * ( position - pivot ) ) + pivot;
+	}
 
-	camTransform.origin( finalPos );
+	camTransform.origin( finalPos + motion );
 }
 
 constexpr float ROT_SPEED = 0.05f;
-- 
GitLab