Browse Source

MeshViewer :

- Added file handling with new mesh generation each time the buffer file is updated (that's not very pretty, but it works).
- Added multiple mesh viewing with "history" and some basic camera movement (it uses the keypad for now, not very sam friendly, I know).
legacy
Benjamin ‘Touky’ Huet touky 11 years ago
parent
commit
157e67c2be
2 changed files with 312 additions and 90 deletions
  1. +311
    -90
      test/MeshViewer.cpp
  2. +1
    -0
      test/MeshViewerBuffer.txt

+ 311
- 90
test/MeshViewer.cpp View File

@@ -1,3 +1,4 @@

//
// Lol Engine - EasyMesh tutorial
//
@@ -19,31 +20,91 @@

using namespace std;
using namespace lol;
#define MESH_DIST 5.0f

#define IPT_CAM_RESET "Cam_Center"
#define IPT_CAM_FORWARD "Cam_Forward"
#define IPT_CAM_BACKWARD "Cam_Backward"
#define IPT_CAM_ZOOM_OUT "Cam_Zoom_In"
#define IPT_CAM_ZOOM_IN "Cam_Zoom_Out"

#define IPT_MESH_UPDATE "Mesh_Update"
#define IPT_MESH_RESET "Mesh_Reset"

#define IPT_MESH_LEFT "Mesh_Left"
#define IPT_MESH_RIGHT "Mesh_Right"
#define IPT_MESH_UP "Mesh_Up"
#define IPT_MESH_DOWN "Mesh_Down"
#define IPT_MESH_SCALE_UP "Mesh_Scale_Up"
#define IPT_MESH_SCALE_DOWN "Mesh_Scale_Down"
#define IPT_MESH_OFFSET_UP "Mesh_Offset_Up"
#define IPT_MESH_OFFSET_DOWN "Mesh_Offset_Down"
#define IPT_MESH_ROT_LEFT "Mesh_Rot_Left"
#define IPT_MESH_ROT_RIGHT "Mesh_Rot_Right"
#define IPT_MESH_ROT_UP "Mesh_Rot_Up"
#define IPT_MESH_ROT_DOWN "Mesh_Rot_Down"

class MeshViewer : public WorldEntity
{
public:
MeshViewer()
void SetFov(float new_fov=60.0f)
{
int i=10;
while (i--)
{
m_meshes.Push(EasyMesh());
m_meshes.Last().Compile("[sc#2f2 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#22f ab 2 2 2 tx 0 csgu]]");
}
//FOV compensation doesn't work
ivec2 video_size = Video::GetSize();
float near = -video_size.x - video_size.y;
float far = video_size.x + video_size.y;
float t1 = tanf(new_fov / 2);
float dist = video_size.x / (2.0f * t1);
//m_fov_compensation = mat4::translate(-0.5f * video_size.x, -0.5f * video_size.y, -dist);
m_fov_compensation = mat4::translate(vec3(.0f));
if (new_fov > 0.1f)
m_camera->SetPerspective(new_fov, (float)video_size.x, (float)video_size.y, .1f, 1000.f);
else
m_camera->SetOrtho((float)video_size.x, (float)video_size.y, .1f, 1000.f);
}

MeshViewer(char *file_buffer = "MeshViewerBuffer.txt")
{
//Input setup
Input::LinkActionToKey(IPT_CAM_RESET, Key::Return);
Input::LinkActionToKey(IPT_CAM_FORWARD, Key::PageUp);
Input::LinkActionToKey(IPT_CAM_BACKWARD, Key::PageDown);
Input::LinkActionToKey(IPT_CAM_ZOOM_IN, Key::Home);
Input::LinkActionToKey(IPT_CAM_ZOOM_OUT, Key::End);

Input::LinkActionToKey(IPT_MESH_LEFT, Key::Left);
Input::LinkActionToKey(IPT_MESH_RIGHT, Key::Right);
Input::LinkActionToKey(IPT_MESH_UP, Key::Up);
Input::LinkActionToKey(IPT_MESH_DOWN, Key::Down);

Input::LinkActionToKey(IPT_MESH_UPDATE, Key::Space);
Input::LinkActionToKey(IPT_MESH_RESET, Key::KP0);

Input::LinkActionToKey(IPT_MESH_OFFSET_DOWN, Key::KP1);
Input::LinkActionToKey(IPT_MESH_OFFSET_UP, Key::KP3);
Input::LinkActionToKey(IPT_MESH_SCALE_DOWN, Key::KP7);
Input::LinkActionToKey(IPT_MESH_SCALE_UP, Key::KP9);

Input::LinkActionToKey(IPT_MESH_ROT_LEFT, Key::KP4);
Input::LinkActionToKey(IPT_MESH_ROT_RIGHT, Key::KP6);
Input::LinkActionToKey(IPT_MESH_ROT_UP, Key::KP8);
Input::LinkActionToKey(IPT_MESH_ROT_DOWN, Key::KP5);
m_angle = 0;

//Camera Setup
m_fov_zoom_damp = .0f;
m_fov_damp = 60.0f;
m_fov = 60.0f;
m_camera = new Camera(vec3(0.f, 600.f, 0.f),
vec3(0.f, 0.f, 0.f),
vec3(0, 1, 0));
m_camera->SetPerspective(60.f, 16, 9, .1f, 1000.f);
SetFov(m_fov_damp);
m_camera->SetTarget(vec3(0.f, 0.f, 0.f));
m_camera->SetPosition(vec3(0.f, 0.f, 5.f));
m_camera->SetPosition(vec3(0.f, 0.f, 10.f));
m_camera->ForceSceneUpdate();
Ticker::Ref(m_camera);

//Lights setup
m_lights << new Light();
m_lights.Last()->SetPosition(vec4(4.f, -1.f, -4.f, 0.f));
m_lights.Last()->SetColor(vec4(.0f, .2f, .5f, 1.f));
@@ -54,10 +115,39 @@ public:
m_lights.Last()->SetColor(vec4(.5f, .3f, .0f, 1.f));
Ticker::Ref(m_lights.Last());

min_pos = vec3(FLT_MAX);
max_pos = vec3(-FLT_MAX);
//Speed damp
m_mesh_rotate_damp = vec2(.0f);
m_mesh_screen_move_damp = vec2(.0f);
m_mesh_move_damp = vec2(.0f);

//Actual values
SetDefaultMeshTransform();

//Actual values damp
m_mesh_rotation_damp = vec2(.0f);
m_mesh_screen_offset_damp = vec2(.0f);
m_mesh_offset_damp = vec2(.0f);


m_ready = false;
m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
mat4::rotate(m_angle, vec3(0, 1, 0)) *
mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));

//File management
#ifdef HAVE_STDIO_H
m_file_buffer = fopen("MeshViewerBuffer.txt", "r");

if (!m_file_buffer)
Ticker::Shutdown();
#else //Full FAIL, kill the viewer
Ticker::Shutdown();
#endif

m_last_stream_size = 0;
m_last_stream_cmd << 0;

m_stream_update_time = 0.0f;
m_stream_update_timer = 1.0f;
}

