mirror of
https://github.com/TheRedShip/RT_GPU.git
synced 2025-09-27 18:48:36 +02:00
174 lines
5.6 KiB
C++
174 lines
5.6 KiB
C++
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* movements.cpp :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2025/02/20 16:01:59 by tomoron #+# #+# */
|
|
/* Updated: 2025/03/18 17:00:17 by tomoron ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "RT.hpp"
|
|
|
|
glm::vec3 Renderer::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::vec2 Renderer::bezierSphereInterpolate(glm::vec4 control, glm::vec2 from, glm::vec2 to, float time)
|
|
{
|
|
glm::vec2 delta;
|
|
glm::vec2 p1, p2;
|
|
float t;
|
|
|
|
p1 = glm::vec2(control.x, control.y);
|
|
p2 = glm::vec2(control.z, control.w);
|
|
t = time;
|
|
for(int i = 0; i < 5; i++) {
|
|
float currentX = 3.0f * ((1 - t) * (1 - t)) * t * p1.x + 3.0f * (1 - t) * (t * t) * p2.x + (t * t * t);
|
|
|
|
if(abs(currentX - time) < 0.00001f) {
|
|
break;
|
|
}
|
|
|
|
glm::vec2 derivative = glm::vec2(
|
|
3.0f * (1 - t) * (1 - t) * p1.x +
|
|
6.0f * (1.0f - t) * t * (p2.x - p1.x) +
|
|
3.0f * t * t * (1.0f - p2.x),
|
|
|
|
3.0f * (1 - t) * (1 - t) * p1.y +
|
|
6.0f * (1.0f - t) * t * (p2.y - p1.y) +
|
|
3.0f * t * t * (1.0f - p2.y)
|
|
);
|
|
|
|
if(abs(derivative.x) > 0.00001f){
|
|
t = t - (currentX - time) / derivative.x;
|
|
t = glm::clamp(t, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
t = 3.0f * ((1 - t) * (1 - t)) * t * p1.y + 3.0f * (1 - t) * (t * t) * p2.y + (t * t * t);
|
|
|
|
delta = to - from;
|
|
return(from + glm::vec2(delta.x * t, delta.y * t));
|
|
}
|
|
|
|
t_pathPoint Renderer::createNextPoint(t_pathPoint from, t_pathPoint to)
|
|
{
|
|
t_pathPoint res;
|
|
|
|
res.pos = to.pos + (to.pos - from.pos);
|
|
res.dir = to.dir + (to.dir - from.dir);
|
|
res.time = to.time + (to.time - from.time);
|
|
return (res);
|
|
}
|
|
|
|
void Renderer::getInterpolationPoints(t_pathPoint &prev, t_pathPoint &from, t_pathPoint &to, t_pathPoint &next)
|
|
{
|
|
from = _path[_curPathIndex];
|
|
to = _path[_curPathIndex + 1];
|
|
|
|
if(!_curPathIndex)
|
|
prev = from;
|
|
else if (_curPathIndex && _path[_curPathIndex - 1].time == _path[_curPathIndex].time)
|
|
prev = createNextPoint(to, from);
|
|
else
|
|
prev = _path[_curPathIndex - 1];
|
|
|
|
if((size_t)_curPathIndex + 2 >= _path.size())
|
|
next = to;
|
|
else if ((size_t)_curPathIndex + 2 < _path.size() && _path[_curPathIndex + 2].time == _path[_curPathIndex + 1].time)
|
|
next = createNextPoint(from, to);
|
|
else
|
|
next = _path[_curPathIndex + 2];
|
|
}
|
|
|
|
void Renderer::interpolateMovement(float time, glm::vec3 *pos, glm::vec2 *dir)
|
|
{
|
|
t_pathPoint prev;
|
|
t_pathPoint from;
|
|
t_pathPoint to;
|
|
t_pathPoint next;
|
|
|
|
float pathTime;
|
|
float normalTime;
|
|
bool smallDistPrev;
|
|
bool smallDistNext;
|
|
float splitTime;
|
|
glm::vec4 bezierControl;
|
|
|
|
std::cout << "current time : " << time << std::endl;
|
|
while(_curPathIndex < _path.size() - 2 && (_path[_curPathIndex + 1].time * 60) < time)
|
|
_curPathIndex++;
|
|
|
|
splitTime = time - (_path[_curPathIndex].time * 60);
|
|
getInterpolationPoints(prev, from, to, next);
|
|
|
|
pathTime = (to.time - from.time) * 60;
|
|
normalTime = 1 - ((pathTime - splitTime) / pathTime);
|
|
|
|
glm::vec3 points[4] = {prev.pos, from.pos, to.pos, next.pos};
|
|
*pos = hermiteInterpolate(points, normalTime);
|
|
|
|
smallDistPrev = glm::distance((to.dir - from.dir) / glm::vec2(pathTime), (from.dir - prev.dir) / glm::vec2((from.time - prev.time) * 60)) < 40;
|
|
smallDistNext = glm::distance((to.dir - from.dir) / glm::vec2(pathTime), (next.dir - to.dir) / glm::vec2((next.time - to.time) * 60)) < 40;
|
|
bezierControl.x = 0.2f;
|
|
bezierControl.y = !_curPathIndex || smallDistPrev ? .1f : .0f;
|
|
bezierControl.z = 0.8f;
|
|
bezierControl.w = (size_t)_curPathIndex + 2 >= _path.size() || smallDistNext ? .9f : 1.0f;
|
|
|
|
*dir = bezierSphereInterpolate(bezierControl, from.dir, to.dir, normalTime);
|
|
if(std::isnan(dir->x) || std::isnan(dir->y))
|
|
*dir = from.dir;
|
|
if(splitTime >= pathTime)
|
|
{
|
|
*pos = to.pos;
|
|
*dir = to.dir;
|
|
_curPathIndex++;
|
|
}
|
|
}
|
|
|
|
void Renderer::makeMovement(float time)
|
|
{
|
|
glm::vec2 dir;
|
|
glm::vec3 pos;
|
|
Camera *cam;
|
|
|
|
interpolateMovement(time, &pos, &dir);
|
|
|
|
cam = _scene->getCamera();
|
|
cam->setPosition(pos);
|
|
cam->setDirection(dir.x, dir.y);
|
|
_win->setFrameCount(0);
|
|
|
|
if(_curPathIndex == _destPathIndex)
|
|
{
|
|
_destPathIndex = 0;
|
|
if(!_testMode)
|
|
endRender(0);
|
|
}
|
|
}
|