smooth transition between points using hermite interpolation for position and sphere interpolation for rotation

This commit is contained in:
2025-01-28 02:27:23 +01:00
parent c909cbd6da
commit 0f159baf9d
4 changed files with 112 additions and 21 deletions

View File

@ -3,15 +3,15 @@ Pos=60,60
Size=400,400 Size=400,400
[Window][Camera] [Window][Camera]
Pos=687,417 Pos=927,11
Size=259,200 Size=259,200
[Window][Material] [Window][Material]
Pos=646,129 Pos=9,5
Size=266,299 Size=266,299
[Window][Fog settings] [Window][Fog settings]
Pos=35,417 Pos=22,314
Size=247,130 Size=247,130
[Window][Debug] [Window][Debug]
@ -24,6 +24,6 @@ Size=274,205
Collapsed=1 Collapsed=1
[Window][Renderer] [Window][Renderer]
Pos=32,4 Pos=344,18
Size=404,469 Size=514,500

View File

@ -6,7 +6,7 @@
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/22 16:29:26 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 imguiPathCreation(void);
void imguiRenderInfo(void); void imguiRenderInfo(void);
std::string floatToTime(float timef); std::string floatToTime(float timef);
glm::vec2 sphereInterpolate(glm::vec2 from, glm::vec2 to, float time);
int _min; int _min;
int _sec; int _sec;
int _samples; int _samples;
int _testSamples; int _testSamples;
int _fps; int _fps;
bool _mine;
std::vector<t_pathPoint> _path; std::vector<t_pathPoint> _path;
Scene *_scene; Scene *_scene;
Window *_win; Window *_win;

View File

@ -6,7 +6,7 @@
/* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */ /* By: ycontre <ycontre@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/15 14:00:38 by TheRed #+# #+# */ /* 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; _yaw += xoffset * _sensitivity;
_pitch += yoffset * _sensitivity; _pitch += yoffset * _sensitivity;
// while(_yaw < 0)
// _yaw += 360;
// while(_yaw > 360)
// _yaw -= 360;
if (constraint_pitch) if (constraint_pitch)
{ {
if (_pitch > 89.0f) _pitch = 89.0f; if (_pitch > 89.0f) _pitch = 89.0f;

View File

@ -6,7 +6,7 @@
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/22 16:34:53 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; _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) void Renderer::makeMovement(float timeFromStart, float curSplitTimeReset)
{ {
t_pathPoint from; t_pathPoint from;
t_pathPoint to; t_pathPoint to;
t_pathPoint prev;
t_pathPoint next;
float pathTime; float pathTime;
Camera *cam; Camera *cam;
glm::vec3 posStep; glm::vec3 pos;
glm::vec2 dirStep; glm::vec2 dir;
float normalTime;
from = _path[_curPathIndex]; from = _path[_curPathIndex];
to = _path[_curPathIndex + 1]; 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(); cam = _scene->getCamera();
pathTime = (to.time - from.time) * 60; pathTime = (to.time - from.time) * 60;
normalTime = 1 - ((pathTime - timeFromStart) / pathTime);
posStep.x = ((to.pos.x - from.pos.x) / pathTime) * timeFromStart; pos = hermiteInterpolate((glm::vec3 [4]){prev.pos, from.pos, to.pos, next.pos}, normalTime);
posStep.y = ((to.pos.y - from.pos.y) / pathTime) * timeFromStart; dir = sphereInterpolate(from.dir, to.dir, normalTime);
posStep.z = ((to.pos.z - from.pos.z) / pathTime) * timeFromStart; if(std::isnan(dir.x) || std::isnan(dir.y))
dirStep.x = ((to.dir.x - from.dir.x) / pathTime) * timeFromStart; dir = from.dir;
dirStep.y = ((to.dir.y - from.dir.y) / pathTime) * timeFromStart; // 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) if(timeFromStart >= pathTime)
{ {
posStep = to.pos - from.pos; pos = to.pos;
dirStep = to.dir - from.dir; dir = to.dir;
_curSplitStart = curSplitTimeReset; _curSplitStart = curSplitTimeReset;
_curPathIndex++; _curPathIndex++;
} }
cam->setPosition(from.pos + posStep); std::cout << glm::to_string(dir) << std::endl;
cam->setDirection(from.dir.x + dirStep.x, from.dir.y + dirStep.y); cam->setPosition(pos);
cam->setDirection(dir.x, dir.y);
_win->setFrameCount(0); _win->setFrameCount(0);
if(_curPathIndex == _destPathIndex) if(_curPathIndex == _destPathIndex)
{ {
@ -256,6 +340,7 @@ void Renderer::imguiPathCreation(void)
ImGui::SliderInt("test spi", &_testSamples, 1, 10); ImGui::SliderInt("test spi", &_testSamples, 1, 10);
ImGui::SliderInt("render spi", &_samples, 1, 1000); ImGui::SliderInt("render spi", &_samples, 1, 1000);
ImGui::SliderInt("render fps", &_fps, 30, 120); ImGui::SliderInt("render fps", &_fps, 30, 120);
ImGui::Checkbox("mine", &_mine);
if(_path.size() && ImGui::Button("try full path")) if(_path.size() && ImGui::Button("try full path"))
{ {
_scene->getCamera()->setPosition(_path[0].pos); _scene->getCamera()->setPosition(_path[0].pos);