~MeshViewer()
@@ -65,71 +155,157 @@ public:
Ticker::Unref(m_camera);
for (int i = 0; i < m_lights.Count(); ++i)
Ticker::Unref(m_lights[i]);
#ifdef HAVE_STDIO_H
fclose(m_file_buffer);
#endif
}

void SetDefaultMeshTransform()
{
m_mesh_rotation = vec2(25.0f, .0f);
m_mesh_screen_offset = vec2(.54f, .0f);
m_mesh_offset = vec2(-.64f, .07f);
}
virtual void TickGame(float seconds)
{
WorldEntity::TickGame(seconds);
//vec4 vertex = in_ModelView * vec4(in_Vertex, 1.0);
// gl_Position = in_Proj * vertex;


m_angle += seconds * 70.0f;
m_mat = mat4::rotate(m_angle, vec3(0, 1, 0));

//mat4 screen_matrix = Scene::GetDefault()->GetProjMatrix() * Scene::GetDefault()->GetViewMatrix();
mat4 world_view_matrix = m_camera->GetViewMatrix() * m_mat;
mat4 world_screen_matrix = m_camera->GetProjMatrix() * world_view_matrix;
mat4 view_world_matrix = inverse(m_camera->GetViewMatrix());
mat4 screen_view_matrix = inverse(m_camera->GetProjMatrix());
vec4 a(0, 2, 0, 1.0f);
vec4 b(0,-2, 0, 1.0f);
vec4 c(0, 0, -2, 1.0f);
vec4 d(-1, -1, 1, 1.0f);

//vec2 toto;
//near plane : vec4(toto, 1.f, 1.f);
//far plane : vec4(toto, -1.f, 1.f);

a = vec4((world_screen_matrix * a).xyz / a.w, a.w);
b = vec4((world_screen_matrix * b).xyz / b.w, b.w);
c = vec4((inverse(world_screen_matrix) * c).xyz / c.w, c.w);
d = vec4((inverse(world_screen_matrix) * d).xyz / d.w, d.w);
a = b;
c = d;

//this is the algorithm for a camera that must keep n target in the screen

//Shutdown logic
if (Input::WasReleased(Key::Escape))
Ticker::Shutdown();

//Update Mesh BBox - Get the Min/Max needed
vec3 min_max[2] = { vec3(FLT_MAX), vec3(-FLT_MAX) };
int mesh_id = m_meshes.Count() - 1;
for (; mesh_id >= 0; mesh_id--)
if (m_meshes[mesh_id].m2)
break;

if (m_meshes.Count() && mesh_id >= 0)
{
//Get the Min/Max needed
vec3 new_min_pos(FLT_MAX);
vec3 new_max_pos(-FLT_MAX);
for (int i = 0; i < m_meshes.Last().GetVertexCount(); i++)
for (int i = 0; i < m_meshes[mesh_id].m1.GetVertexCount(); i++)
{
vec4 vpos = world_view_matrix * vec4(m_meshes.Last().GetVertexLocation(i), 1.0f);
new_min_pos = min(vpos.xyz, new_min_pos);
new_max_pos = max(vpos.xyz, new_max_pos);
vec3 vpos = m_meshes[mesh_id].m1.GetVertexLocation(i);
min_max[0] = min(vpos.xyz, min_max[0]);
min_max[1] = max(vpos.xyz, min_max[1]);
}
}
else
{
min_max[0] = vec3(.0f);
min_max[1] = vec3(.0f);
}
//[0] : center, [1] : size.
vec3 BBox[2] = { vec3(.0f), vec3(.0f) };
BBox[1] = min_max[1] - min_max[0];
BBox[0] = min_max[0] + BBox[1] * .5f;
vec3 BBox_mod = BBox[1];

//--
//Camera movement handling
//--
vec3 cam_move = BBox_mod * seconds *
vec3(.0f, .0f, (float)(Input::GetStatus(IPT_CAM_BACKWARD) - Input::GetStatus(IPT_CAM_FORWARD)));

if (Input::WasReleased(IPT_CAM_RESET))
SetFov();

float fov_zoom = (float)(Input::GetStatus(IPT_CAM_ZOOM_OUT) - Input::GetStatus(IPT_CAM_ZOOM_IN));
m_fov_zoom_damp = damp(m_fov_zoom_damp, fov_zoom, (fov_zoom == .0f)?(.15f):(0.5f), seconds);
m_fov = max(.0f, m_fov + seconds * 10.0f * m_fov_zoom_damp);
m_fov_damp = damp(m_fov_damp, m_fov, .2f, seconds);
SetFov(m_fov_damp);

m_camera->SetPosition(m_camera->GetPosition() + cam_move);
m_camera->SetTarget(m_camera->GetPosition() + vec3(0, 0, -5.0f));

//--
//Mesh movement handling
//--
if (Input::WasReleased(IPT_MESH_RESET))
SetDefaultMeshTransform();

vec2 new_move = vec2(.0f);

new_move = vec2((float)(Input::GetStatus(IPT_MESH_RIGHT) - Input::GetStatus(IPT_MESH_LEFT)),
(float)(Input::GetStatus(IPT_MESH_UP) - Input::GetStatus(IPT_MESH_DOWN)));
m_mesh_screen_move_damp = vec2(damp(m_mesh_screen_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
damp(m_mesh_screen_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));

new_move = vec2((float)(Input::GetStatus(IPT_MESH_OFFSET_UP) - Input::GetStatus(IPT_MESH_OFFSET_DOWN)),
(float)(Input::GetStatus(IPT_MESH_SCALE_UP) - Input::GetStatus(IPT_MESH_SCALE_DOWN)));
m_mesh_move_damp = vec2(damp(m_mesh_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
damp(m_mesh_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));

new_move = vec2((float)(Input::GetStatus(IPT_MESH_ROT_UP) - Input::GetStatus(IPT_MESH_ROT_DOWN)),
(float)(Input::GetStatus(IPT_MESH_ROT_RIGHT) - Input::GetStatus(IPT_MESH_ROT_LEFT)));
m_mesh_rotate_damp = vec2(damp(m_mesh_rotate_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
damp(m_mesh_rotate_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));

vec2 mesh_screen_move = seconds * 0.6f * m_mesh_screen_move_damp;
vec2 mesh_offset_move = seconds * vec2(.6f, .2f) * m_mesh_move_damp;
vec2 mesh_rotate = seconds * vec2(40.0f, 60.0f) * m_mesh_rotate_damp;

//Add movement
m_mesh_screen_offset += mesh_screen_move;
m_mesh_offset += mesh_offset_move;
m_mesh_rotation += mesh_rotate;

//Compute damp
m_mesh_rotation_damp = damp(m_mesh_rotation_damp, m_mesh_rotation, .2f, seconds);
m_mesh_screen_offset_damp = damp(m_mesh_screen_offset_damp, m_mesh_screen_offset, .2f, seconds);
m_mesh_offset_damp = damp(m_mesh_offset_damp, m_mesh_offset, .2f, seconds);

//Clamp necessary
m_mesh_rotation.x = clamp(m_mesh_rotation.x, -90.0f, 90.0f);
m_mesh_offset.y = max(.0f, m_mesh_offset.y);

//m_angle += seconds * 70.0f;
m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
mat4::rotate(m_angle, vec3(0, 1, 0)) *
mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));

//--
//File management
//--
if (Input::WasReleased(IPT_MESH_UPDATE))
m_stream_update_time = m_stream_update_timer + 1.0f;
m_stream_update_time += seconds;

#ifdef HAVE_STDIO_H
// obtain file size:
fseek(m_file_buffer, 0 , SEEK_END);
long new_stream_size = ftell(m_file_buffer);
rewind(m_file_buffer);
#else
long new_stream_size = 0;
#endif

if (new_stream_size && (new_stream_size != m_last_stream_size || m_stream_update_time > m_stream_update_timer))
{
Array<char> new_stream_cmd;
m_stream_update_time = .0f;

//Reserve the needed datas & read the file
new_stream_cmd.Resize((int)new_stream_size);
#ifdef HAVE_STDIO_H
size_t result = fread(&new_stream_cmd[0], 1, new_stream_size, m_file_buffer);
#else
#endif

//Actual camera algorithm
//if the new cmd is different from the previous one
if (new_stream_cmd.Count() != m_last_stream_cmd.Count() ||
strcmp(&new_stream_cmd[0], &m_last_stream_cmd[0]))
{
vec4 BottomLeft = m_camera->GetProjMatrix() * vec4(new_min_pos.xy, new_min_pos.z, 1.0f);
vec4 TopRight = m_camera->GetProjMatrix() * vec4(new_max_pos.xy, new_min_pos.z, 1.0f);
BottomLeft = vec4(BottomLeft.xyz / BottomLeft.w, BottomLeft.w);
TopRight = vec4(TopRight.xyz / TopRight.w, TopRight.w);
//vec2 NewSize = TopRight.xy - BottomLeft.xy;
//NewSize.x = max(NewSize.x, NewSize.y) * 1.5f;
vec4 DistantPoint = screen_view_matrix * vec4(vec2(1.0f, 1.0f), TopRight.z * TopRight.w, TopRight.w);

vec3 vcenter = vec3(new_min_pos.xy + new_max_pos.xy, .0f) * .5f;
vec4 new_pos = screen_view_matrix * vec4(.0f, .0f, new_min_pos.z, 1.0f);
//vcenter.z += (new_pos.z - new_pos.z * NewSize.x);
vcenter = (view_world_matrix * vec4(vcenter, 1.0f)).xyz;

m_camera->SetPosition(damp(m_camera->GetPosition(), vcenter, 0.4f, seconds));
//m_camera->SetPosition(vcenter);
m_camera->SetTarget(m_camera->GetPosition() + vec3(0, 0, -5.0f));
//store the current datas
m_last_stream_cmd = new_stream_cmd;
m_last_stream_size = new_stream_size;

//Create a new mesh
m_meshes.Push(EasyMesh(), false, .0f, vec3(.0f));
m_meshes.Last().m1.Compile(&new_stream_cmd[0]);
}
//
}
}

@@ -137,46 +313,91 @@ public:
{
WorldEntity::TickDraw(seconds);

if (!m_ready)
for (int i = 0; i < m_meshes.Count(); i++)
{
for (int i = 0; i < m_meshes.Count(); i++)
m_meshes[i].MeshConvert();
m_ready = true;
if (!m_meshes[i].m2)
{
m_meshes[i].m1.MeshConvert();
m_meshes[i].m2 = true;
}
}

Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

m_mat = mat4::translate(vec3(m_meshes.Count() * MESH_DIST * 0.5f, 0, m_meshes.Count() * MESH_DIST) * -1.0f) * m_mat;
mat4 default_proj = Scene::GetDefault()->GetProjMatrix();
for (int i = 0; i < m_meshes.Count(); i++)
{
m_mat = mat4::translate(vec3(MESH_DIST * 0.5f, 0, MESH_DIST)) * m_mat;
m_meshes[i].Render(m_mat);
Video::Clear(ClearMask::Depth);
float new_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (i + 1))));
m_meshes[i].m3 = damp(m_meshes[i].m3, new_scale, .35f, seconds);
if (m_meshes[i].m3 > .0f)
{
vec3 new_mesh_offset = vec3(.0f);
for (int j = m_meshes.Count() - 1; j > i; j--)
{
float ofs_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (j + 0))));
new_mesh_offset = new_mesh_offset + vec3(m_meshes[j].m3 * ofs_scale * ofs_scale * m_mesh_offset_damp.x, .0f, .0f);
}
m_meshes[i].m4 = damp(m_meshes[i].m4, new_mesh_offset, .35f, seconds);
Scene::GetDefault()->SetProjMatrix(mat4::translate(m_meshes[i].m4) *
mat4::translate(vec3(m_mesh_screen_offset_damp, .0f)) *
mat4::scale(vec3(vec2(m_meshes[i].m3), 1.0f)) *
default_proj *
m_fov_compensation);
m_meshes[i].m1.Render(m_mat);
Video::Clear(ClearMask::Depth);
}
}
//m_mat = mat4::translate(vec3(.0f));
//m_meshes.Last().Render(m_mat);
Scene::GetDefault()->SetProjMatrix(default_proj);
}

