Browse Source

btphystest : added new camera functions. Added funny camera stuff for cat simulation.

undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> 11 years ago
parent
commit
876f62228c
6 changed files with 268 additions and 28 deletions
  1. +153
    -2
      src/camera.cpp
  2. +51
    -3
      src/camera.h
  3. +4
    -1
      src/math/vector.cpp
  4. +57
    -21
      test/btphystest.cpp
  5. +2
    -0
      test/btphystest.h
  6. +1
    -1
      test/front_camera_sprite.lolfx

+ 153
- 2
src/camera.cpp View File

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


+ 51
- 3
src/camera.h View File

@@ -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__ */


+ 4
- 1
src/math/vector.cpp View File

@@ -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 */


+ 57
- 21
test/btphystest.cpp View File

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




+ 2
- 0
test/btphystest.h View File

@@ -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__


+ 1
- 1
test/front_camera_sprite.lolfx View File

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


Loading…
Cancel
Save