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

Last change on this file since 1554 was 1554, checked in by touky, 11 years ago

Added Location modifier in URO.
Added BtPhystest for Bullet Physics test project.

File size: 14.9 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 15
12#define DEF_Y 1
13#define DEF_Z 15
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                m_dist_modifier_influence_point(vec3(1.0f)),
172                m_dist_modifier_grid_point(vec3(1.0f)),
173                m_wave_angle(0.0f),
174                m_debug_point_angle(0.0f)
175    {
176
177                m_dist_modifier_influence_point.y = .0f;
178
179                m_ref_mesh.Compile( "[sc#f80 afcb10 8 8 -1]"
180                                                        "[sc#bbd afcb8 10 8 -1]"
181                                                        "[sc#44d afcb8 8 10 -1]");
182
183                m_influence_list << (influence_infos(0.0f, false, false, INF_WAVE)
184                                                                << point_infos_Part(OFF_DEF, vec3(.0f), vec3(.0f), .0f, vec3(.0f), .0f, 1.2f));
185                //m_influence_list << (influence_infos(0.3f, true, false)
186                //                                              << point_infos_Part(OFF_DEF, vec3(.0f, 40.0f, .0f), vec3(.0f, 90.0f, .0f)));
187                //m_influence_list << (influence_infos(0.7f, true, false)
188                //                                              << point_infos_Part(OFF_DEF, vec3(.0f, 40.0f, .0f), vec3(.0f, 90.0f, .0f)));
189                m_influence_list << (influence_infos(1.0f)
190                                                                << point_infos_Part(OFF_DEF, vec3(.0f, 80.0f, .0f), vec3(.0f, .0f, 90.0f), .0f, vec3(2.0f, .0f, .0f), .0f, .2f)
191                                                                /*
192                                                                << point_infos_Part(RND_MIN, vec3(-40.0f, .0f, -40.0f), vec3(.0f))
193                                                                << point_infos_Part(RND_MAX, vec3(40.0f, .0f, 40.0f), vec3(.0f))*/
194                                                                );
195
196                vec3 default_offset = vec3((float)DEF_X, (float)DEF_Y, (float)DEF_Z) * (float)DEF_SIZE * 0.5f;
197                for (int z=0; z < DEF_Z; z++)
198                        for (int y=0; y < DEF_Y; y++)
199                                for (int x=0; x < DEF_X; x++)
200                                        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());
201}
202
203    ~UserReactiveObject()
204    {
205    }
206
207    char const *GetName() { return "<UserReactiveObject>"; }
208
209        virtual bool InfluenceEntityRegistration(bool IsRegistering, WorldEntity *RegEntity)
210        {
211                for (int i = 0; i < m_influencing_entities.Count(); ++i)
212                {
213                        if (!m_influencing_entities[i])
214                                m_influencing_entities.Remove(i--);
215                        else if (m_influencing_entities[i] == RegEntity)
216                        {
217                                if (IsRegistering)
218                                        return false;
219                                else
220                                {
221                                        m_influencing_entities.Remove(i--);
222                                        Ticker::Unref(RegEntity);
223                                        return true;
224                                }
225                        }
226                }
227
228                m_influencing_entities << RegEntity;
229                Ticker::Ref(RegEntity);
230
231                return true;
232        }
233
234protected:
235    virtual void TickGame(float seconds)
236    {
237        WorldEntity::TickGame(seconds);
238
239                m_rotation *= quat::rotate(seconds * 10.0f, vec3(0, 1, 0));
240                m_local_to_world = mat4::translate(m_position) * mat4(m_rotation);
241
242                m_influence_point_list.Empty();
243
244                m_wave_angle += 3.0f * seconds;
245                m_debug_point_angle += 1.0f * seconds;
246
247                if (m_wave_angle > M_PI * 2.0f)
248                        m_wave_angle -= M_PI * 2.0f;
249                if (m_debug_point_angle > M_PI * 2.0f)
250                        m_debug_point_angle -= M_PI * 2.0f;
251
252                for (int i = 0; i < m_influencing_entities.Count(); ++i)
253                {
254                        if (m_influencing_entities[i])
255                        {
256                                mat4 LocalPos = inverse(m_local_to_world) * mat4::translate(m_influencing_entities[i]->m_position);
257                                m_influence_point_list << influencing_point_infos(BLD_SPHERE, LocalPos.v3.xyz, 1.0f);
258                        }
259                }
260
261                //m_influence_point_list << influencing_point_infos(BLD_SPHERE, vec3(lol::cos(m_debug_point_angle) * DEF_X, 0, lol::sin(m_debug_point_angle) * DEF_Z) * DEF_SIZE * 0.3f, 1.0f);
262                //m_influence_point_list << influencing_point_infos(BLD_SQUARE, vec3(-lol::cos(m_debug_point_angle) * DEF_X, 0, -lol::sin(m_debug_point_angle) * DEF_Z) * DEF_SIZE * 0.3f, 1.0f);
263
264                ComputeInfluenceValues();
265
266                ComputePointFromInfluenceValues(seconds);
267    }
268
269        void ComputeInfluenceValues()
270    {
271                //t = t * t * (3 - 2 * t)
272                for (int i=0; i < m_point_list.Count(); i++)
273                {
274                        float cur_blend = 0.0f;
275                        transient_infos &CurTI = m_point_list[i];
276
277                        CurTI.m_influence_previous = CurTI.m_influence;
278
279                        for (int j = 0; j < m_influence_point_list.Count(); j++)
280                        {
281                                float new_blend = 0.0f;
282                                influencing_point_infos &CurIPI = m_influence_point_list[j];
283                                vec3 ModBasePos = CurTI.m_base_pos * m_dist_modifier_grid_point;
284                                vec3 ModInfPos = CurIPI.m_position * m_dist_modifier_influence_point;
285
286                                switch (CurIPI.m_useage)
287                                {
288                                        case BLD_SPHERE:
289                                        {
290                                                new_blend = 1.0f - min(1.0f, max(0.0f, length(ModBasePos - ModInfPos) - DEF_INF_MAX) / DEF_INF_BLEND);
291                                                break;
292                                        }
293                                        case BLD_SQUARE:
294                                        {
295                                                vec3 point_diff = ModBasePos - ModInfPos;
296                                                point_diff = vec3(std::abs(point_diff.x), std::abs(point_diff.y), std::abs(point_diff.z));
297
298                                                new_blend = min(1.0f - min(1.0f, max(0.0f, point_diff.z - DEF_INF_MAX) / DEF_INF_BLEND),
299                                                                                min(1.0f - min(1.0f, max(0.0f, point_diff.y - DEF_INF_MAX) / DEF_INF_BLEND),
300                                                                                        1.0f - min(1.0f, max(0.0f, point_diff.x - DEF_INF_MAX) / DEF_INF_BLEND)));
301                                                break;
302                                        }
303                                        default:
304                                        {
305                                                break;
306                                        }
307                                };
308
309                                //cur_blend = max(cur_blend, 1.0f - min(1.0f, max(0.0f, length(ModBasePos - ModInfPos) - DEF_INF_MAX) / DEF_INF_BLEND));
310                                cur_blend = max(cur_blend, new_blend);
311                        }
312
313                        CurTI.m_influence = cur_blend;
314                }
315        }
316
317        void ComputePointFromInfluenceValues(float seconds)
318        {
319                for (int i=0; i < m_point_list.Count(); i++)
320                {
321                        bool dir_influence_up = (m_point_list[i].m_influence - m_point_list[i].m_influence_previous > .0f)?(true):(false);
322
323                        int info_a = 0;
324                        int info_b = m_influence_list.Count();
325                        float step_a = -1.0f;
326                        float step_b = 2.0f;
327                        for (int j=0; j < m_influence_list.Count(); j++)
328                        {
329                                influence_infos &tmp = m_influence_list[j];
330                                if (m_influence_list[j].m_step <= m_point_list[i].m_influence &&
331                                        m_influence_list[j].m_step > step_a &&
332                                        ((dir_influence_up && !m_influence_list[j].m_ignore_step_up) ||
333                                        (!dir_influence_up && !m_influence_list[j].m_ignore_step_down)))
334                                {
335                                        info_a = j;
336                                        step_a = m_influence_list[j].m_step;
337                                }
338                                if (m_influence_list[j].m_step >= m_point_list[i].m_influence &&
339                                        m_influence_list[j].m_step < step_b &&
340                                        ((dir_influence_up && !m_influence_list[j].m_ignore_step_up) ||
341                                        (!dir_influence_up && !m_influence_list[j].m_ignore_step_down)))
342                                {
343                                        info_b = j;
344                                        step_b = m_influence_list[j].m_step;
345                                }
346                        }
347
348                        work_infos work_a = work_infos();
349                        work_infos work_b = work_infos();
350                        get_modified_point(m_influence_list[info_a], info_a, m_point_list[i], work_a);
351                        get_modified_point(m_influence_list[info_b], info_b, m_point_list[i], work_b);
352
353                        float divider = step_b - step_a;
354                        divider = (divider > .0f)?((m_point_list[i].m_influence - step_a) / divider):(1.0f);
355
356                        float damp_used = ((dir_influence_up)?(work_b.m_damp_up):(work_a.m_damp_down));
357                        damp_used = (seconds / (seconds + damp_used));
358
359                        work_a.m_pos            = work_a.m_pos + (work_b.m_pos - work_a.m_pos) * divider;
360                        work_a.m_rot            = work_a.m_rot + (work_b.m_rot - work_a.m_rot) * divider;
361                        work_a.m_scale          = work_a.m_scale + (work_b.m_scale - work_a.m_scale) * divider;
362                        work_a.m_scale_3d       = work_a.m_scale_3d + (work_b.m_scale_3d - work_a.m_scale_3d) * divider;
363
364                        m_point_list[i].m_final_pos                     += (work_a.m_pos - m_point_list[i].m_final_pos) * damp_used;
365                        m_point_list[i].m_final_rot                     += (work_a.m_rot - m_point_list[i].m_final_rot) * damp_used;
366                        m_point_list[i].m_final_scale           += (work_a.m_scale - m_point_list[i].m_final_scale) * damp_used;
367                        m_point_list[i].m_final_scale_3d        += (work_a.m_scale_3d - m_point_list[i].m_final_scale_3d) * damp_used;
368                }
369        }
370
371        void get_modified_point(const influence_infos &src_infos, const int random_idx, const transient_infos &src_transient, work_infos &dst_work)
372        {
373                //Base setup
374                dst_work.m_pos                  = src_transient.m_base_pos;
375                dst_work.m_rot                  = src_transient.m_base_rot;
376                dst_work.m_scale                = src_transient.m_base_scale;
377                dst_work.m_scale_3d             = src_transient.m_base_scale_3d;
378                dst_work.m_damp_down    = src_infos.m_damp_down[OFF_DEF];
379                dst_work.m_damp_up              = src_infos.m_damp_up[OFF_DEF];
380
381                //Added offset via given method
382                switch (src_infos.m_method)
383                {
384                        case INF_WAVE:
385                        {
386                                float point_angle = m_wave_angle + (float)src_transient.m_point_id * 2.0f * (float)M_PI * 2.0f / ((float)DEF_X * 1.051f);
387                                dst_work.m_pos += vec3(0.0f, (-1.0f + lol::cos(point_angle)) * 20.0f, 0.0f);
388                                //TODO : dst_work.m_rot += vec3(0,0,0);
389                        }
390                        case INF_DEFAULT:
391                        {
392                                dst_work.m_pos          += src_infos.m_offset_pos[OFF_DEF];
393                                dst_work.m_rot          += src_infos.m_offset_rot[OFF_DEF];
394                                dst_work.m_scale        += src_infos.m_offset_scale[OFF_DEF];
395                                dst_work.m_scale_3d += src_infos.m_offset_scale_3d[OFF_DEF];
396                                if (src_transient.random_list.Count() && random_idx > 0 && random_idx < src_transient.random_list.Count())
397                                {
398                                        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;
399                                        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;
400                                        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;
401                                        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;
402                                        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;
403                                        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;
404                                }
405                                break;
406                        }
407                }
408        }
409
410    virtual void TickDraw(float seconds)
411    {
412        WorldEntity::TickDraw(seconds);
413
414        if (!m_ready)
415        {
416            m_ref_mesh.MeshConvert();
417            m_ready = true;
418        }
419
420                for (int i=0; i < m_point_list.Count(); i++)
421                {
422                        mat4 model = m_local_to_world *
423                                mat4::translate(m_point_list[i].m_final_pos) *
424                                mat4(quat::fromeuler_yxz(m_point_list[i].m_final_rot)) *
425                                mat4::scale(m_point_list[i].m_final_scale_3d * m_point_list[i].m_final_scale);
426                        m_ref_mesh.Render(model);
427                }
428    }
429
430private:
431        //mesh used to render UserReactiveObject
432    EasyMesh                                            m_ref_mesh;
433        //List of Pos/Rot/Etc... currently applied to the UserReactiveObject's meshes.
434        Array<transient_infos>                  m_point_list;
435        //List of influence steps
436        Array<influence_infos>                  m_influence_list;
437        //List of currently influencing points
438        Array<influencing_point_infos>  m_influence_point_list;
439        //List of currently influencing entities (converted in m_influence_point_list at each frame).
440        Array<WorldEntity*>                             m_influencing_entities;
441
442        vec3                                                    m_dist_modifier_influence_point;
443        vec3                                                    m_dist_modifier_grid_point;
444
445        float                                                   m_wave_angle;
446        float                                                   m_debug_point_angle;
447        mat4                                                    m_local_to_world;
448    bool                                                        m_ready;
449};
450
451#endif /* __USERREACTIVEOBJECT_H__ */
452
Note: See TracBrowser for help on using the repository browser.