@@ -31,6 +31,14 @@ Camera::Camera() | |||
m_gamegroup = GAMEGROUP_BEFORE; | |||
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 */ | |||
SetProjection(mat4::perspective(45.f, 800.f, 600.f, -1000.f, 1000.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) | |||
{ | |||
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_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) | |||
@@ -60,16 +77,44 @@ void Camera::SetView(vec3 pos, quat rot) | |||
pos + rot.transform(vec3(0.f, 0.f, -1.f)), | |||
rot.transform(vec3(0.f, 1.f, 0.f))); | |||
m_position = pos; | |||
m_target_distance = .0f; | |||
} | |||
mat4 Camera::GetView() | |||
{ | |||
return m_view_matrix; | |||
} | |||
//----------------------------------------------------------------------------- | |||
//Projections functions | |||
//-- | |||
void Camera::SetProjection(mat4 const &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() | |||
@@ -77,11 +122,117 @@ mat4 Camera::GetProjection() | |||
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() | |||
{ | |||
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) | |||
{ | |||
WorldEntity::TickGame(seconds); | |||
@@ -29,26 +29,74 @@ public: | |||
char const *GetName() { return "<camera>"; } | |||
//View functions | |||
void SetView(mat4 const &view); | |||
void SetView(vec3 eye, vec3 target, vec3 up); | |||
void SetView(vec3 pos, vec3 rot); | |||
void SetView(vec3 pos, quat rot); | |||
mat4 GetView(); | |||
//Projections functions | |||
//private: | |||
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(); | |||
//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 GetTarget(); | |||
vec3 GetUp(); | |||
vec3 GetRotationEuler(); | |||
quat GetRotation(); | |||
//Convenience functions | |||
float GetFrustumHeightAtDistance(float distance, float fov); | |||
float GetFOVForHeightAndDistance(float distance, float height); | |||
protected: | |||
virtual void TickGame(float seconds); | |||
virtual void TickDraw(float seconds); | |||
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 */ | |||
#endif /* __CAMERA_H__ */ | |||
@@ -768,6 +768,7 @@ template<> mat4 mat4::frustum(float left, float right, float bottom, | |||
return ret; | |||
} | |||
//Returns a standard perspective matrix | |||
template<> mat4 mat4::perspective(float fov_y, float width, | |||
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); | |||
} | |||
//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, | |||
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 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 */ | |||
@@ -38,6 +38,7 @@ using namespace lol::phys; | |||
#define ZERO_SPEED 3.5f | |||
#define JUMP_HEIGHT 30.f | |||
#define JUMP_STRAFE .5f | |||
#define TARGET_TIMER 10.f + (rand(4.f) - 2.f) | |||
int gNumObjects = 64; | |||
@@ -83,12 +84,14 @@ BtPhysTest::BtPhysTest(bool editor) | |||
m_camera->SetView(vec3(70.f, 50.f, 0.f), | |||
vec3(0.f, 0.f, 0.f), | |||
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 | |||
m_camera->SetView(vec3(50.f, 50.f, 0.f), | |||
vec3(0.f, 0.f, 0.f), | |||
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 | |||
g_scene->PushCamera(m_camera); | |||
@@ -304,10 +307,19 @@ void BtPhysTest::TickGame(float seconds) | |||
vec3 cam_center(0.f); | |||
float cam_factor = .0f; | |||
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 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++) | |||
{ | |||
PhysicsObject* PhysObj = m_physobj_list[i].m1; | |||
@@ -315,22 +327,33 @@ void BtPhysTest::TickGame(float seconds) | |||
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 (lol::abs(PhysObj->GetPhysic()->GetLinearVelocity().y) < ZERO_SPEED) | |||
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)), | |||
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, | |||
//vec3(70.f, 30.f, 0.f), | |||
cam_center / cam_factor, vec3(0, 1, 0)); | |||
tmp, vec3(0, 1, 0)); | |||
#endif //USE_BODIES | |||
#endif //CAT_MODE | |||
@@ -73,6 +73,8 @@ private: | |||
Array<PhysicsObject*> m_stairs_list; | |||
float m_loop_value; | |||
float m_target_timer; | |||
int m_cam_target; | |||
}; | |||
#endif // __BTPHYSTEST_H__ | |||
@@ -77,7 +77,7 @@ void main(void) | |||
vec4 color = texture2D(in_texture, texcoord) * pass_color; | |||
//need 130 : ivec2 tex_size = textureSize(in_texture, 0); | |||
int sample_nb = 5; | |||
int sample_nb = 2; | |||
if (color.a < 0.9) | |||
{ | |||
for (int x = -sample_nb; x <= sample_nb; x++) | |||