source: trunk/test/MeshViewer.cpp @ 2356

Last change on this file since 2356 was 2356, checked in by lolbot, 7 years ago

fixed 17 files out of 2363:

  • removed 55 CR characters
  • removed 80 trailing whitespaces
  • replaced 1236 tabs with spaces
File size: 14.7 KB
Line 
1
2//
3// Lol Engine - EasyMesh tutorial
4//
5// Copyright: (c) 2011-2013 Sam Hocevar <sam@hocevar.net>
6//            (c) 2012-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
7//   This program is free software; you can redistribute it and/or
8//   modify it under the terms of the Do What The Fuck You Want To
9//   Public License, Version 2, as published by Sam Hocevar. See
10//   http://www.wtfpl.net/ for more details.
11//
12
13#if defined HAVE_CONFIG_H
14#   include "config.h"
15#endif
16
17#include <cfloat> /* for FLT_MAX */
18
19#include "core.h"
20
21using namespace std;
22using namespace lol;
23
24#define    IPT_CAM_RESET          "Cam_Center"
25#define    IPT_CAM_FORWARD        "Cam_Forward"
26#define    IPT_CAM_BACKWARD       "Cam_Backward"
27#define    IPT_CAM_ZOOM_OUT       "Cam_Zoom_In"
28#define    IPT_CAM_ZOOM_IN        "Cam_Zoom_Out"
29
30#define    IPT_MESH_UPDATE        "Mesh_Update"
31#define    IPT_MESH_RESET         "Mesh_Reset"
32
33#define    IPT_MESH_LEFT          "Mesh_Left"
34#define    IPT_MESH_RIGHT         "Mesh_Right"
35#define    IPT_MESH_UP            "Mesh_Up"
36#define    IPT_MESH_DOWN          "Mesh_Down"
37#define    IPT_MESH_SCALE_UP      "Mesh_Scale_Up"
38#define    IPT_MESH_SCALE_DOWN    "Mesh_Scale_Down"
39#define    IPT_MESH_OFFSET_UP     "Mesh_Offset_Up"
40#define    IPT_MESH_OFFSET_DOWN   "Mesh_Offset_Down"
41#define    IPT_MESH_ROT_LEFT      "Mesh_Rot_Left"
42#define    IPT_MESH_ROT_RIGHT     "Mesh_Rot_Right"
43#define    IPT_MESH_ROT_UP        "Mesh_Rot_Up"
44#define    IPT_MESH_ROT_DOWN      "Mesh_Rot_Down"
45
46class MeshViewer : public WorldEntity
47{
48public:
49    void SetFov(float new_fov=60.0f)
50    {
51        //FOV compensation doesn't work
52        ivec2 video_size = Video::GetSize();
53        float near = -video_size.x - video_size.y;
54        float far = video_size.x + video_size.y;
55        float t1 = tanf(new_fov / 2);
56        float dist = video_size.x / (2.0f * t1);
57        //m_fov_compensation = mat4::translate(-0.5f * video_size.x, -0.5f * video_size.y, -dist);
58        m_fov_compensation = mat4::translate(vec3(.0f));
59        if (new_fov > 0.1f)
60            m_camera->SetPerspective(new_fov, (float)video_size.x, (float)video_size.y, .1f, 1000.f);
61        else
62            m_camera->SetOrtho((float)video_size.x, (float)video_size.y, .1f, 1000.f);
63    }
64
65    MeshViewer(char *file_buffer = "MeshViewerBuffer.txt")
66    {
67        //Input setup
68        Input::LinkActionToKey(IPT_CAM_RESET,           Key::Return);
69        Input::LinkActionToKey(IPT_CAM_FORWARD,         Key::PageUp);
70        Input::LinkActionToKey(IPT_CAM_BACKWARD,        Key::PageDown);
71        Input::LinkActionToKey(IPT_CAM_ZOOM_IN,         Key::Home);
72        Input::LinkActionToKey(IPT_CAM_ZOOM_OUT,        Key::End);
73
74        Input::LinkActionToKey(IPT_MESH_LEFT,           Key::Left);
75        Input::LinkActionToKey(IPT_MESH_RIGHT,          Key::Right);
76        Input::LinkActionToKey(IPT_MESH_UP,             Key::Up);
77        Input::LinkActionToKey(IPT_MESH_DOWN,           Key::Down);
78
79        Input::LinkActionToKey(IPT_MESH_UPDATE,         Key::Space);
80        Input::LinkActionToKey(IPT_MESH_RESET,          Key::KP0);
81
82        Input::LinkActionToKey(IPT_MESH_OFFSET_DOWN,    Key::KP1);
83        Input::LinkActionToKey(IPT_MESH_OFFSET_UP,      Key::KP3);
84        Input::LinkActionToKey(IPT_MESH_SCALE_DOWN,     Key::KP7);
85        Input::LinkActionToKey(IPT_MESH_SCALE_UP,       Key::KP9);
86
87        Input::LinkActionToKey(IPT_MESH_ROT_LEFT,       Key::KP4);
88        Input::LinkActionToKey(IPT_MESH_ROT_RIGHT,      Key::KP6);
89        Input::LinkActionToKey(IPT_MESH_ROT_UP,         Key::KP8);
90        Input::LinkActionToKey(IPT_MESH_ROT_DOWN,       Key::KP5);
91
92        m_angle = 0;
93
94        //Camera Setup
95        m_fov_zoom_damp = .0f;
96        m_fov_damp = 60.0f;
97        m_fov = 60.0f;
98        m_camera = new Camera(vec3(0.f, 600.f, 0.f),
99                              vec3(0.f, 0.f, 0.f),
100                              vec3(0, 1, 0));
101        SetFov(m_fov_damp);
102        m_camera->SetTarget(vec3(0.f, 0.f, 0.f));
103        m_camera->SetPosition(vec3(0.f, 0.f, 10.f));
104        m_camera->ForceSceneUpdate();
105        Ticker::Ref(m_camera);
106
107        //Lights setup
108        m_lights << new Light();
109        m_lights.Last()->SetPosition(vec4(4.f, -1.f, -4.f, 0.f));
110        m_lights.Last()->SetColor(vec4(.0f, .2f, .5f, 1.f));
111        Ticker::Ref(m_lights.Last());
112
113        m_lights << new Light();
114        m_lights.Last()->SetPosition(vec4(8.f, 2.f, 6.f, 1.f));
115        m_lights.Last()->SetColor(vec4(.5f, .3f, .0f, 1.f));
116        Ticker::Ref(m_lights.Last());
117
118        //Speed damp
119        m_mesh_rotate_damp = vec2(.0f);
120        m_mesh_screen_move_damp = vec2(.0f);
121        m_mesh_move_damp = vec2(.0f);
122
123        //Actual values
124        SetDefaultMeshTransform();
125
126        //Actual values damp
127        m_mesh_rotation_damp = vec2(.0f);
128        m_mesh_screen_offset_damp = vec2(.0f);
129        m_mesh_offset_damp = vec2(.0f);
130
131
132        m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
133                mat4::rotate(m_angle, vec3(0, 1, 0)) *
134                mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));
135
136        //File management
137#ifdef HAVE_STDIO_H
138        m_file_buffer = fopen("MeshViewerBuffer.txt", "r");
139
140        if (!m_file_buffer)
141            Ticker::Shutdown();
142#else //Full FAIL, kill the viewer
143        Ticker::Shutdown();
144#endif
145
146        m_last_stream_size = 0;
147        m_last_stream_cmd << 0;
148
149        m_stream_update_time = 0.0f;
150        m_stream_update_timer = 1.0f;
151    }
152
153    ~MeshViewer()
154    {
155        Ticker::Unref(m_camera);
156        for (int i = 0; i < m_lights.Count(); ++i)
157            Ticker::Unref(m_lights[i]);
158#ifdef HAVE_STDIO_H
159        fclose(m_file_buffer);
160#endif
161    }
162
163    void SetDefaultMeshTransform()
164    {
165        m_mesh_rotation = vec2(25.0f, .0f);
166        m_mesh_screen_offset = vec2(.54f, .0f);
167        m_mesh_offset = vec2(-.64f, .07f);
168    }
169
170    virtual void TickGame(float seconds)
171    {
172        WorldEntity::TickGame(seconds);
173
174        //Shutdown logic
175        if (Input::WasReleased(Key::Escape))
176            Ticker::Shutdown();
177
178        //Update Mesh BBox - Get the Min/Max needed
179        vec3 min_max[2] = { vec3(FLT_MAX), vec3(-FLT_MAX) };
180        int mesh_id = m_meshes.Count() - 1;
181        for (; mesh_id >= 0; mesh_id--)
182            if (m_meshes[mesh_id].m2)
183                break;
184
185        if (m_meshes.Count() && mesh_id >= 0)
186        {
187            for (int i = 0; i < m_meshes[mesh_id].m1.GetVertexCount(); i++)
188            {
189                vec3 vpos = m_meshes[mesh_id].m1.GetVertexLocation(i);
190                min_max[0] = min(vpos.xyz, min_max[0]);
191                min_max[1] = max(vpos.xyz, min_max[1]);
192            }
193        }
194        else
195        {
196            min_max[0] = vec3(.0f);
197            min_max[1] = vec3(.0f);
198        }
199        //[0] : center, [1] : size.
200        vec3 BBox[2] = { vec3(.0f), vec3(.0f) };
201        BBox[1] = min_max[1] - min_max[0];
202        BBox[0] = min_max[0] + BBox[1] * .5f;
203        vec3 BBox_mod = BBox[1];
204
205        //--
206        //Camera movement handling
207        //--
208        vec3 cam_move = BBox_mod * seconds *
209                        vec3(.0f, .0f, (float)(Input::GetStatus(IPT_CAM_BACKWARD) - Input::GetStatus(IPT_CAM_FORWARD)));
210
211        if (Input::WasReleased(IPT_CAM_RESET))
212            SetFov();
213
214        float fov_zoom = (float)(Input::GetStatus(IPT_CAM_ZOOM_OUT) - Input::GetStatus(IPT_CAM_ZOOM_IN));
215        m_fov_zoom_damp = damp(m_fov_zoom_damp, fov_zoom, (fov_zoom == .0f)?(.15f):(0.5f), seconds);
216        m_fov = max(.0f, m_fov + seconds * 10.0f * m_fov_zoom_damp);
217        m_fov_damp = damp(m_fov_damp, m_fov, .2f, seconds);
218        SetFov(m_fov_damp);
219
220        m_camera->SetPosition(m_camera->GetPosition() + cam_move);
221        m_camera->SetTarget(m_camera->GetPosition() + vec3(0, 0, -5.0f));
222
223        //--
224        //Mesh movement handling
225        //--
226        if (Input::WasReleased(IPT_MESH_RESET))
227            SetDefaultMeshTransform();
228
229        vec2 new_move = vec2(.0f);
230
231        new_move = vec2((float)(Input::GetStatus(IPT_MESH_RIGHT) - Input::GetStatus(IPT_MESH_LEFT)),
232                        (float)(Input::GetStatus(IPT_MESH_UP)    - Input::GetStatus(IPT_MESH_DOWN)));
233        m_mesh_screen_move_damp = vec2(damp(m_mesh_screen_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
234                                         damp(m_mesh_screen_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
235
236        new_move = vec2((float)(Input::GetStatus(IPT_MESH_OFFSET_UP) - Input::GetStatus(IPT_MESH_OFFSET_DOWN)),
237                        (float)(Input::GetStatus(IPT_MESH_SCALE_UP)  - Input::GetStatus(IPT_MESH_SCALE_DOWN)));
238        m_mesh_move_damp = vec2(damp(m_mesh_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
239                                  damp(m_mesh_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
240
241        new_move = vec2((float)(Input::GetStatus(IPT_MESH_ROT_UP)    - Input::GetStatus(IPT_MESH_ROT_DOWN)),
242                        (float)(Input::GetStatus(IPT_MESH_ROT_RIGHT) - Input::GetStatus(IPT_MESH_ROT_LEFT)));
243        m_mesh_rotate_damp = vec2(damp(m_mesh_rotate_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
244                                    damp(m_mesh_rotate_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
245
246        vec2 mesh_screen_move = seconds * 0.6f * m_mesh_screen_move_damp;
247        vec2 mesh_offset_move = seconds * vec2(.6f, .2f) * m_mesh_move_damp;
248        vec2 mesh_rotate = seconds * vec2(40.0f, 60.0f) * m_mesh_rotate_damp;
249
250        //Add movement
251        m_mesh_screen_offset += mesh_screen_move;
252        m_mesh_offset += mesh_offset_move;
253        m_mesh_rotation += mesh_rotate;
254
255        //Compute damp
256        m_mesh_rotation_damp = damp(m_mesh_rotation_damp, m_mesh_rotation, .2f, seconds);
257        m_mesh_screen_offset_damp = damp(m_mesh_screen_offset_damp, m_mesh_screen_offset, .2f, seconds);
258        m_mesh_offset_damp = damp(m_mesh_offset_damp, m_mesh_offset, .2f, seconds);
259
260        //Clamp necessary
261        m_mesh_rotation.x = clamp(m_mesh_rotation.x, -90.0f, 90.0f);
262        m_mesh_offset.y = max(.0f, m_mesh_offset.y);
263
264        //m_angle += seconds * 70.0f;
265        m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
266                mat4::rotate(m_angle, vec3(0, 1, 0)) *
267                mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));
268
269        //--
270        //File management
271        //--
272        if (Input::WasReleased(IPT_MESH_UPDATE))
273            m_stream_update_time = m_stream_update_timer + 1.0f;
274        m_stream_update_time += seconds;
275
276#ifdef HAVE_STDIO_H
277        // obtain file size:
278        fseek(m_file_buffer, 0 , SEEK_END);
279        long new_stream_size = ftell(m_file_buffer);
280        rewind(m_file_buffer);
281#else
282        long new_stream_size = 0;
283#endif
284
285        if (new_stream_size && (new_stream_size != m_last_stream_size || m_stream_update_time > m_stream_update_timer))
286        {
287            Array<char> new_stream_cmd;
288            m_stream_update_time = .0f;
289
290            //Reserve the needed datas & read the file
291            new_stream_cmd.Resize((int)new_stream_size);
292#ifdef HAVE_STDIO_H
293            size_t result = fread(&new_stream_cmd[0], 1, new_stream_size, m_file_buffer);
294#else
295#endif
296
297            //if the new cmd is different from the previous one
298            if (new_stream_cmd.Count() != m_last_stream_cmd.Count() ||
299                strcmp(&new_stream_cmd[0], &m_last_stream_cmd[0]))
300            {
301                //store the current datas
302                m_last_stream_cmd  = new_stream_cmd;
303                m_last_stream_size = new_stream_size;
304
305                //Create a new mesh
306                m_meshes.Push(EasyMesh(), false, .0f, vec3(.0f));
307                m_meshes.Last().m1.Compile(&new_stream_cmd[0]);
308            }
309        }
310    }
311
312    virtual void TickDraw(float seconds)
313    {
314        WorldEntity::TickDraw(seconds);
315
316        for (int i = 0; i < m_meshes.Count(); i++)
317        {
318            if (!m_meshes[i].m2)
319            {
320                m_meshes[i].m1.MeshConvert();
321                m_meshes[i].m2 = true;
322            }
323        }
324
325        Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
326
327        mat4 default_proj = Scene::GetDefault()->GetProjMatrix();
328        for (int i = 0; i < m_meshes.Count(); i++)
329        {
330            float new_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (i + 1))));
331            m_meshes[i].m3 = damp(m_meshes[i].m3, new_scale, .35f, seconds);
332            if (m_meshes[i].m3 > .0f)
333            {
334                vec3 new_mesh_offset = vec3(.0f);
335                for (int j = m_meshes.Count() - 1; j > i; j--)
336                {
337                    float ofs_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (j + 0))));
338                    new_mesh_offset = new_mesh_offset + vec3(m_meshes[j].m3 * ofs_scale * ofs_scale * m_mesh_offset_damp.x, .0f, .0f);
339                }
340                m_meshes[i].m4 = damp(m_meshes[i].m4, new_mesh_offset, .35f, seconds);
341                Scene::GetDefault()->SetProjMatrix(mat4::translate(m_meshes[i].m4) *
342                                                   mat4::translate(vec3(m_mesh_screen_offset_damp, .0f)) *
343                                                   mat4::scale(vec3(vec2(m_meshes[i].m3), 1.0f)) *
344                                                   default_proj *
345                                                   m_fov_compensation);
346                m_meshes[i].m1.Render(m_mat);
347                Video::Clear(ClearMask::Depth);
348            }
349        }
350        Scene::GetDefault()->SetProjMatrix(default_proj);
351    }
352
353private:
354    float           m_angle;
355    mat4            m_mat;
356
357    //Mesh infos
358    //Move damping
359    vec2            m_mesh_rotate_damp;
360    vec2            m_mesh_screen_move_damp;
361    vec2            m_mesh_move_damp;
362
363    //Move transform damping
364    vec2            m_mesh_rotation_damp;
365    vec2            m_mesh_screen_offset_damp;
366    vec2            m_mesh_offset_damp;
367
368    vec2            m_mesh_rotation;     //Meshes rotation
369    vec2            m_mesh_screen_offset;//Meshes screen offset
370    vec2            m_mesh_offset;       //Mesh Offset after first mesh (x: offset, y: scale)
371
372    //File data
373#ifdef HAVE_STDIO_H
374    FILE *          m_file_buffer;
375#endif
376    long            m_last_stream_size;
377    Array<char>     m_last_stream_cmd;
378    float           m_stream_update_time;
379    float           m_stream_update_timer;
380
381    //misc datas
382    Array<EasyMesh, bool, float, vec3> m_meshes;
383    Array<Light *>  m_lights;
384    Camera *        m_camera;
385    float           m_fov;
386    float           m_fov_damp;
387    float           m_fov_zoom_damp;
388    mat4            m_fov_compensation;
389};
390
391//The basic main :
392int main(int argc, char **argv)
393{
394    System::Init(argc, argv);
395
396    Application app("MeshViewer", ivec2(1600, 600), 60.0f);
397    if (argc > 1)
398        new MeshViewer(argv[1]);
399    else
400        new MeshViewer();
401    app.Run();
402
403    return EXIT_SUCCESS;
404}
405
Note: See TracBrowser for help on using the repository browser.