numeric : Added SmoothClamp & swap camera : fixed target&up issues and added screen-scale factor. touky_demo : correct camera integration & first pass on uro refactor. Also added Makefile to vcprojundefined
@@ -2,6 +2,7 @@ | |||||
// Lol Engine | // Lol Engine | ||||
// | // | ||||
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | ||||
// 2012-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
// This program is free software; you can redistribute it and/or | // This program is free software; you can redistribute it and/or | ||||
// modify it under the terms of the Do What The Fuck You Want To | // modify it under the terms of the Do What The Fuck You Want To | ||||
// Public License, Version 2, as published by Sam Hocevar. See | // Public License, Version 2, as published by Sam Hocevar. See | ||||
@@ -38,12 +39,13 @@ Camera::Camera() | |||||
m_screen_size = (float)screen_size.x; | m_screen_size = (float)screen_size.x; | ||||
m_screen_ratio = (float)screen_size.x / (float)screen_size.y; | m_screen_ratio = (float)screen_size.x / (float)screen_size.y; | ||||
m_is_shifted = false; | m_is_shifted = false; | ||||
m_screen_scale = vec2(1.f); | |||||
m_target_distance = .0f; | |||||
/* Create a default perspective */ | /* Create a default perspective */ | ||||
SetProjection(mat4::perspective(45.f, 800.f, 600.f, -1000.f, 1000.f)); | SetProjection(mat4::perspective(45.f, 800.f, 600.f, -1000.f, 1000.f)); | ||||
SetView(mat4::lookat(vec3(0.f, 50.f, 50.f), | |||||
vec3(0.f), | |||||
vec3(0.f, 1.f, 0.f))); | |||||
SetView(mat4::lookat(vec3(0.f, 50.f, 50.f), vec3(0.f), vec3(0.f, 1.f, 0.f))); | |||||
} | } | ||||
Camera::~Camera() | Camera::~Camera() | ||||
@@ -53,6 +55,8 @@ Camera::~Camera() | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
//View functions | //View functions | ||||
//-- | //-- | ||||
//WARNING : Don't forget the position | |||||
void Camera::SetView(mat4 const &view) | void Camera::SetView(mat4 const &view) | ||||
{ | { | ||||
m_view_matrix = view; | m_view_matrix = view; | ||||
@@ -68,14 +72,12 @@ void Camera::SetView(vec3 eye, vec3 target, vec3 up) | |||||
void Camera::SetView(vec3 pos, vec3 rot) | void Camera::SetView(vec3 pos, vec3 rot) | ||||
{ | { | ||||
SetView(pos, quat::fromeuler_xyz(rot)); | |||||
SetView(pos, quat::fromeuler_zyx(rot.zyx)); | |||||
} | } | ||||
void Camera::SetView(vec3 pos, quat rot) | void Camera::SetView(vec3 pos, quat rot) | ||||
{ | { | ||||
m_view_matrix = mat4::lookat(pos, | |||||
pos + rot.transform(vec3(0.f, 0.f, -max(m_target_distance, 1.f))), | |||||
rot.transform(vec3(0.f, 1.f, 0.f))); | |||||
m_view_matrix = inverse(mat4(rot)) * mat4::translate(-pos); | |||||
m_position = pos; | m_position = pos; | ||||
} | } | ||||
@@ -104,16 +106,16 @@ void Camera::SetProjection(float fov, float near, float far, float screen_size, | |||||
m_far = far; | m_far = far; | ||||
m_screen_size = screen_size; | m_screen_size = screen_size; | ||||
m_screen_ratio = screen_ratio; | m_screen_ratio = screen_ratio; | ||||
mat4 screen_scale = mat4::scale(vec3(m_screen_scale.xy, 1.f)); | |||||
if (m_fov > .0f) | if (m_fov > .0f) | ||||
{ | { | ||||
if (m_is_shifted) | if (m_is_shifted) | ||||
SetProjection(mat4::shifted_perspective(m_fov, screen_size, screen_ratio, m_far - m_near)); | |||||
SetProjection(screen_scale * mat4::shifted_perspective(m_fov, screen_size, screen_ratio, m_near, m_far)); | |||||
else | else | ||||
SetProjection(mat4::perspective(m_fov, screen_size, screen_size * screen_ratio, m_near, m_far)); | |||||
SetProjection(screen_scale * mat4::perspective(m_fov, screen_size, screen_size * screen_ratio, m_near, m_far)); | |||||
} | } | ||||
else | else | ||||
SetProjection(mat4::ortho(screen_size, screen_size * screen_ratio, m_near, m_far)); | |||||
SetProjection(screen_scale * mat4::ortho(screen_size, screen_size * screen_ratio, m_near, m_far)); | |||||
} | } | ||||
mat4 Camera::GetProjection() | mat4 Camera::GetProjection() | ||||
@@ -149,6 +151,12 @@ void Camera::SetDrawInfos(float near, float far) | |||||
SetProjection(m_fov, near, far, m_screen_size, m_screen_ratio); | SetProjection(m_fov, near, far, m_screen_size, m_screen_ratio); | ||||
} | } | ||||
void Camera::SetScreenScale(vec2 screen_scale) | |||||
{ | |||||
m_screen_scale = screen_scale; | |||||
SetProjection(m_fov, m_near, m_far, m_screen_size, m_screen_ratio); | |||||
} | |||||
void Camera::UseShift(bool should_shift) | void Camera::UseShift(bool should_shift) | ||||
{ | { | ||||
m_is_shifted = should_shift; | m_is_shifted = should_shift; | ||||
@@ -163,28 +171,23 @@ void Camera::UseTarget(bool use_target) | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
//camera manipulation Functions | //camera manipulation Functions | ||||
//-- | //-- | ||||
void Camera::SetPosition(vec3 pos) | |||||
void Camera::SetPosition(vec3 pos, bool keep_target) | |||||
{ | { | ||||
if (m_target_distance > .0f) | |||||
SetView(m_position, m_position + GetTarget(), GetUp()); | |||||
if (keep_target) | |||||
SetView(pos, GetTarget(), GetUp()); | |||||
else | else | ||||
SetView(GetView() * mat4::translate(pos - m_position)); | SetView(GetView() * mat4::translate(pos - m_position)); | ||||
m_position = pos; | m_position = pos; | ||||
} | } | ||||
void Camera::SetTarget(vec3 target) | |||||
void Camera::SetTarget(vec3 target, vec3 up) | |||||
{ | { | ||||
SetView(m_position, target, GetUp()); | |||||
} | |||||
void Camera::SetUp(vec3 up) | |||||
{ | |||||
SetView(m_position, GetTarget(), up); | |||||
SetView(m_position, target, up); | |||||
} | } | ||||
void Camera::SetRotation(vec3 rot) | void Camera::SetRotation(vec3 rot) | ||||
{ | { | ||||
SetRotation(quat::fromeuler_xyz(rot)); | |||||
SetView(m_position, rot); | |||||
} | } | ||||
void Camera::SetRotation(quat rot) | void Camera::SetRotation(quat rot) | ||||
@@ -52,6 +52,7 @@ public: | |||||
void SetScreenInfos(float screen_size, float screen_ratio); | void SetScreenInfos(float screen_size, float screen_ratio); | ||||
void SetDrawInfos(float far); | void SetDrawInfos(float far); | ||||
void SetDrawInfos(float near, float far); | void SetDrawInfos(float near, float far); | ||||
void SetScreenScale(vec2 scale); | |||||
void UseShift(bool should_shift); | void UseShift(bool should_shift); | ||||
void UseTarget(bool use_target); | void UseTarget(bool use_target); | ||||
@@ -60,13 +61,13 @@ public: | |||||
float GetScreenRatio() { return m_screen_ratio; } | float GetScreenRatio() { return m_screen_ratio; } | ||||
float GetNear() { return m_near; } | float GetNear() { return m_near; } | ||||
float GetFar() { return m_far; } | float GetFar() { return m_far; } | ||||
vec2 GetScreenScale() { return m_screen_scale; } | |||||
bool IsShifted() { return m_is_shifted; } | bool IsShifted() { return m_is_shifted; } | ||||
bool IsTargeting() { return (m_target_distance != .0f); } | bool IsTargeting() { return (m_target_distance != .0f); } | ||||
//camera manipulation Functions | //camera manipulation Functions | ||||
void SetPosition(vec3 pos); | |||||
void SetTarget(vec3 target); | |||||
void SetUp(vec3 up); | |||||
void SetPosition(vec3 pos, bool keep_target=false); | |||||
void SetTarget(vec3 target, vec3 up); | |||||
void SetRotation(vec3 rot); | void SetRotation(vec3 rot); | ||||
void SetRotation(quat rot); | void SetRotation(quat rot); | ||||
@@ -96,7 +97,9 @@ private: | |||||
float m_screen_ratio; | float m_screen_ratio; | ||||
float m_near; | float m_near; | ||||
float m_far; | float m_far; | ||||
vec2 m_screen_scale; | |||||
bool m_is_shifted; | bool m_is_shifted; | ||||
bool m_fix_up; | |||||
}; | }; | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -1804,10 +1804,9 @@ template <typename T> struct Mat4 | |||||
/* Helpers for projection matrices */ | /* Helpers for projection matrices */ | ||||
static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far); | static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far); | ||||
static Mat4<T> ortho(T width, T height, T near, T far); | static Mat4<T> ortho(T width, T height, T near, T far); | ||||
static Mat4<T> ortho(T screen_size, T screen_ratio_xy, T draw_distance); | |||||
static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far); | static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far); | ||||
static Mat4<T> perspective(T fov_y, T width, T height, T near, T far); | static Mat4<T> perspective(T fov_y, T width, T height, T near, T far); | ||||
static Mat4<T> shifted_perspective(T fov_y, T screen_size, T screen_ratio_xy, T draw_distance); | |||||
static Mat4<T> shifted_perspective(T fov_y, T screen_size, T screen_ratio_yx, T near, T far); | |||||
void printf() const; | void printf() const; | ||||
@@ -745,11 +745,6 @@ template<> mat4 mat4::ortho(float width, float height, | |||||
-0.5f * height, 0.5f * height, near, far); | -0.5f * height, 0.5f * height, near, far); | ||||
} | } | ||||
template<> mat4 mat4::ortho(float screen_size, float screen_ratio_xy, float draw_distance) | |||||
{ | |||||
return mat4::ortho(screen_size * screen_ratio_xy, screen_size, .00001f, draw_distance); | |||||
} | |||||
template<> mat4 mat4::frustum(float left, float right, float bottom, | template<> mat4 mat4::frustum(float left, float right, float bottom, | ||||
float top, float near, float far) | float top, float near, float far) | ||||
{ | { | ||||
@@ -782,15 +777,15 @@ template<> mat4 mat4::perspective(float fov_y, float width, | |||||
//Returns a perspective matrix with the camera location shifted to be on the near plane | //Returns a perspective matrix with the camera location shifted to be on the near plane | ||||
template<> mat4 mat4::shifted_perspective(float fov_y, float screen_size, | template<> mat4 mat4::shifted_perspective(float fov_y, float screen_size, | ||||
float screen_ratio_xy, float draw_distance) | |||||
float screen_ratio_yx, float near, float far) | |||||
{ | { | ||||
float new_fov_y = fov_y * (F_PI / 180.0f); | float new_fov_y = fov_y * (F_PI / 180.0f); | ||||
float dist_scr = (screen_size * screen_ratio_yx * .5f) / tanf(new_fov_y * .5f); | |||||
float near = (screen_size * .5f) / lol::tan(new_fov_y * .5f); | |||||
float far = near + draw_distance; | |||||
return mat4::perspective(fov_y, screen_size * screen_ratio_xy, screen_size, near - .000001f, far) * | |||||
mat4::translate(.0f, .0f, -near); | |||||
return mat4::perspective(fov_y, screen_size, screen_size * screen_ratio_yx, | |||||
max(.001f, dist_scr + near), | |||||
max(.001f, dist_scr + far)) * | |||||
mat4::translate(.0f, .0f, -dist_scr); | |||||
} | } | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -43,6 +43,45 @@ template <typename T1, typename T2, typename Tf> static inline T1 damp(const T1 | |||||
return lol::lerp(a, b, dt / (dt + x)); | return lol::lerp(a, b, dt / (dt + x)); | ||||
} | } | ||||
template< class T > inline void Swap( T& A, T& B ) | |||||
{ | |||||
const T Temp = A; | |||||
A = B; | |||||
B = Temp; | |||||
} | |||||
//SmoothClamp clamps x in [a - sd, b + sd] and returns a value in [a, b] that is smoothed at the borders. | |||||
static inline float SmoothClamp(float &x, float a, float b, float sd) | |||||
{ | |||||
if (b < a) | |||||
Swap(a, b); | |||||
float tx = x; | |||||
float ta = a - sd; | |||||
float tb = b + sd; | |||||
if (sd > 0.f) | |||||
{ | |||||
if ((b - a) < 2.f * sd) | |||||
sd = .5f * (b - a); | |||||
if (tx < a + sd && tx > a - sd) | |||||
{ | |||||
float t = (tx - a) / sd; | |||||
t = 0.25f * (t + 1.0f) * (t + 1.0f); | |||||
tx = a + t * sd; | |||||
} | |||||
else if (tx < b + sd && tx > b - sd) | |||||
{ | |||||
float t = -(tx - b) / sd; | |||||
t = 0.25f * (t + 1.0f) * (t + 1.0f); | |||||
tx = b - t * sd; | |||||
} | |||||
} | |||||
x = lol::clamp(x, ta, tb); | |||||
return lol::clamp(tx, a, b); | |||||
} | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
#endif // __LOL_NUMERIC_H__ | #endif // __LOL_NUMERIC_H__ | ||||
@@ -295,7 +295,7 @@ public: | |||||
if (m_fov_damp < MIN_FOV) | if (m_fov_damp < MIN_FOV) | ||||
cur_cam->SetProjection(mat4::ortho(screen_size * fov_ratio * 1.1f, 1600.f / 600.f, 1000.f)); | cur_cam->SetProjection(mat4::ortho(screen_size * fov_ratio * 1.1f, 1600.f / 600.f, 1000.f)); | ||||
else if (fov_ratio > .0f) | else if (fov_ratio > .0f) | ||||
cur_cam->SetProjection(mat4::shifted_perspective(m_fov_damp, screen_size * fov_ratio * 1.1f, 1600.f / 600.f, 1000.f)); | |||||
cur_cam->SetProjection(mat4::shifted_perspective(m_fov_damp, screen_size * fov_ratio * 1.1f, 1600.f / 600.f, .00001f, 1000.f)); | |||||
vec3 cam_center = cam_min_max[0] + min_max_diff * .5f; | vec3 cam_center = cam_min_max[0] + min_max_diff * .5f; | ||||
@@ -19,7 +19,7 @@ | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
//Override Gamegroups names for Physic-useage | |||||
//Override Gamegroups names for Physic-usage | |||||
//"_ENT_" means that this is a group for Entities that use EasyPhysic primitives. | //"_ENT_" means that this is a group for Entities that use EasyPhysic primitives. | ||||
//"_EZP_" means that this is a group for EasyPhysic primitives. | //"_EZP_" means that this is a group for EasyPhysic primitives. | ||||
#define GAMEGROUP_ENT_INPUT GAMEGROUP_BEFORE | #define GAMEGROUP_ENT_INPUT GAMEGROUP_BEFORE | ||||