source: trunk/orbital/Lolnament.h @ 1496

Last change on this file since 1496 was 1496, checked in by touky, 9 years ago

Added Damping & random in the Lolnament.

File size: 10.9 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 012 Benjamin Huet <huet.benjamin@gmail.com>
5//            (c) 2012 Sam Hocevar <sam@hocevar.net>
6//
7
8#if !defined __LOLNAMENT_H__
9#define __LOLNAMENT_H__
10
11#define DEF_X 30
12#define DEF_Y 1
13#define DEF_Z 30
14#define DEF_SIZE 10
15#define DEF_INF_BLEND 50
16#define DEF_INF_MAX 30
17
18struct work_infos
19{
20        work_infos()
21        {
22                m_pos = vec3(0,0,0);
23                m_rot = vec3(0,0,0);
24                m_scale = 0.0f;
25                m_scale_3d = vec3(0,0,0);
26                m_damp_up = 0.0f;
27                m_damp_down = 0.0f;
28        }
29        work_infos(vec3 offset_pos, vec3 offset_rot, float offset_scale, vec3 offset_scale_3d, float damp_up, float damp_down)
30        {
31                m_pos = offset_pos;
32                m_rot = offset_rot;
33                m_scale = offset_scale;
34                m_scale_3d = offset_scale_3d;
35                m_damp_up = damp_up;
36                m_damp_down = damp_down;
37        }
38
39        vec3    m_pos;
40        vec3    m_rot;
41        float   m_scale;
42        vec3    m_scale_3d;
43        float   m_damp_up;
44        float   m_damp_down;
45};
46
47struct Point_infos_Part
48{
49        Point_infos_Part(int useage_index, vec3 offset_pos, vec3 offset_rot, float offset_scale=.0f, vec3 offset_scale_3d=vec3(.0f), float damp_up=.0f, float damp_down=.0f)
50        {
51                m_useage_index  = useage_index;
52                m_point_infos   =work_infos(offset_pos, offset_rot, offset_scale, offset_scale_3d, damp_up, damp_down);
53        }
54
55        int                     m_useage_index;
56        work_infos      m_point_infos;
57};
58
59struct transient_infos
60{
61        transient_infos(int point_id, vec3 base_pos, vec3 base_rot=vec3(0.0f, 0.0f, 0.0f), float base_scale=1.0f, vec3 base_scale_3d=vec3(1.0f, 1.0f, 1.0f), int random_number=0)
62                : m_influence(0.0f),
63                m_influence_previous(0.0f)
64        {
65                m_point_id = point_id;
66
67                m_base_pos = base_pos;
68                m_base_rot = base_rot;
69                m_base_scale = base_scale;
70                m_base_scale_3d = base_scale_3d;
71
72                m_final_pos = base_pos;
73                m_final_rot = base_rot;
74                m_final_scale = base_scale;
75                m_final_scale_3d = base_scale_3d;
76
77                for (; random_number > 0; random_number--)
78                        random_list << work_infos(vec3(RandF(), RandF(), RandF()), vec3(RandF(), RandF(), RandF()), RandF(), vec3(RandF(), RandF(), RandF()), RandF(), RandF());
79        };
80
81        int             m_point_id;
82
83        vec3    m_base_pos;
84        vec3    m_base_rot;
85        float   m_base_scale;
86        vec3    m_base_scale_3d;
87
88        float   m_influence_previous;
89        float   m_influence;
90
91        vec3    m_final_pos;
92        vec3    m_final_rot;
93        float   m_final_scale;
94        vec3    m_final_scale_3d;
95
96        Array<work_infos> random_list;
97};
98
99#define INF_DEFAULT 0 //Basic Blend
100#define INF_WAVE        1 //Blend with wave
101
102#define OFF_DEF 0 //Reference offset
103#define RND_MIN 1 //Minimum random offset
104#define RND_MAX 2 //Maximum random offset
105#define MAX_OFF 3 //Maximum offset slots
106
107struct influence_infos
108{
109        influence_infos(float step, const int method=INF_DEFAULT)
110        {
111                //Empty struct
112                memset(this, 0, sizeof(influence_infos));
113
114                m_step = clamp(step, 0.0f, 1.0f);
115                m_method = method;
116        };
117
118        inline influence_infos& operator<<(Point_infos_Part const &added_part)
119        {
120                if (added_part.m_useage_index >= OFF_DEF && added_part.m_useage_index < MAX_OFF)
121                {
122                        int i = added_part.m_useage_index;
123                        m_offset_pos[i]                 = added_part.m_point_infos.m_pos;
124                        m_offset_rot[i]                 = added_part.m_point_infos.m_rot;
125                        m_offset_scale[i]               = added_part.m_point_infos.m_scale;
126                        m_offset_scale_3d[i]    = added_part.m_point_infos.m_scale_3d;
127                        m_damp_up[i]                    = added_part.m_point_infos.m_damp_up;
128                        m_damp_down[i]                  = added_part.m_point_infos.m_damp_down;
129                }
130
131                return *this;
132        }
133
134        float   m_step;
135        int             m_method;
136
137        vec3    m_offset_pos[3];
138        vec3    m_offset_rot[3];
139        float   m_offset_scale[3];
140        vec3    m_offset_scale_3d[3];
141        float   m_damp_up[3];
142        float   m_damp_down[3];
143};
144
145class Lolnament : public WorldEntity
146{
147public:
148    Lolnament()
149      : m_ready(false)
150    {
151                m_ref_mesh.Compile( "[sc#f80 afcb8 6 6 1]"
152                                                        "[sc#bbd afcb6 8 6 1]"
153                                                        "[sc#44d afcb6 6 8 1]");
154
155                wave_angle = 0.0f;
156                debug_point_angle = 0.0f;
157
158                m_influence_list << (influence_infos(0.0f, INF_WAVE) << Point_infos_Part(OFF_DEF, vec3(.0f), vec3(.0f), .0f, vec3(.0f), .0f, 1.2f));
159                m_influence_list << (influence_infos(0.3f) << Point_infos_Part(OFF_DEF, vec3(.0f, 40.0f, .0f), vec3(.0f, 90.0f, .0f)));
160                m_influence_list << (influence_infos(0.7f) << Point_infos_Part(OFF_DEF, vec3(.0f, 40.0f, .0f), vec3(.0f, 90.0f, .0f)));
161                m_influence_list << (influence_infos(1.0f) << Point_infos_Part(OFF_DEF, vec3(.0f, 80.0f, .0f), vec3(.0f, .0f, 90.0f), .0f, vec3(2.0f, .0f, .0f))
162                                                                                                        << Point_infos_Part(RND_MIN, vec3(-40.0f, .0f, -40.0f), vec3(.0f))
163                                                                                                        << Point_infos_Part(RND_MAX, vec3(40.0f, .0f, 40.0f), vec3(.0f)));
164
165                vec3 default_offset = vec3((float)DEF_X, (float)DEF_Y, (float)DEF_Z) * (float)DEF_SIZE * 0.5f;
166                for (int z=0; z < DEF_Z; z++)
167                        for (int y=0; y < DEF_Y; y++)
168                                for (int x=0; x < DEF_X; x++)
169                                        m_point_list << transient_infos(m_point_list.Count(), vec3((float)x, (float)y, (float)z) * (float)DEF_SIZE - default_offset, vec3(0,0,0), 1.0f, vec3(1.0f), m_influence_list.Count());
170}
171
172    ~Lolnament()
173    {
174    }
175
176    char const *GetName() { return "<Lolnament>"; }
177
178protected:
179    virtual void TickGame(float seconds)
180    {
181        WorldEntity::TickGame(seconds);
182
183                m_influence_point_list.Empty();
184
185                wave_angle += 3.0f * seconds;
186                debug_point_angle += 1.0f * seconds;
187
188                if (wave_angle > M_PI * 2.0f)
189                        wave_angle -= M_PI * 2.0f;
190                if (debug_point_angle > M_PI * 2.0f)
191                        debug_point_angle -= M_PI * 2.0f;
192
193                m_influence_point_list << vec4(cos(debug_point_angle) * DEF_X * DEF_SIZE * 0.3f, 0, sin(debug_point_angle) * DEF_Z * DEF_SIZE * 0.3f, 1.0f);
194
195                ComputeInfluenceValues();
196
197                ComputePointFromInfluenceValues(seconds);
198    }
199
200        void ComputeInfluenceValues()
201    {
202                for (int i=0; i < m_point_list.Count(); i++)
203                {
204                        m_point_list[i].m_influence_previous = m_point_list[i].m_influence;
205                        m_point_list[i].m_influence = 0.0f;
206                        for (int j=0; j < m_influence_point_list.Count(); j++)
207                                m_point_list[i].m_influence = max(m_point_list[i].m_influence, 1.0f - min(1.0f, max(0.0f, length(m_point_list[i].m_base_pos - m_influence_point_list[j].xyz) - DEF_INF_MAX) / DEF_INF_BLEND));
208                }
209        }
210
211        void ComputePointFromInfluenceValues(float seconds)
212        {
213                for (int i=0; i < m_point_list.Count(); i++)
214                {
215                        int info_a = 0;
216                        int info_b = m_influence_list.Count();
217                        float step_a = -1.0f;
218                        float step_b = 2.0f;
219                        for (int j=0; j < m_influence_list.Count(); j++)
220                        {
221                                if (m_influence_list[j].m_step <= m_point_list[i].m_influence &&
222                                        m_influence_list[j].m_step > step_a)
223                                {
224                                        info_a = j;
225                                        step_a = m_influence_list[j].m_step;
226                                }
227                                if (m_influence_list[j].m_step >= m_point_list[i].m_influence &&
228                                        m_influence_list[j].m_step < step_b)
229                                {
230                                        info_b = j;
231                                        step_b = m_influence_list[j].m_step;
232                                }
233                        }
234
235                        work_infos work_a = work_infos();
236                        work_infos work_b = work_infos();
237                        get_modified_point(m_influence_list[info_a], info_a, m_point_list[i], work_a);
238                        get_modified_point(m_influence_list[info_b], info_b, m_point_list[i], work_b);
239
240                        float divider = step_b - step_a;
241                        divider = (divider > .0f)?((m_point_list[i].m_influence - step_a) / divider):(1.0f);
242
243                        float dir_influence = m_point_list[i].m_influence - m_point_list[i].m_influence_previous;
244                        float damp_used = ((dir_influence > 0.f)?(work_b.m_damp_up):(work_a.m_damp_down));
245                        damp_used = (seconds / (seconds + damp_used));
246
247                        work_a.m_pos            = work_a.m_pos + (work_b.m_pos - work_a.m_pos) * divider;
248                        work_a.m_rot            = work_a.m_rot + (work_b.m_rot - work_a.m_rot) * divider;
249                        work_a.m_scale          = work_a.m_scale + (work_b.m_scale - work_a.m_scale) * divider;
250                        work_a.m_scale_3d       = work_a.m_scale_3d + (work_b.m_scale_3d - work_a.m_scale_3d) * divider;
251
252                        m_point_list[i].m_final_pos                     += (work_a.m_pos - m_point_list[i].m_final_pos) * damp_used;
253                        m_point_list[i].m_final_rot                     += (work_a.m_rot - m_point_list[i].m_final_rot) * damp_used;
254                        m_point_list[i].m_final_scale           += (work_a.m_scale - m_point_list[i].m_final_scale) * damp_used;
255                        m_point_list[i].m_final_scale_3d        += (work_a.m_scale_3d - m_point_list[i].m_final_scale_3d) * damp_used;
256                }
257        }
258
259        void get_modified_point(const influence_infos &src_infos, const int random_idx, const transient_infos &src_transient, work_infos &dst_work)
260        {
261                //Base setup
262                dst_work.m_pos                  = src_transient.m_base_pos;
263                dst_work.m_rot                  = src_transient.m_base_rot;
264                dst_work.m_scale                = src_transient.m_base_scale;
265                dst_work.m_scale_3d             = src_transient.m_base_scale_3d;
266                dst_work.m_damp_down    = src_infos.m_damp_down[OFF_DEF];
267                dst_work.m_damp_up              = src_infos.m_damp_up[OFF_DEF];
268
269                //Added offset via given method
270                switch (src_infos.m_method)
271                {
272                        case INF_WAVE:
273                        {
274                                float point_angle = wave_angle + (float)src_transient.m_point_id * 2.0f * (float)M_PI * 2.0f / ((float)DEF_X * 1.051f);
275                                dst_work.m_pos += vec3(0.0f, (-1.0f + cos(point_angle)) * 20.0f, 0.0f);
276                                //TODO : dst_work.m_rot += vec3(0,0,0);
277                        }
278                        case INF_DEFAULT:
279                        {
280                                dst_work.m_pos          += src_infos.m_offset_pos[OFF_DEF];
281                                dst_work.m_rot          += src_infos.m_offset_rot[OFF_DEF];
282                                dst_work.m_scale        += src_infos.m_offset_scale[OFF_DEF];
283                                dst_work.m_scale_3d += src_infos.m_offset_scale_3d[OFF_DEF];
284                                if (src_transient.random_list.Count() && random_idx > 0 && random_idx < src_transient.random_list.Count())
285                                {
286                                        dst_work.m_pos                  += src_infos.m_offset_pos[RND_MIN] + (src_infos.m_offset_pos[RND_MAX] - src_infos.m_offset_pos[RND_MIN]) * src_transient.random_list[random_idx].m_pos;
287                                        dst_work.m_rot                  += src_infos.m_offset_rot[RND_MIN] + (src_infos.m_offset_rot[RND_MAX] - src_infos.m_offset_rot[RND_MIN]) * src_transient.random_list[random_idx].m_rot;
288                                        dst_work.m_scale                += src_infos.m_offset_scale[RND_MIN] + (src_infos.m_offset_scale[RND_MAX] - src_infos.m_offset_scale[RND_MIN]) * src_transient.random_list[random_idx].m_scale;
289                                        dst_work.m_scale_3d             += src_infos.m_offset_scale_3d[RND_MIN] + (src_infos.m_offset_scale_3d[RND_MAX] - src_infos.m_offset_scale_3d[RND_MIN]) * src_transient.random_list[random_idx].m_scale_3d;
290                                        dst_work.m_damp_down    += src_infos.m_damp_down[RND_MIN] + (src_infos.m_damp_down[RND_MAX] - src_infos.m_damp_down[RND_MIN]) * src_transient.random_list[random_idx].m_damp_down;
291                                        dst_work.m_damp_up              += src_infos.m_damp_up[RND_MIN] + (src_infos.m_damp_up[RND_MAX] - src_infos.m_damp_up[RND_MIN]) * src_transient.random_list[random_idx].m_damp_up;
292                                }
293                                break;
294                        }
295                }
296        }
297
298    virtual void TickDraw(float seconds)
299    {
300        WorldEntity::TickDraw(seconds);
301
302        if (!m_ready)
303        {
304            m_ref_mesh.MeshConvert();
305            m_ready = true;
306        }
307
308                m_rotation *= quat::rotate(seconds * 10.0f, vec3(0, 1, 0));
309                mat4 main_matrix = mat4::translate(m_position) * mat4(m_rotation);
310                for (int i=0; i < m_point_list.Count(); i++)
311                {
312                        mat4 model = main_matrix *
313                                mat4::translate(m_point_list[i].m_final_pos) *
314                                mat4(quat::fromeuler_yxz(m_point_list[i].m_final_rot)) *
315                                mat4::scale(m_point_list[i].m_final_scale_3d * m_point_list[i].m_final_scale);
316                        m_ref_mesh.Render(model);
317                }
318    }
319
320private:
321        //mesh used to render Lolnament
322    Mesh m_ref_mesh;
323        //List of Pos/Rot/Etc... currently applied to the Lolnament's meshes.
324        Array<transient_infos> m_point_list;
325        //List of influence steps
326        Array<influence_infos> m_influence_list;
327
328        Array<vec4> m_influence_point_list;
329
330        float wave_angle;
331        float debug_point_angle;
332    bool m_ready;
333};
334
335#endif /* __LOLNAMENT_H__ */
336
Note: See TracBrowser for help on using the repository browser.