private:
//Array<EasyMesh, mat4, float> m_gears;
float m_angle;
mat4 m_mat;
vec3 min_pos;
vec3 max_pos;

Array<EasyMesh> m_meshes;
Array<Light *> m_lights;
Camera *m_camera;

bool m_ready;
float m_angle;
mat4 m_mat;

//Mesh infos
//Move damping
vec2 m_mesh_rotate_damp;
vec2 m_mesh_screen_move_damp;
vec2 m_mesh_move_damp;

//Move transform damping
vec2 m_mesh_rotation_damp;
vec2 m_mesh_screen_offset_damp;
vec2 m_mesh_offset_damp;

vec2 m_mesh_rotation; //Meshes rotation
vec2 m_mesh_screen_offset;//Meshes screen offset
vec2 m_mesh_offset; //Mesh Offset after first mesh (x: offset, y: scale)

//File data
#ifdef HAVE_STDIO_H
FILE * m_file_buffer;
#endif
long m_last_stream_size;
Array<char> m_last_stream_cmd;
float m_stream_update_time;
float m_stream_update_timer;

//misc datas
Array<EasyMesh, bool, float, vec3> m_meshes;
Array<Light *> m_lights;
Camera * m_camera;
float m_fov;
float m_fov_damp;
float m_fov_zoom_damp;
mat4 m_fov_compensation;
};

//The basic main :
int main(int argc, char **argv)
{
System::Init(argc, argv);

Application app("MeshViewer", ivec2(960, 600), 60.0f);
new MeshViewer();
Application app("MeshViewer", ivec2(1600, 600), 60.0f);
if (argc > 1)
new MeshViewer(argv[1]);
else
new MeshViewer();
app.Run();

return EXIT_SUCCESS;


+ 1
- 0
test/MeshViewerBuffer.txt View File

@@ -0,0 +1 @@
[sc#2f2 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#22f ab 2 2 2 tx 0 csgu]]

Loading…
Cancel
Save