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

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

Added worldentity registration support.
Character now walks around.

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