@@ -31,6 +31,14 @@ Camera::Camera() | |||||
m_gamegroup = GAMEGROUP_BEFORE; | m_gamegroup = GAMEGROUP_BEFORE; | ||||
m_drawgroup = DRAWGROUP_CAMERA; | m_drawgroup = DRAWGROUP_CAMERA; | ||||
ivec2 screen_size = Video::GetSize(); | |||||
m_fov = 45.f; | |||||
m_near = -1000.f; | |||||
m_far = 1000.f; | |||||
m_screen_size = (float)screen_size.x; | |||||
m_screen_ratio = (float)screen_size.x / (float)screen_size.y; | |||||
m_is_shifted = false; | |||||
/* 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), | SetView(mat4::lookat(vec3(0.f, 50.f, 50.f), | ||||
@@ -42,6 +50,9 @@ Camera::~Camera() | |||||
{ | { | ||||
} | } | ||||
//----------------------------------------------------------------------------- | |||||
//View functions | |||||
//-- | |||||
void Camera::SetView(mat4 const &view) | void Camera::SetView(mat4 const &view) | ||||
{ | { | ||||
m_view_matrix = view; | m_view_matrix = view; | ||||
@@ -52,6 +63,12 @@ void Camera::SetView(vec3 eye, vec3 target, vec3 up) | |||||
{ | { | ||||
m_view_matrix = mat4::lookat(eye, target, up); | m_view_matrix = mat4::lookat(eye, target, up); | ||||
m_position = eye; | m_position = eye; | ||||
m_target_distance = length(target - m_position); | |||||
} | |||||
void Camera::SetView(vec3 pos, vec3 rot) | |||||
{ | |||||
SetView(pos, quat::fromeuler_xyz(rot)); | |||||
} | } | ||||
void Camera::SetView(vec3 pos, quat rot) | void Camera::SetView(vec3 pos, quat rot) | ||||
@@ -60,16 +77,44 @@ void Camera::SetView(vec3 pos, quat rot) | |||||
pos + rot.transform(vec3(0.f, 0.f, -1.f)), | pos + rot.transform(vec3(0.f, 0.f, -1.f)), | ||||
rot.transform(vec3(0.f, 1.f, 0.f))); | rot.transform(vec3(0.f, 1.f, 0.f))); | ||||
m_position = pos; | m_position = pos; | ||||
m_target_distance = .0f; | |||||
} | |||||
mat4 Camera::GetView() | |||||
{ | |||||
return m_view_matrix; | |||||
} | } | ||||
//----------------------------------------------------------------------------- | |||||
//Projections functions | |||||
//-- | |||||
void Camera::SetProjection(mat4 const &proj) | void Camera::SetProjection(mat4 const &proj) | ||||
{ | { | ||||
m_proj_matrix = proj; | m_proj_matrix = proj; | ||||
} | } | ||||
mat4 Camera::GetView() | |||||
void Camera::SetProjection(float fov, float near, float far) | |||||
{ | { | ||||
return m_view_matrix; | |||||
SetProjection(fov, near, far, m_screen_size, m_screen_ratio); | |||||
} | |||||
void Camera::SetProjection(float fov, float near, float far, float screen_size, float screen_ratio) | |||||
{ | |||||
m_fov = fov; | |||||
m_near = near; | |||||
m_far = far; | |||||
m_screen_size = screen_size; | |||||
m_screen_ratio = screen_ratio; | |||||
if (m_fov > .0f) | |||||
{ | |||||
if (m_is_shifted) | |||||
SetProjection(mat4::shifted_perspective(m_fov, screen_size, screen_ratio, m_far - m_near)); | |||||
else | |||||
SetProjection(mat4::perspective(m_fov, screen_size, screen_size * screen_ratio, m_near, m_far)); | |||||
} | |||||
else | |||||
SetProjection(mat4::ortho(screen_size, screen_size * screen_ratio, m_near, m_far)); | |||||
} | } | ||||
mat4 Camera::GetProjection() | mat4 Camera::GetProjection() | ||||
@@ -77,11 +122,117 @@ mat4 Camera::GetProjection() | |||||
return m_proj_matrix; | return m_proj_matrix; | ||||
} | } | ||||
//----------------------------------------------------------------------------- | |||||
//Projections manipulation functions | |||||
//-- | |||||
void Camera::SetFov(float fov) | |||||
{ | |||||
SetProjection(fov, m_near, m_far, m_screen_size, m_screen_ratio); | |||||
} | |||||
void Camera::SetScreenInfos(float screen_size) | |||||
{ | |||||
SetScreenInfos(screen_size, m_screen_ratio); | |||||
} | |||||
void Camera::SetScreenInfos(float screen_size, float screen_ratio) | |||||
{ | |||||
SetProjection(m_fov, m_near, m_far, screen_size, screen_ratio); | |||||
} | |||||
void Camera::SetDrawInfos(float far) | |||||
{ | |||||
SetDrawInfos(m_near, far); | |||||
} | |||||
void Camera::SetDrawInfos(float near, float far) | |||||
{ | |||||
SetProjection(m_fov, near, far, m_screen_size, m_screen_ratio); | |||||
} | |||||
void Camera::UseShift(bool should_shift) | |||||
{ | |||||
m_is_shifted = should_shift; | |||||
SetProjection(m_fov, m_near, m_far, m_screen_size, m_screen_ratio); | |||||
} | |||||
//----------------------------------------------------------------------------- | |||||
//camera manipulation Functions | |||||
//-- | |||||
void Camera::SetPosition(vec3 pos) | |||||
{ | |||||
if (m_target_distance > .0f) | |||||
{ | |||||
vec4 up = m_view_matrix * vec4(0.f, 1.f, 0.f, 0.f); | |||||
vec4 target = m_view_matrix * vec4(0.f, 0.f, -m_target_distance, 0.f); | |||||
SetView(m_position, m_position + target.xyz, up.xyz); | |||||
} | |||||
else | |||||
m_view_matrix = m_view_matrix * mat4::translate(pos - m_position); | |||||
m_position = pos; | |||||
} | |||||
void Camera::SetTarget(vec3 target) | |||||
{ | |||||
vec4 up = inverse(m_view_matrix) * vec4(0.f, 1.f, 0.f, 0.f); | |||||
SetView(m_position, target, up.xyz); | |||||
} | |||||
void Camera::SetUp(vec3 up) | |||||
{ | |||||
vec4 target = inverse(m_view_matrix) * vec4(0.f, 0.f, -max(m_target_distance, 1.f), 0.f); | |||||
SetView(m_position, m_position + target.xyz, up); | |||||
} | |||||
void Camera::SetRotation(vec3 rot) | |||||
{ | |||||
SetRotation(quat::fromeuler_xyz(rot)); | |||||
} | |||||
void Camera::SetRotation(quat rot) | |||||
{ | |||||
SetView(m_position, rot); | |||||
} | |||||
//-- | |||||
vec3 Camera::GetPosition() | vec3 Camera::GetPosition() | ||||
{ | { | ||||
return m_position; | return m_position; | ||||
} | } | ||||
vec3 Camera::GetTarget() | |||||
{ | |||||
return m_position + (inverse(m_view_matrix) * vec4(0.f, 0.f, -max(m_target_distance, 1.f), 0.f)).xyz; | |||||
} | |||||
vec3 Camera::GetUp() | |||||
{ | |||||
return (inverse(m_view_matrix) * vec4(0.f, 1.f, 0.f, 0.f)).xyz; | |||||
} | |||||
vec3 Camera::GetRotationEuler() | |||||
{ | |||||
return vec3::toeuler(GetRotation()); | |||||
} | |||||
quat Camera::GetRotation() | |||||
{ | |||||
return quat(inverse(m_view_matrix)); | |||||
} | |||||
// Calculate the frustum height at a given distance from the camera. | |||||
float Camera::GetFrustumHeightAtDistance(float distance, float fov) | |||||
{ | |||||
return 2.f * distance * lol::tan(fov * .5f * (F_PI / 180.f)); | |||||
} | |||||
// Calculate the FOV needed to get a given frustum height at a given distance. | |||||
float Camera::GetFOVForHeightAndDistance(float distance, float height) | |||||
{ | |||||
return 2.f * lol::atan(height * .5f / distance) * (180.f / F_PI); | |||||
} | |||||
void Camera::TickGame(float seconds) | void Camera::TickGame(float seconds) | ||||
{ | { | ||||
WorldEntity::TickGame(seconds); | WorldEntity::TickGame(seconds); | ||||
@@ -29,26 +29,74 @@ public: | |||||
char const *GetName() { return "<camera>"; } | char const *GetName() { return "<camera>"; } | ||||
//View functions | |||||
void SetView(mat4 const &view); | void SetView(mat4 const &view); | ||||
void SetView(vec3 eye, vec3 target, vec3 up); | void SetView(vec3 eye, vec3 target, vec3 up); | ||||
void SetView(vec3 pos, vec3 rot); | |||||
void SetView(vec3 pos, quat rot); | void SetView(vec3 pos, quat rot); | ||||
mat4 GetView(); | |||||
//Projections functions | |||||
//private: | |||||
void SetProjection(mat4 const &proj); | void SetProjection(mat4 const &proj); | ||||
public: | |||||
void SetProjection(float fov, float near, float far); | |||||
void SetProjection(float fov, float near, float far, float screen_size, float screen_ratio); | |||||
mat4 GetView(); | |||||
mat4 GetProjection(); | mat4 GetProjection(); | ||||
//Projections manipulation functions | |||||
void SetFov(float fov); | |||||
void SetScreenInfos(float screen_size); | |||||
void SetScreenInfos(float screen_size, float screen_ratio); | |||||
void SetDrawInfos(float far); | |||||
void SetDrawInfos(float near, float far); | |||||
void UseShift(bool should_shift); | |||||
float GetFov() { return m_fov; } | |||||
float GetScreenSize() { return m_screen_size; } | |||||
float GetScreenRatio() { return m_screen_ratio; } | |||||
float GetNear() { return m_near; } | |||||
float GetFar() { return m_far; } | |||||
bool IsShifted() { return m_is_shifted; } | |||||
//camera manipulation Functions | |||||
void SetPosition(vec3 pos); | |||||
void SetTarget(vec3 target); | |||||
void SetUp(vec3 up); | |||||
void SetRotation(vec3 rot); | |||||
void SetRotation(quat rot); | |||||
vec3 GetPosition(); | vec3 GetPosition(); | ||||
vec3 GetTarget(); | |||||
vec3 GetUp(); | |||||
vec3 GetRotationEuler(); | |||||
quat GetRotation(); | |||||
//Convenience functions | |||||
float GetFrustumHeightAtDistance(float distance, float fov); | |||||
float GetFOVForHeightAndDistance(float distance, float height); | |||||
protected: | protected: | ||||
virtual void TickGame(float seconds); | virtual void TickGame(float seconds); | ||||
virtual void TickDraw(float seconds); | virtual void TickDraw(float seconds); | ||||
private: | private: | ||||
mat4 m_view_matrix, m_proj_matrix; | |||||
//Work datas | |||||
mat4 m_view_matrix; | |||||
mat4 m_proj_matrix; | |||||
//Datas used to create above matrix | |||||
float m_target_distance; | |||||
float m_fov; | |||||
float m_screen_size; | |||||
float m_screen_ratio; | |||||
float m_near; | |||||
float m_far; | |||||
bool m_is_shifted; | |||||
}; | }; | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||
#endif /* __CAMERA_H__ */ | #endif /* __CAMERA_H__ */ | ||||
@@ -768,6 +768,7 @@ template<> mat4 mat4::frustum(float left, float right, float bottom, | |||||
return ret; | return ret; | ||||
} | } | ||||
//Returns a standard perspective matrix | |||||
template<> mat4 mat4::perspective(float fov_y, float width, | template<> mat4 mat4::perspective(float fov_y, float width, | ||||
float height, float near, float far) | float height, float near, float far) | ||||
{ | { | ||||
@@ -779,6 +780,7 @@ template<> mat4 mat4::perspective(float fov_y, float width, | |||||
return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far); | return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far); | ||||
} | } | ||||
//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_xy, float draw_distance) | ||||
{ | { | ||||
@@ -787,7 +789,8 @@ template<> mat4 mat4::shifted_perspective(float fov_y, float screen_size, | |||||
float near = (screen_size * .5f) / tanf(new_fov_y * .5f); | float near = (screen_size * .5f) / tanf(new_fov_y * .5f); | ||||
float far = near + draw_distance; | 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_ratio_xy, screen_size, near - .000001f, far) * | |||||
mat4::translate(.0f, .0f, -near); | |||||
} | } | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -38,6 +38,7 @@ using namespace lol::phys; | |||||
#define ZERO_SPEED 3.5f | #define ZERO_SPEED 3.5f | ||||
#define JUMP_HEIGHT 30.f | #define JUMP_HEIGHT 30.f | ||||
#define JUMP_STRAFE .5f | #define JUMP_STRAFE .5f | ||||
#define TARGET_TIMER 10.f + (rand(4.f) - 2.f) | |||||
int gNumObjects = 64; | int gNumObjects = 64; | ||||
@@ -83,12 +84,14 @@ BtPhysTest::BtPhysTest(bool editor) | |||||
m_camera->SetView(vec3(70.f, 50.f, 0.f), | m_camera->SetView(vec3(70.f, 50.f, 0.f), | ||||
vec3(0.f, 0.f, 0.f), | vec3(0.f, 0.f, 0.f), | ||||
vec3(0, 1, 0)); | vec3(0, 1, 0)); | ||||
m_camera->SetProjection(mat4::perspective(60.f, (float)Video::GetSize().x, (float)Video::GetSize().y, .1f, 1000.f)); | |||||
m_camera->SetProjection(60.f, .1f, 1000.f, (float)Video::GetSize().x, (float)Video::GetSize().y / (float)Video::GetSize().x); | |||||
m_target_timer = TARGET_TIMER; | |||||
m_cam_target = -1; | |||||
#else | #else | ||||
m_camera->SetView(vec3(50.f, 50.f, 0.f), | m_camera->SetView(vec3(50.f, 50.f, 0.f), | ||||
vec3(0.f, 0.f, 0.f), | vec3(0.f, 0.f, 0.f), | ||||
vec3(0, 1, 0)); | vec3(0, 1, 0)); | ||||
m_camera->SetProjection(mat4::perspective(45.f, (float)Video::GetSize().x, (float)Video::GetSize().y, .1f, 1000.f)); | |||||
m_camera->SetProjection(45.f, .1f, 1000.f, (float)Video::GetSize().x, (float)Video::GetSize().y / (float)Video::GetSize().x); | |||||
#endif | #endif | ||||
g_scene->PushCamera(m_camera); | g_scene->PushCamera(m_camera); | ||||
@@ -304,10 +307,19 @@ void BtPhysTest::TickGame(float seconds) | |||||
vec3 cam_center(0.f); | vec3 cam_center(0.f); | ||||
float cam_factor = .0f; | float cam_factor = .0f; | ||||
vec2 screen_min_max[2] = { vec2(FLT_MAX), vec2(-FLT_MAX) }; | vec2 screen_min_max[2] = { vec2(FLT_MAX), vec2(-FLT_MAX) }; | ||||
vec3 cam_min_max[2] = { vec3(FLT_MAX), vec3(-FLT_MAX) }; | |||||
mat4 world_cam = g_scene->GetCamera()->GetView(); | mat4 world_cam = g_scene->GetCamera()->GetView(); | ||||
mat4 cam_screen = g_scene->GetCamera()->GetProjection(); | mat4 cam_screen = g_scene->GetCamera()->GetProjection(); | ||||
m_target_timer -= seconds; | |||||
if (m_target_timer < .0f) | |||||
{ | |||||
m_target_timer = TARGET_TIMER; | |||||
if (m_cam_target == -1) | |||||
m_cam_target = rand(m_physobj_list.Count()); | |||||
else | |||||
m_cam_target = -1; | |||||
} | |||||
for (int i = 0; i < m_physobj_list.Count(); i++) | for (int i = 0; i < m_physobj_list.Count(); i++) | ||||
{ | { | ||||
PhysicsObject* PhysObj = m_physobj_list[i].m1; | PhysicsObject* PhysObj = m_physobj_list[i].m1; | ||||
@@ -315,22 +327,33 @@ void BtPhysTest::TickGame(float seconds) | |||||
vec3 obj_loc = PhysObj->GetPhysic()->GetTransform().v3.xyz; | vec3 obj_loc = PhysObj->GetPhysic()->GetTransform().v3.xyz; | ||||
cam_center += obj_loc; | |||||
cam_factor += 1.f; | |||||
if (m_cam_target == -1 || m_cam_target == i) | |||||
{ | |||||
cam_center += obj_loc; | |||||
cam_factor += 1.f; | |||||
mat4 LocalPos = mat4::translate(obj_loc); | |||||
vec3 vpos; | |||||
mat4 LocalPos = mat4::translate(obj_loc); | |||||
vec3 vpos; | |||||
LocalPos = world_cam * LocalPos; | |||||
vpos = LocalPos.v3.xyz; | |||||
cam_min_max[0] = min(vpos.xyz, cam_min_max[0]); | |||||
cam_min_max[1] = max(vpos.xyz, cam_min_max[1]); | |||||
LocalPos = world_cam * LocalPos; | |||||
mat4 LocalPos0 = LocalPos; | |||||
LocalPos = cam_screen * LocalPos; | |||||
vpos = (LocalPos.v3 / LocalPos.v3.w).xyz; | |||||
screen_min_max[0] = min(vpos.xy, screen_min_max[0]); | |||||
screen_min_max[1] = max(vpos.xy, screen_min_max[1]); | |||||
int j = 2; | |||||
while (j-- > 0) | |||||
{ | |||||
if (j == 1) | |||||
LocalPos = mat4::translate(vec3(-4.f)) * LocalPos0; | |||||
else | |||||
LocalPos = mat4::translate(vec3(4.f)) * LocalPos0; | |||||
LocalPos = cam_screen * LocalPos; | |||||
vpos = (LocalPos.v3 / LocalPos.v3.w).xyz; | |||||
screen_min_max[0] = min(vpos.xy, screen_min_max[0]); | |||||
screen_min_max[1] = max(vpos.xy, screen_min_max[1]); | |||||
} | |||||
} | |||||
//Jump handling | |||||
//if (length(PhysObj->GetPhysic()->GetLinearVelocity()) < ZERO_SPEED) | //if (length(PhysObj->GetPhysic()->GetLinearVelocity()) < ZERO_SPEED) | ||||
if (lol::abs(PhysObj->GetPhysic()->GetLinearVelocity().y) < ZERO_SPEED) | if (lol::abs(PhysObj->GetPhysic()->GetLinearVelocity().y) < ZERO_SPEED) | ||||
Timer -= seconds; | Timer -= seconds; | ||||
@@ -345,16 +368,29 @@ void BtPhysTest::TickGame(float seconds) | |||||
} | } | ||||
} | } | ||||
vec3 min_max_diff = (cam_min_max[1] - cam_min_max[0]); | |||||
float screen_size = max(max(lol::abs(min_max_diff.x), lol::abs(min_max_diff.y)), | |||||
max( lol::abs(min_max_diff.x), lol::abs(min_max_diff.y))); | |||||
float fov_ratio = max(max(lol::abs(screen_min_max[0].x), lol::abs(screen_min_max[0].y)), | float fov_ratio = max(max(lol::abs(screen_min_max[0].x), lol::abs(screen_min_max[0].y)), | ||||
max(lol::abs(screen_min_max[1].x), lol::abs(screen_min_max[1].y))); | max(lol::abs(screen_min_max[1].x), lol::abs(screen_min_max[1].y))); | ||||
//m_camera->SetProjection(mat4::perspective(30.f * fov_ratio * 1.1f, 1280.f, 960.f, .1f, 1000.f)); | |||||
vec3 new_target = cam_center / cam_factor; | |||||
float fov_dp = .0f; | |||||
float loc_dp = .0f; | |||||
//ideally fov is on the target | |||||
if (lol::abs(fov_ratio - 1.f) < .2f) | |||||
fov_dp = ((m_cam_target == -1)?(.7f):(.2f)); | |||||
else | |||||
fov_dp = ((m_cam_target == -1)?(1.7f):(.9f)); | |||||
//ideally loc is on the target | |||||
if (length(new_target - m_camera->GetTarget()) < 6.f) | |||||
loc_dp = ((m_cam_target == -1)?(.5f):(.03f)); | |||||
else | |||||
loc_dp = ((m_cam_target == -1)?(.9f):(.5f)); | |||||
m_camera->SetFov(damp(m_camera->GetFov(), m_camera->GetFov() * fov_ratio * 1.1f, fov_dp, seconds)); | |||||
vec3 tmp = damp(m_camera->GetTarget(), new_target, loc_dp, seconds); | |||||
m_camera->SetView((mat4::rotate(10.f * seconds, vec3(.0f, 1.f, .0f)) * vec4(m_camera->GetPosition(), 1.0f)).xyz, | m_camera->SetView((mat4::rotate(10.f * seconds, vec3(.0f, 1.f, .0f)) * vec4(m_camera->GetPosition(), 1.0f)).xyz, | ||||
//vec3(70.f, 30.f, 0.f), | |||||
cam_center / cam_factor, vec3(0, 1, 0)); | |||||
tmp, vec3(0, 1, 0)); | |||||
#endif //USE_BODIES | #endif //USE_BODIES | ||||
#endif //CAT_MODE | #endif //CAT_MODE | ||||
@@ -73,6 +73,8 @@ private: | |||||
Array<PhysicsObject*> m_stairs_list; | Array<PhysicsObject*> m_stairs_list; | ||||
float m_loop_value; | float m_loop_value; | ||||
float m_target_timer; | |||||
int m_cam_target; | |||||
}; | }; | ||||
#endif // __BTPHYSTEST_H__ | #endif // __BTPHYSTEST_H__ | ||||
@@ -77,7 +77,7 @@ void main(void) | |||||
vec4 color = texture2D(in_texture, texcoord) * pass_color; | vec4 color = texture2D(in_texture, texcoord) * pass_color; | ||||
//need 130 : ivec2 tex_size = textureSize(in_texture, 0); | //need 130 : ivec2 tex_size = textureSize(in_texture, 0); | ||||
int sample_nb = 5; | |||||
int sample_nb = 2; | |||||
if (color.a < 0.9) | if (color.a < 0.9) | ||||
{ | { | ||||
for (int x = -sample_nb; x <= sample_nb; x++) | for (int x = -sample_nb; x <= sample_nb; x++) | ||||