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 __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 |
|
---|
18 | struct 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 |
|
---|
47 | struct 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 |
|
---|
62 | struct 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 |
|
---|
76 | struct 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 |
|
---|
124 | struct 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 |
|
---|
166 | class Lolnament : public WorldEntity
|
---|
167 | {
|
---|
168 | public:
|
---|
169 | Lolnament()
|
---|
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 | ~Lolnament()
|
---|
200 | {
|
---|
201 | }
|
---|
202 |
|
---|
203 | char const *GetName() { return "<Lolnament>"; }
|
---|
204 |
|
---|
205 | protected:
|
---|
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 | for (int i=0; i < m_point_list.Count(); i++)
|
---|
231 | {
|
---|
232 | m_point_list[i].m_influence_previous = m_point_list[i].m_influence;
|
---|
233 |
|
---|
234 | float cur_blend = 0.0f;
|
---|
235 | for (int j=0; j < m_influence_point_list.Count(); j++)
|
---|
236 | {
|
---|
237 | float new_blend = 0.0f;
|
---|
238 | switch (m_influence_point_list[j].m_useage)
|
---|
239 | {
|
---|
240 | case BLD_SPHERE:
|
---|
241 | {
|
---|
242 | 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);
|
---|
243 | break;
|
---|
244 | }
|
---|
245 | case BLD_SQUARE:
|
---|
246 | {
|
---|
247 | vec3 point_diff = m_point_list[i].m_base_pos - m_influence_point_list[j].m_position;
|
---|
248 | point_diff = vec3(std::abs(point_diff.x), std::abs(point_diff.y), std::abs(point_diff.z));
|
---|
249 |
|
---|
250 | new_blend = min(1.0f - min(1.0f, max(0.0f, point_diff.z - DEF_INF_MAX) / DEF_INF_BLEND),
|
---|
251 | min(1.0f - min(1.0f, max(0.0f, point_diff.y - DEF_INF_MAX) / DEF_INF_BLEND),
|
---|
252 | 1.0f - min(1.0f, max(0.0f, point_diff.x - DEF_INF_MAX) / DEF_INF_BLEND)));
|
---|
253 | break;
|
---|
254 | }
|
---|
255 | default:
|
---|
256 | {
|
---|
257 | break;
|
---|
258 | }
|
---|
259 | };
|
---|
260 |
|
---|
261 | //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));
|
---|
262 | cur_blend = max(cur_blend, new_blend);
|
---|
263 | }
|
---|
264 |
|
---|
265 | m_point_list[i].m_influence = cur_blend;
|
---|
266 | }
|
---|
267 | }
|
---|
268 |
|
---|
269 | void ComputePointFromInfluenceValues(float seconds)
|
---|
270 | {
|
---|
271 | for (int i=0; i < m_point_list.Count(); i++)
|
---|
272 | {
|
---|
273 | bool dir_influence_up = (m_point_list[i].m_influence - m_point_list[i].m_influence_previous > .0f)?(true):(false);
|
---|
274 |
|
---|
275 | int info_a = 0;
|
---|
276 | int info_b = m_influence_list.Count();
|
---|
277 | float step_a = -1.0f;
|
---|
278 | float step_b = 2.0f;
|
---|
279 | for (int j=0; j < m_influence_list.Count(); j++)
|
---|
280 | {
|
---|
281 | influence_infos &tmp = m_influence_list[j];
|
---|
282 | if (m_influence_list[j].m_step <= m_point_list[i].m_influence &&
|
---|
283 | m_influence_list[j].m_step > step_a &&
|
---|
284 | ((dir_influence_up && !m_influence_list[j].m_ignore_step_up) ||
|
---|
285 | (!dir_influence_up && !m_influence_list[j].m_ignore_step_down)))
|
---|
286 | {
|
---|
287 | info_a = j;
|
---|
288 | step_a = m_influence_list[j].m_step;
|
---|
289 | }
|
---|
290 | if (m_influence_list[j].m_step >= m_point_list[i].m_influence &&
|
---|
291 | m_influence_list[j].m_step < step_b &&
|
---|
292 | ((dir_influence_up && !m_influence_list[j].m_ignore_step_up) ||
|
---|
293 | (!dir_influence_up && !m_influence_list[j].m_ignore_step_down)))
|
---|
294 | {
|
---|
295 | info_b = j;
|
---|
296 | step_b = m_influence_list[j].m_step;
|
---|
297 | }
|
---|
298 | }
|
---|
299 |
|
---|
300 | work_infos work_a = work_infos();
|
---|
301 | work_infos work_b = work_infos();
|
---|
302 | get_modified_point(m_influence_list[info_a], info_a, m_point_list[i], work_a);
|
---|
303 | get_modified_point(m_influence_list[info_b], info_b, m_point_list[i], work_b);
|
---|
304 |
|
---|
305 | float divider = step_b - step_a;
|
---|
306 | divider = (divider > .0f)?((m_point_list[i].m_influence - step_a) / divider):(1.0f);
|
---|
307 |
|
---|
308 | float damp_used = ((dir_influence_up)?(work_b.m_damp_up):(work_a.m_damp_down));
|
---|
309 | damp_used = (seconds / (seconds + damp_used));
|
---|
310 |
|
---|
311 | work_a.m_pos = work_a.m_pos + (work_b.m_pos - work_a.m_pos) * divider;
|
---|
312 | work_a.m_rot = work_a.m_rot + (work_b.m_rot - work_a.m_rot) * divider;
|
---|
313 | work_a.m_scale = work_a.m_scale + (work_b.m_scale - work_a.m_scale) * divider;
|
---|
314 | work_a.m_scale_3d = work_a.m_scale_3d + (work_b.m_scale_3d - work_a.m_scale_3d) * divider;
|
---|
315 |
|
---|
316 | m_point_list[i].m_final_pos += (work_a.m_pos - m_point_list[i].m_final_pos) * damp_used;
|
---|
317 | m_point_list[i].m_final_rot += (work_a.m_rot - m_point_list[i].m_final_rot) * damp_used;
|
---|
318 | m_point_list[i].m_final_scale += (work_a.m_scale - m_point_list[i].m_final_scale) * damp_used;
|
---|
319 | m_point_list[i].m_final_scale_3d += (work_a.m_scale_3d - m_point_list[i].m_final_scale_3d) * damp_used;
|
---|
320 | }
|
---|
321 | }
|
---|
322 |
|
---|
323 | void get_modified_point(const influence_infos &src_infos, const int random_idx, const transient_infos &src_transient, work_infos &dst_work)
|
---|
324 | {
|
---|
325 | //Base setup
|
---|
326 | dst_work.m_pos = src_transient.m_base_pos;
|
---|
327 | dst_work.m_rot = src_transient.m_base_rot;
|
---|
328 | dst_work.m_scale = src_transient.m_base_scale;
|
---|
329 | dst_work.m_scale_3d = src_transient.m_base_scale_3d;
|
---|
330 | dst_work.m_damp_down = src_infos.m_damp_down[OFF_DEF];
|
---|
331 | dst_work.m_damp_up = src_infos.m_damp_up[OFF_DEF];
|
---|
332 |
|
---|
333 | //Added offset via given method
|
---|
334 | switch (src_infos.m_method)
|
---|
335 | {
|
---|
336 | case INF_WAVE:
|
---|
337 | {
|
---|
338 | float point_angle = wave_angle + (float)src_transient.m_point_id * 2.0f * (float)M_PI * 2.0f / ((float)DEF_X * 1.051f);
|
---|
339 | dst_work.m_pos += vec3(0.0f, (-1.0f + lol::cos(point_angle)) * 20.0f, 0.0f);
|
---|
340 | //TODO : dst_work.m_rot += vec3(0,0,0);
|
---|
341 | }
|
---|
342 | case INF_DEFAULT:
|
---|
343 | {
|
---|
344 | dst_work.m_pos += src_infos.m_offset_pos[OFF_DEF];
|
---|
345 | dst_work.m_rot += src_infos.m_offset_rot[OFF_DEF];
|
---|
346 | dst_work.m_scale += src_infos.m_offset_scale[OFF_DEF];
|
---|
347 | dst_work.m_scale_3d += src_infos.m_offset_scale_3d[OFF_DEF];
|
---|
348 | if (src_transient.random_list.Count() && random_idx > 0 && random_idx < src_transient.random_list.Count())
|
---|
349 | {
|
---|
350 | 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;
|
---|
351 | 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;
|
---|
352 | 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;
|
---|
353 | 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;
|
---|
354 | 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;
|
---|
355 | 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;
|
---|
356 | }
|
---|
357 | break;
|
---|
358 | }
|
---|
359 | }
|
---|
360 | }
|
---|
361 |
|
---|
362 | virtual void TickDraw(float seconds)
|
---|
363 | {
|
---|
364 | WorldEntity::TickDraw(seconds);
|
---|
365 |
|
---|
366 | if (!m_ready)
|
---|
367 | {
|
---|
368 | m_ref_mesh.MeshConvert();
|
---|
369 | m_ready = true;
|
---|
370 | }
|
---|
371 |
|
---|
372 | m_rotation *= quat::rotate(seconds * 10.0f, vec3(0, 1, 0));
|
---|
373 | mat4 main_matrix = mat4::translate(m_position) * mat4(m_rotation);
|
---|
374 | for (int i=0; i < m_point_list.Count(); i++)
|
---|
375 | {
|
---|
376 | mat4 model = main_matrix *
|
---|
377 | mat4::translate(m_point_list[i].m_final_pos) *
|
---|
378 | mat4(quat::fromeuler_yxz(m_point_list[i].m_final_rot)) *
|
---|
379 | mat4::scale(m_point_list[i].m_final_scale_3d * m_point_list[i].m_final_scale);
|
---|
380 | m_ref_mesh.Render(model);
|
---|
381 | }
|
---|
382 | }
|
---|
383 |
|
---|
384 | private:
|
---|
385 | //mesh used to render Lolnament
|
---|
386 | EasyMesh m_ref_mesh;
|
---|
387 | //List of Pos/Rot/Etc... currently applied to the Lolnament's meshes.
|
---|
388 | Array<transient_infos> m_point_list;
|
---|
389 | //List of influence steps
|
---|
390 | Array<influence_infos> m_influence_list;
|
---|
391 | //List of currently influencing points
|
---|
392 | Array<influencing_point_infos> m_influence_point_list;
|
---|
393 |
|
---|
394 | float wave_angle;
|
---|
395 | float debug_point_angle;
|
---|
396 | bool m_ready;
|
---|
397 | };
|
---|
398 |
|
---|
399 | #endif /* __LOLNAMENT_H__ */
|
---|
400 |
|
---|