source: trunk/games/ToukyDemo/UserReactiveObject.h @ 1547

Last change on this file since 1547 was 1526, checked in by touky, 8 years ago

added ToukyDemo to the repo.

File size: 13.5 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 2012 Benjamin Huet <huet.benjamin@gmail.com>
5//            (c) 2012 Sam Hocevar <sam@hocevar.net>
6//
7
8#if !defined __USERREACTIVEOBJECT_H__
9#define __USERREACTIVEOBJECT_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        = 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;
56        work_infos      m_point_infos;
57};
58
59#define BLD_SPHERE      0 //influence is calculated as a sphere interpolation
60#define BLD_SQUARE      1 //influence is calculated as a max of each vec3() component
61
62struct influencing_point_infos
63{
64        influencing_point_infos(int useage, vec3 position, float blend)
65        {
66                m_useage        = useage;
67                m_position      = position;
68                m_blend         = blend;
69        }
70
71        int                     m_useage;
72        vec3            m_position;
73        float           m_blend;
74};
75
76struct transient_infos
77{
78        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)
79                : m_influence(0.0f),
80                m_influence_previous(0.0f)
81        {
82                m_point_id = point_id;
83
84                m_base_pos = base_pos;
85                m_base_rot = base_rot;
86                m_base_scale = base_scale;
87                m_base_scale_3d = base_scale_3d;
88
89                m_final_pos = base_pos;
90                m_final_rot = base_rot;
91                m_final_scale = base_scale;
92                m_final_scale_3d = base_scale_3d;
93
94                for (; random_number > 0; random_number--)
95                        random_list << work_infos(vec3(RandF(), RandF(), RandF()), vec3(RandF(), RandF(), RandF()), RandF(), vec3(RandF(), RandF(), RandF()), RandF(), RandF());
96        };
97
98        int             m_point_id;
99
100        vec3    m_base_pos;
101        vec3    m_base_rot;
102        float   m_base_scale;
103        vec3    m_base_scale_3d;
104
105        float   m_influence_previous;
106        float   m_influence;
107
108        vec3    m_final_pos;
109        vec3    m_final_rot;
110        float   m_final_scale;
111        vec3    m_final_scale_3d;
112
113        Array<work_infos> random_list;
114};
115
116#define INF_DEFAULT 0 //Basic Blend
117#define INF_WAVE        1 //Blend with wave
118
119#define OFF_DEF 0 //Reference offset
120#define RND_MIN 1 //Minimum random offset
121#define RND_MAX 2 //Maximum random offset
122#define MAX_OFF 3 //Maximum offset slots
123
124struct influence_infos
125{
126        influence_infos(float step, const bool ignore_step_down=false, const bool ignore_step_up=false, const int method=INF_DEFAULT)
127        {
128                //Empty struct
129                memset(this, 0, sizeof(influence_infos));
130
131                m_step = clamp(step, 0.0f, 1.0f);
132                m_method = method;
133                m_ignore_step_up = ignore_step_up;
134                m_ignore_step_down = ignore_step_down;
135        };
136
137        inline influence_infos& operator<<(point_infos_Part const &added_part)
138        {
139                if (added_part.m_useage >= OFF_DEF && added_part.m_useage < MAX_OFF)
140                {
141                        int i = added_part.m_useage;
142                        m_offset_pos[i]                 = added_part.m_point_infos.m_pos;
143                        m_offset_rot[i]                 = added_part.m_point_infos.m_rot;
144                        m_offset_scale[i]               = added_part.m_point_infos.m_scale;
145                        m_offset_scale_3d[i]    = added_part.m_point_infos.m_scale_3d;
146                        m_damp_up[i]                    = added_part.m_point_infos.m_damp_up;
147                        m_damp_down[i]                  = added_part.m_point_infos.m_damp_down;
148                }
149
150                return *this;
151        }
152
153        float   m_step;
154        int             m_method;
155        bool    m_ignore_step_up;
156        bool    m_ignore_step_down;
157
158        vec3    m_offset_pos[3];
159        vec3    m_offset_rot[3];
160        float   m_offset_scale[3];
161        vec3    m_offset_scale_3d[3];
162        float   m_damp_up[3];
163        float   m_damp_down[3];
164};
165
166class UserReactiveObject : public WorldEntity
167{
168public:
169    UserReactiveObject()
170      : m_ready(false)
171    {
172                m_ref_mesh.Compile( "[sc#f80 afcb10 8 8 -1]"
173                                                        "[sc#bbd afcb8 10 8 -1]"
174                                                        "[sc#44d afcb8 8 10 -1]");
175
176                wave_angle = 0.0f;
177                debug_point_angle = 0.0f;
178
179                m_influence_list << (influence_infos(0.0f, false, false, INF_WAVE)
180                                                                << point_infos_Part(OFF_DEF, vec3(.0f), vec3(.0f), .0f, vec3(.0f), .0f, 1.2f));
181                //m_influence_list << (influence_infos(0.3f, true, false)
182                //                                              << point_infos_Part(OFF_DEF, vec3(.0f, 40.0f, .0f), vec3(.0f, 90.0f, .0f)));
183                //m_influence_list << (influence_infos(0.7f, true, false)
184                //                                              << point_infos_Part(OFF_DEF, vec3(.0f, 40.0f, .0f), vec3(.0f, 90.0f, .0f)));
185                m_influence_list << (influence_infos(1.0f)
186                                                                << point_infos_Part(OFF_DEF, vec3(.0f, 80.0f, .0f), vec3(.0f, .0f, 90.0f), .0f, vec3(2.0f, .0f, .0f), .0f, .2f)
187                                                                /*
188                                                                << point_infos_Part(RND_MIN, vec3(-40.0f, .0f, -40.0f), vec3(.0f))
189                                                                << point_infos_Part(RND_MAX, vec3(40.0f, .0f, 40.0f), vec3(.0f))*/
190                                                                );
191
192                vec3 default_offset = vec3((float)DEF_X, (float)DEF_Y, (float)DEF_Z) * (float)DEF_SIZE * 0.5f;
193                for (int z=0; z < DEF_Z; z++)
194                        for (int y=0; y < DEF_Y; y++)
195                                for (int x=0; x < DEF_X; x++)
196                                        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());
197}
198
199    ~UserReactiveObject()
200    {
201    }
202
203    char const *GetName() { return "<UserReactiveObject>"; }
204
205protected:
206    virtual void TickGame(float seconds)
207    {
208        WorldEntity::TickGame(seconds);
209
210                m_influence_point_list.Empty();
211
212                wave_angle += 3.0f * seconds;
213                debug_point_angle += 1.0f * seconds;
214
215                if (wave_angle > M_PI * 2.0f)
216                        wave_angle -= M_PI * 2.0f;
217                if (debug_point_angle > M_PI * 2.0f)
218                        debug_point_angle -= M_PI * 2.0f;
219
220                //m_influence_point_list << influencing_point_infos(BLD_SPHERE, vec3(lol::cos(debug_point_angle) * DEF_X, 0, lol::sin(debug_point_angle) * DEF_Z) * DEF_SIZE * 0.3f, 1.0f);
221                m_influence_point_list << influencing_point_infos(BLD_SQUARE, vec3(-lol::cos(debug_point_angle) * DEF_X, 0, -lol::sin(debug_point_angle) * DEF_Z) * DEF_SIZE * 0.3f, 1.0f);
222
223                ComputeInfluenceValues();
224
225                ComputePointFromInfluenceValues(seconds);
226    }
227
228        void ComputeInfluenceValues()
229    {
230                //t = t * t * (3 - 2 * t)
231                for (int i=0; i < m_point_list.Count(); i++)
232                {
233                        m_point_list[i].m_influence_previous = m_point_list[i].m_influence;
234
235                        float cur_blend = 0.0f;
236                        for (int j=0; j < m_influence_point_list.Count(); j++)
237                        {
238                                float new_blend = 0.0f;
239                                switch (m_influence_point_list[j].m_useage)
240                                {
241                                case BLD_SPHERE:
242                                        {
243                                                new_blend = 1.0f - min(1.0f, max(0.0f, length(m_point_list[i].m_base_pos - m_influence_point_list[j].m_position) - DEF_INF_MAX) / DEF_INF_BLEND);
244                                                break;
245                                        }
246                                case BLD_SQUARE:
247                                        {
248                                                vec3 point_diff = m_point_list[i].m_base_pos - m_influence_point_list[j].m_position;
249                                                point_diff = vec3(std::abs(point_diff.x), std::abs(point_diff.y), std::abs(point_diff.z));
250
251                                                new_blend = min(1.0f - min(1.0f, max(0.0f, point_diff.z - DEF_INF_MAX) / DEF_INF_BLEND),
252                                                                                min(1.0f - min(1.0f, max(0.0f, point_diff.y - DEF_INF_MAX) / DEF_INF_BLEND),
253                                                                                        1.0f - min(1.0f, max(0.0f, point_diff.x - DEF_INF_MAX) / DEF_INF_BLEND)));
254                                                break;
255                                        }
256                                default:
257                                        {
258                                                break;
259                                        }
260                                };
261
262                                //cur_blend = max(cur_blend, 1.0f - min(1.0f, max(0.0f, length(m_point_list[i].m_base_pos - m_influence_point_list[j].m_position) - DEF_INF_MAX) / DEF_INF_BLEND));
263                                cur_blend = max(cur_blend, new_blend);
264                        }
265
266                        m_point_list[i].m_influence = cur_blend;
267                }
268        }
269
270        void ComputePointFromInfluenceValues(float seconds)
271        {
272                for (int i=0; i < m_point_list.Count(); i++)
273                {
274                        bool dir_influence_up = (m_point_list[i].m_influence - m_point_list[i].m_influence_previous > .0f)?(true):(false);
275
276                        int info_a = 0;
277                        int info_b = m_influence_list.Count();
278                        float step_a = -1.0f;
279                        float step_b = 2.0f;
280                        for (int j=0; j < m_influence_list.Count(); j++)
281                        {
282                                influence_infos &tmp = m_influence_list[j];
283                                if (m_influence_list[j].m_step <= m_point_list[i].m_influence &&
284                                        m_influence_list[j].m_step > step_a &&
285                                        ((dir_influence_up && !m_influence_list[j].m_ignore_step_up) ||
286                                        (!dir_influence_up && !m_influence_list[j].m_ignore_step_down)))
287                                {
288                                        info_a = j;
289                                        step_a = m_influence_list[j].m_step;
290                                }
291                                if (m_influence_list[j].m_step >= m_point_list[i].m_influence &&
292                                        m_influence_list[j].m_step < step_b &&
293                                        ((dir_influence_up && !m_influence_list[j].m_ignore_step_up) ||
294                                        (!dir_influence_up && !m_influence_list[j].m_ignore_step_down)))
295                                {
296                                        info_b = j;
297                                        step_b = m_influence_list[j].m_step;
298                                }
299                        }
300
301                        work_infos work_a = work_infos();
302                        work_infos work_b = work_infos();
303                        get_modified_point(m_influence_list[info_a], info_a, m_point_list[i], work_a);
304                        get_modified_point(m_influence_list[info_b], info_b, m_point_list[i], work_b);
305
306                        float divider = step_b - step_a;
307                        divider = (divider > .0f)?((m_point_list[i].m_influence - step_a) / divider):(1.0f);
308
309                        float damp_used = ((dir_influence_up)?(work_b.m_damp_up):(work_a.m_damp_down));
310                        damp_used = (seconds / (seconds + damp_used));
311
312                        work_a.m_pos            = work_a.m_pos + (work_b.m_pos - work_a.m_pos) * divider;
313                        work_a.m_rot            = work_a.m_rot + (work_b.m_rot - work_a.m_rot) * divider;
314                        work_a.m_scale          = work_a.m_scale + (work_b.m_scale - work_a.m_scale) * divider;
315                        work_a.m_scale_3d       = work_a.m_scale_3d + (work_b.m_scale_3d - work_a.m_scale_3d) * divider;
316
317                        m_point_list[i].m_final_pos                     += (work_a.m_pos - m_point_list[i].m_final_pos) * damp_used;
318                        m_point_list[i].m_final_rot                     += (work_a.m_rot - m_point_list[i].m_final_rot) * damp_used;
319                        m_point_list[i].m_final_scale           += (work_a.m_scale - m_point_list[i].m_final_scale) * damp_used;
320                        m_point_list[i].m_final_scale_3d        += (work_a.m_scale_3d - m_point_list[i].m_final_scale_3d) * damp_used;
321                }
322        }
323
324        void get_modified_point(const influence_infos &src_infos, const int random_idx, const transient_infos &src_transient, work_infos &dst_work)
325        {
326                //Base setup
327                dst_work.m_pos                  = src_transient.m_base_pos;
328                dst_work.m_rot                  = src_transient.m_base_rot;
329                dst_work.m_scale                = src_transient.m_base_scale;
330                dst_work.m_scale_3d             = src_transient.m_base_scale_3d;
331                dst_work.m_damp_down    = src_infos.m_damp_down[OFF_DEF];
332                dst_work.m_damp_up              = src_infos.m_damp_up[OFF_DEF];
333
334                //Added offset via given method
335                switch (src_infos.m_method)
336                {
337                        case INF_WAVE:
338                        {
339                                float point_angle = wave_angle + (float)src_transient.m_point_id * 2.0f * (float)M_PI * 2.0f / ((float)DEF_X * 1.051f);
340                                dst_work.m_pos += vec3(0.0f, (-1.0f + lol::cos(point_angle)) * 20.0f, 0.0f);
341                                //TODO : dst_work.m_rot += vec3(0,0,0);
342                        }
343                        case INF_DEFAULT:
344                        {
345                                dst_work.m_pos          += src_infos.m_offset_pos[OFF_DEF];
346                                dst_work.m_rot          += src_infos.m_offset_rot[OFF_DEF];
347                                dst_work.m_scale        += src_infos.m_offset_scale[OFF_DEF];
348                                dst_work.m_scale_3d += src_infos.m_offset_scale_3d[OFF_DEF];
349                                if (src_transient.random_list.Count() && random_idx > 0 && random_idx < src_transient.random_list.Count())
350                                {
351                                        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;
352                                        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;
353                                        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;
354                                        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;
355                                        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;
356                                        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;
357                                }
358                                break;
359                        }
360                }
361        }
362
363    virtual void TickDraw(float seconds)
364    {
365        WorldEntity::TickDraw(seconds);
366
367        if (!m_ready)
368        {
369            m_ref_mesh.MeshConvert();
370            m_ready = true;
371        }
372
373                m_rotation *= quat::rotate(seconds * 10.0f, vec3(0, 1, 0));
374                mat4 main_matrix = mat4::translate(m_position) * mat4(m_rotation);
375                for (int i=0; i < m_point_list.Count(); i++)
376                {
377                        mat4 model = main_matrix *
378                                mat4::translate(m_point_list[i].m_final_pos) *
379                                mat4(quat::fromeuler_yxz(m_point_list[i].m_final_rot)) *
380                                mat4::scale(m_point_list[i].m_final_scale_3d * m_point_list[i].m_final_scale);
381                        m_ref_mesh.Render(model);
382                }
383    }
384
385private:
386        //mesh used to render UserReactiveObject
387    EasyMesh m_ref_mesh;
388        //List of Pos/Rot/Etc... currently applied to the UserReactiveObject's meshes.
389        Array<transient_infos> m_point_list;
390        //List of influence steps
391        Array<influence_infos> m_influence_list;
392        //List of currently influencing points
393        Array<influencing_point_infos> m_influence_point_list;
394
395        float wave_angle;
396        float debug_point_angle;
397    bool m_ready;
398};
399
400#endif /* __USERREACTIVEOBJECT_H__ */
401
Note: See TracBrowser for help on using the repository browser.