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(cos(debug_point_angle) * DEF_X, 0, sin(debug_point_angle) * DEF_Z) * DEF_SIZE * 0.3f, 1.0f); |
---|
221 | m_influence_point_list << influencing_point_infos(BLD_SQUARE, vec3(-cos(debug_point_angle) * DEF_X, 0, -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 + 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 | |
---|