| @@ -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++) | |||