From 0f159baf9db77bf362a96fe4944d9d45a8251664 Mon Sep 17 00:00:00 2001 From: tomoron Date: Tue, 28 Jan 2025 02:27:23 +0100 Subject: [PATCH] smooth transition between points using hermite interpolation for position and sphere interpolation for rotation --- imgui.ini | 10 ++-- includes/RT/Renderer.hpp | 4 +- srcs/class/Camera.cpp | 6 ++- srcs/class/Renderer.cpp | 113 ++++++++++++++++++++++++++++++++++----- 4 files changed, 112 insertions(+), 21 deletions(-) diff --git a/imgui.ini b/imgui.ini index 0d09fe6..e266055 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,15 +3,15 @@ Pos=60,60 Size=400,400 [Window][Camera] -Pos=687,417 +Pos=927,11 Size=259,200 [Window][Material] -Pos=646,129 +Pos=9,5 Size=266,299 [Window][Fog settings] -Pos=35,417 +Pos=22,314 Size=247,130 [Window][Debug] @@ -24,6 +24,6 @@ Size=274,205 Collapsed=1 [Window][Renderer] -Pos=32,4 -Size=404,469 +Pos=344,18 +Size=514,500 diff --git a/includes/RT/Renderer.hpp b/includes/RT/Renderer.hpp index 75474d8..bd516b5 100644 --- a/includes/RT/Renderer.hpp +++ b/includes/RT/Renderer.hpp @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/01/22 16:29:26 by tomoron #+# #+# */ -/* Updated: 2025/01/26 04:15:45 by tomoron ### ########.fr */ +/* Updated: 2025/01/28 01:20:39 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -50,12 +50,14 @@ class Renderer void imguiPathCreation(void); void imguiRenderInfo(void); std::string floatToTime(float timef); + glm::vec2 sphereInterpolate(glm::vec2 from, glm::vec2 to, float time); int _min; int _sec; int _samples; int _testSamples; int _fps; + bool _mine; std::vector _path; Scene *_scene; Window *_win; diff --git a/srcs/class/Camera.cpp b/srcs/class/Camera.cpp index 2a09b80..aaab1b0 100644 --- a/srcs/class/Camera.cpp +++ b/srcs/class/Camera.cpp @@ -6,7 +6,7 @@ /* By: ycontre +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/15 14:00:38 by TheRed #+# #+# */ -/* Updated: 2025/01/23 18:34:29 by tomoron ### ########.fr */ +/* Updated: 2025/01/28 02:15:41 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -59,6 +59,10 @@ void Camera::processMouse(float xoffset, float yoffset, bool constraint_pitch = _yaw += xoffset * _sensitivity; _pitch += yoffset * _sensitivity; +// while(_yaw < 0) +// _yaw += 360; +// while(_yaw > 360) +// _yaw -= 360; if (constraint_pitch) { if (_pitch > 89.0f) _pitch = 89.0f; diff --git a/srcs/class/Renderer.cpp b/srcs/class/Renderer.cpp index 0c69af0..f52e57f 100644 --- a/srcs/class/Renderer.cpp +++ b/srcs/class/Renderer.cpp @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/01/22 16:34:53 by tomoron #+# #+# */ -/* Updated: 2025/01/27 16:31:11 by tomoron ### ########.fr */ +/* Updated: 2025/01/28 02:19:41 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -208,35 +208,119 @@ void Renderer::update(Shader &shader) _curSamples = 0; } +glm::vec3 hermiteInterpolate(glm::vec3 points[4], double alpha) +{ + double tension; + double bias; + glm::vec3 tang[2]; + double alphaSqr[2]; + glm::vec3 coef[4]; + + tension = 0; + bias = 0; + + alphaSqr[0] = alpha * alpha; + alphaSqr[1] = alphaSqr[0] * alpha; + + tang[0] = (points[1] - points[0]) * glm::vec3(1 + bias) * glm::vec3(1 - tension) / glm::vec3(2); + tang[0] += (points[2] - points[1]) * glm::vec3(1 - bias) * glm::vec3(1 - tension) / glm::vec3(2); + tang[1] = (points[2] - points[1]) * glm::vec3(1 + bias) * glm::vec3(1 - tension) / glm::vec3(2); + tang[1] += (points[3] - points[2]) * glm::vec3(1 - bias) * glm::vec3(1 - tension) / glm::vec3(2); + + coef[0] = glm::vec3(2 * alphaSqr[1] - 3 * alphaSqr[0] + 1); + coef[1] = glm::vec3(alphaSqr[1] - 2 * alphaSqr[0] + alpha); + coef[2] = glm::vec3(alphaSqr[1] - alphaSqr[0]); + coef[3] = glm::vec3(-2 * alphaSqr[1] + 3 * alphaSqr[0]); + + return(coef[0] * points[1] + coef[1] * tang[0] + coef[2] * tang[1] + coef[3] * points[2]); +} + +glm::quat eulerToQuaternion(float pitch, float yaw) { + std::cout << "input : " << pitch << ", " << yaw << std::endl; + glm::quat qPitch = glm::angleAxis(glm::radians(pitch), glm::vec3(1, 0, 0)); + glm::quat qYaw = glm::angleAxis(glm::radians(yaw), glm::vec3(0, 1, 0)); + + glm::quat result = qYaw* qPitch; + std::cout << "output : " << glm::to_string(result) << std::endl; + return(result); +} + +glm::vec2 Renderer::sphereInterpolate(glm::vec2 from, glm::vec2 to, float time) +{ + glm::vec3 eulerRes; + glm::quat qFrom; + glm::quat qTo; + glm::quat res; + float angle; + float dot; + + qFrom = glm::normalize(eulerToQuaternion(from.y, from.x)); + qTo = glm::normalize(eulerToQuaternion(to.y, to.x)); + + dot = glm::dot(qFrom, qTo); + if(dot < 0) + to = -to; + angle = 2 * glm::acos(dot); + res = (glm::sin((1 - time) * angle / glm::sin(angle)) * qFrom) + ((glm::sin(time * angle) / glm::sin(angle)) * qTo); + eulerRes = glm::degrees(glm::eulerAngles(res)); + return(glm::vec2(eulerRes.y, eulerRes.x)); +} + + void Renderer::makeMovement(float timeFromStart, float curSplitTimeReset) { t_pathPoint from; t_pathPoint to; + t_pathPoint prev; + t_pathPoint next; float pathTime; Camera *cam; - glm::vec3 posStep; - glm::vec2 dirStep; + glm::vec3 pos; + glm::vec2 dir; + float normalTime; from = _path[_curPathIndex]; to = _path[_curPathIndex + 1]; + if(_curPathIndex) + prev = _path[_curPathIndex - 1]; + else + prev = from; + if((size_t)_curPathIndex + 3 == _path.size()) + next = _path[_curPathIndex + 2]; + else + next = to; + + cam = _scene->getCamera(); pathTime = (to.time - from.time) * 60; - - posStep.x = ((to.pos.x - from.pos.x) / pathTime) * timeFromStart; - posStep.y = ((to.pos.y - from.pos.y) / pathTime) * timeFromStart; - posStep.z = ((to.pos.z - from.pos.z) / pathTime) * timeFromStart; - dirStep.x = ((to.dir.x - from.dir.x) / pathTime) * timeFromStart; - dirStep.y = ((to.dir.y - from.dir.y) / pathTime) * timeFromStart; - + normalTime = 1 - ((pathTime - timeFromStart) / pathTime); + + pos = hermiteInterpolate((glm::vec3 [4]){prev.pos, from.pos, to.pos, next.pos}, normalTime); + dir = sphereInterpolate(from.dir, to.dir, normalTime); + if(std::isnan(dir.x) || std::isnan(dir.y)) + dir = from.dir; +// dir.x = hermiteInterpolate((glm::vec3 [4]){ +// glm::vec3(prev.dir.x, prev.dir.y, 0), +// glm::vec3(from.dir.x, from.dir.y, 0), +// glm::vec3(to.dir.x, to.dir.y, 0), +// glm::vec3(next.dir.x, next.dir.y, 0) +// }, normalTime).x; +// dir.y = hermiteInterpolate((glm::vec3 [4]){ +// glm::vec3(prev.dir.x, prev.dir.y, 0), +// glm::vec3(from.dir.x, from.dir.y, 0), +// glm::vec3(to.dir.x, to.dir.y, 0), +// glm::vec3(next.dir.x, next.dir.y, 0) +// }, normalTime).y; if(timeFromStart >= pathTime) { - posStep = to.pos - from.pos; - dirStep = to.dir - from.dir; + pos = to.pos; + dir = to.dir; _curSplitStart = curSplitTimeReset; _curPathIndex++; } - cam->setPosition(from.pos + posStep); - cam->setDirection(from.dir.x + dirStep.x, from.dir.y + dirStep.y); + std::cout << glm::to_string(dir) << std::endl; + cam->setPosition(pos); + cam->setDirection(dir.x, dir.y); _win->setFrameCount(0); if(_curPathIndex == _destPathIndex) { @@ -256,6 +340,7 @@ void Renderer::imguiPathCreation(void) ImGui::SliderInt("test spi", &_testSamples, 1, 10); ImGui::SliderInt("render spi", &_samples, 1, 1000); ImGui::SliderInt("render fps", &_fps, 30, 120); + ImGui::Checkbox("mine", &_mine); if(_path.size() && ImGui::Button("try full path")) { _scene->getCamera()->setPosition(_path[0].pos);