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

Last change on this file since 1554 was 1554, checked in by touky, 7 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.