summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_canvas3d_mesh.c
diff options
context:
space:
mode:
authorOleksandr Shcherbina <o.shcherbina@samsung.com>2015-06-17 16:31:14 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-06-17 17:52:17 +0200
commitd409df1caa38ae7eac87f85ff4113484bc5b2099 (patch)
tree2adcbeadf2f4b2e7f4e7ba327a574c6620c23663 /src/lib/evas/canvas/evas_canvas3d_mesh.c
parent9bf6f14a8a59195fe9be004aaff446c51474fc5d (diff)
evas: change interface evas_3d to evas_canvas3d
Summary: Regard to https://phab.enlightenment.org/T2479 it is need for right generation Eolian files Reviewers: cedric Subscribers: cedric, tasn Differential Revision: https://phab.enlightenment.org/D2711 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to 'src/lib/evas/canvas/evas_canvas3d_mesh.c')
-rw-r--r--src/lib/evas/canvas/evas_canvas3d_mesh.c1081
1 files changed, 1081 insertions, 0 deletions
diff --git a/src/lib/evas/canvas/evas_canvas3d_mesh.c b/src/lib/evas/canvas/evas_canvas3d_mesh.c
new file mode 100644
index 0000000..fb20da7
--- /dev/null
+++ b/src/lib/evas/canvas/evas_canvas3d_mesh.c
@@ -0,0 +1,1081 @@
1#include "evas_common_private.h"
2#include "evas_private.h"
3
4#define MY_CLASS EVAS_CANVAS3D_MESH_CLASS
5
6static Evas_Canvas3D_Mesh_Frame *
7evas_canvas3d_mesh_frame_new(Evas_Canvas3D_Mesh *mesh)
8{
9 Evas_Canvas3D_Mesh_Frame *frame = NULL;
10 frame = (Evas_Canvas3D_Mesh_Frame *)calloc(1, sizeof(Evas_Canvas3D_Mesh_Frame));
11
12 if (frame == NULL)
13 {
14 ERR("Failed to allocate memory.");
15 return NULL;
16 }
17
18 frame->mesh = mesh;
19 evas_box3_empty_set(&frame->aabb);
20
21 return frame;
22}
23
24static void
25evas_canvas3d_mesh_frame_free(Evas_Canvas3D_Mesh_Frame *frame)
26{
27 int i;
28
29 if (frame->material)
30 evas_canvas3d_material_mesh_del(frame->material, frame->mesh);
31
32 for (i = 0; i < EVAS_CANVAS3D_VERTEX_ATTRIB_COUNT; i++)
33 {
34 if (frame->vertices[i].owns_data)
35 free(frame->vertices[i].data);
36 }
37
38 free(frame);
39}
40
41Evas_Canvas3D_Mesh_Frame *
42evas_canvas3d_mesh_frame_find(Evas_Canvas3D_Mesh_Data *pd, int frame)
43{
44 Eina_List *l;
45 Evas_Canvas3D_Mesh_Frame *f;
46
47 EINA_LIST_FOREACH(pd->frames, l, f)
48 {
49 if (f->frame == frame)
50 return f;
51 }
52
53 return NULL;
54}
55
56Eina_Bool
57evas_canvas3d_mesh_aabb_add_to_frame(Evas_Canvas3D_Mesh_Data *pd, int frame, int stride)
58{
59 Evas_Canvas3D_Mesh_Frame *curframe = evas_canvas3d_mesh_frame_find(pd, frame);
60 int i = 0, j = 0, step = 0, size = 0, max;
61 float vxmin, vymin, vzmin, vxmax, vymax, vzmax;
62 float *minmaxdata = NULL;
63 Evas_Box3 box3;
64
65 if (stride <= 0) return EINA_FALSE;
66
67 if (!curframe)
68 {
69 ERR("Invalid frame %i.", frame);
70 return EINA_FALSE;
71 }
72
73 step = curframe->vertices[EVAS_CANVAS3D_VERTEX_POSITION].element_count;
74 size = curframe->vertices[EVAS_CANVAS3D_VERTEX_POSITION].size;
75 minmaxdata = (float *)curframe->vertices[EVAS_CANVAS3D_VERTEX_POSITION].data;
76
77 if (!minmaxdata)
78 {
79 ERR("Invalid vertex data.");
80 return EINA_FALSE;
81 }
82
83 vxmax = vxmin = minmaxdata[0];
84 vymax = vymin = minmaxdata[1];
85 vzmax = vzmin = minmaxdata[2];
86 j += step;
87
88 max = size / stride;
89 for (i = 1; i < max; ++i)
90 {
91 vxmin > minmaxdata[j] ? vxmin = minmaxdata[j] : 0;
92 vxmax < minmaxdata[j] ? vxmax = minmaxdata[j] : 0;
93 vymin > minmaxdata[j + 1] ? vymin = minmaxdata[j + 1] : 0;
94 vymax < minmaxdata[j + 1] ? vymax = minmaxdata[j + 1] : 0;
95 vzmin > minmaxdata[j + 2] ? vzmin = minmaxdata[j + 2] : 0;
96 vzmax < minmaxdata[j + 2] ? vzmax = minmaxdata[j + 2] : 0;
97 j += step;
98 }
99
100 evas_box3_empty_set(&box3);
101 evas_box3_set(&box3, vxmin, vymin, vzmin, vxmax, vymax, vzmax);
102 curframe->aabb = box3;
103 return EINA_TRUE;
104}
105
106static inline void
107_mesh_init(Evas_Canvas3D_Mesh_Data *pd)
108{
109 pd->vertex_count = 0;
110 pd->frame_count = 0;
111 pd->frames = NULL;
112
113 pd->index_format = EVAS_CANVAS3D_INDEX_FORMAT_NONE;
114 pd->index_count = 0;
115 pd->indices = NULL;
116 pd->owns_indices = EINA_FALSE;
117 pd->assembly = EVAS_CANVAS3D_VERTEX_ASSEMBLY_TRIANGLES;
118
119 pd->nodes = NULL;
120 pd->blend_sfactor = EVAS_CANVAS3D_BLEND_ONE;
121 pd->blend_dfactor = EVAS_CANVAS3D_BLEND_ZERO;
122 pd->blending = EINA_FALSE;
123
124 pd->alpha_comparison = EVAS_CANVAS3D_COMPARISON_ALWAYS;
125 pd->alpha_ref_value = 0.0f;
126 pd->alpha_test_enabled = EINA_FALSE;
127#ifndef GL_GLES
128 pd->color_pick_key = -1.0;
129#else
130 pd->color_pick_key.r = 0.0;
131 pd->color_pick_key.g = 0.0;
132 pd->color_pick_key.b = 0.0;
133#endif
134 pd->color_pick_enabled = EINA_FALSE;
135}
136
137static inline void
138_mesh_fini(Evas_Canvas3D_Mesh_Data *pd)
139{
140 Eina_List *l;
141 Evas_Canvas3D_Mesh_Frame *f;
142
143 if (pd->frames)
144 {
145 EINA_LIST_FOREACH(pd->frames, l, f)
146 {
147 evas_canvas3d_mesh_frame_free(f);
148 }
149
150 eina_list_free(pd->frames);
151 }
152
153 if (pd->indices && pd->owns_indices)
154 free(pd->indices);
155
156 if (pd->nodes)
157 eina_hash_free(pd->nodes);
158}
159
160static Eina_Bool
161_mesh_node_geometry_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
162 void *data EINA_UNUSED, void *fdata)
163{
164 Evas_Canvas3D_Node *n = *(Evas_Canvas3D_Node **)key;
165 eo_do(n, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_NODE_MESH_GEOMETRY, (Evas_Canvas3D_Object *)fdata));
166 return EINA_TRUE;
167}
168
169static Eina_Bool
170_mesh_node_material_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
171 void *data EINA_UNUSED, void *fdata)
172{
173 Evas_Canvas3D_Node *n = *(Evas_Canvas3D_Node **)key;
174 eo_do(n, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_NODE_MESH_MATERIAL, (Evas_Canvas3D_Object *)fdata));
175 return EINA_TRUE;
176}
177
178static void
179_evas_canvas3d_mesh_evas_canvas3d_object_change_notify(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_State state, Evas_Canvas3D_Object *ref EINA_UNUSED)
180{
181 if (state == EVAS_CANVAS3D_STATE_MESH_MATERIAL)
182 {
183 if (pd->nodes)
184 eina_hash_foreach(pd->nodes, _mesh_node_material_change_notify, obj);
185 }
186 else
187 {
188 if (pd->nodes)
189 eina_hash_foreach(pd->nodes, _mesh_node_geometry_change_notify, obj);
190 }
191}
192
193EOLIAN static void
194_evas_canvas3d_mesh_evas_canvas3d_object_update_notify(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
195{
196 Eina_List *l;
197 Evas_Canvas3D_Mesh_Frame *f;
198
199 EINA_LIST_FOREACH(pd->frames, l, f)
200 {
201 if (f->material)
202 {
203 eo_do(f->material, evas_canvas3d_object_update());
204 }
205 }
206}
207
208
209void
210evas_canvas3d_mesh_node_add(Evas_Canvas3D_Mesh *mesh, Evas_Canvas3D_Node *node)
211{
212 int count = 0;
213 Evas_Canvas3D_Mesh_Data *pd = eo_data_scope_get(mesh, MY_CLASS);
214 if (pd->nodes == NULL)
215 {
216 pd->nodes = eina_hash_pointer_new(NULL);
217
218 if (pd->nodes == NULL)
219 {
220 ERR("Failed to create hash table.");
221 return;
222 }
223 }
224 else
225 count = (int)(uintptr_t)eina_hash_find(pd->nodes, &node);
226
227 eina_hash_set(pd->nodes, &node, (const void *)(uintptr_t)(count + 1));
228}
229
230void
231evas_canvas3d_mesh_node_del(Evas_Canvas3D_Mesh *mesh, Evas_Canvas3D_Node *node)
232{
233 int count = 0;
234 Evas_Canvas3D_Mesh_Data *pd = eo_data_scope_get(mesh, MY_CLASS);
235 if (pd->nodes == NULL)
236 {
237 ERR("No node to delete.");
238 return;
239 }
240
241 count = (int)(uintptr_t)eina_hash_find(pd->nodes, &node);
242
243 if (count == 1)
244 eina_hash_del(pd->nodes, &node, NULL);
245 else
246 eina_hash_set(pd->nodes, &node, (const void *)(uintptr_t)(count - 1));
247}
248
249
250EAPI Evas_Canvas3D_Mesh *
251evas_canvas3d_mesh_add(Evas *e)
252{
253 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
254 return NULL;
255 MAGIC_CHECK_END();
256 Evas_Object *eo_obj = eo_add(MY_CLASS, e);
257 return eo_obj;
258}
259
260EOLIAN static Eo *
261_evas_canvas3d_mesh_eo_base_constructor(Eo *obj, Evas_Canvas3D_Mesh_Data *pd)
262{
263 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
264 eo_do (obj, evas_canvas3d_object_type_set(EVAS_CANVAS3D_OBJECT_TYPE_MESH));
265 _mesh_init(pd);
266
267 return obj;
268}
269
270EOLIAN static void
271_evas_canvas3d_mesh_eo_base_destructor(Eo *obj, Evas_Canvas3D_Mesh_Data *pd)
272{
273 _mesh_fini(pd);
274 eo_do_super(obj, MY_CLASS, eo_destructor());
275}
276
277EOLIAN static void
278_evas_canvas3d_mesh_shade_mode_set(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Shade_Mode mode)
279{
280 if (pd->shade_mode != mode)
281 {
282 pd->shade_mode = mode;
283 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_SHADE_MODE, NULL));
284 }
285}
286
287EOLIAN static Evas_Canvas3D_Shade_Mode
288_evas_canvas3d_mesh_shade_mode_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
289{
290 return pd->shade_mode;
291}
292
293EOLIAN static void
294_evas_canvas3d_mesh_vertex_count_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, unsigned int count)
295{
296 pd->vertex_count = count;
297 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_VERTEX_COUNT, NULL));
298}
299
300EOLIAN static unsigned int
301_evas_canvas3d_mesh_vertex_count_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
302{
303 return pd->vertex_count;
304}
305
306EOLIAN static void
307_evas_canvas3d_mesh_frame_add(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, int frame)
308{
309 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
310
311 if (f != NULL)
312 {
313 ERR("Already existing frame.");
314 return;
315 }
316
317 f = evas_canvas3d_mesh_frame_new(obj);
318
319 if (f == NULL)
320 return;
321
322 f->frame = frame;
323 pd->frames = eina_list_append(pd->frames, f);
324 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_FRAME, NULL));
325}
326
327EOLIAN static void
328_evas_canvas3d_mesh_frame_del(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, int frame)
329{
330 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
331
332 if (f == NULL)
333 {
334 ERR("Not existing mesh frame.");
335 return;
336 }
337
338 pd->frames = eina_list_remove(pd->frames, f);
339 evas_canvas3d_mesh_frame_free(f);
340 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_FRAME, NULL));
341}
342
343EOLIAN static void
344_evas_canvas3d_mesh_frame_material_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, int frame, Evas_Canvas3D_Material *material)
345{
346 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
347
348 if (f == NULL)
349 {
350 ERR("Not existing mesh frame.");
351 return;
352 }
353
354 if (f->material == material)
355 return;
356
357 if (f->material)
358 {
359 evas_canvas3d_material_mesh_del(f->material, obj);
360 eo_unref(f->material);
361 }
362
363 f->material = material;
364 eo_ref(material);
365 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_MATERIAL, NULL));
366 evas_canvas3d_material_mesh_add(material, obj);
367}
368
369EOLIAN static Evas_Canvas3D_Material *
370_evas_canvas3d_mesh_frame_material_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, int frame)
371{
372 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
373
374 if (f == NULL)
375 {
376 ERR("Not existing mesh frame.");
377 return NULL;
378 }
379
380 return f->material;
381}
382
383EOLIAN static void
384_evas_canvas3d_mesh_frame_vertex_data_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, int frame, Evas_Canvas3D_Vertex_Attrib attrib, int stride, const void *data)
385{
386 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
387 int element_count;
388
389 if (f == NULL)
390 {
391 ERR("Not existing mesh frame.");
392 return;
393 }
394
395 if (stride < (int)sizeof(float))
396 {
397 ERR("Stride too small");
398 return;
399 }
400
401 if (attrib == EVAS_CANVAS3D_VERTEX_POSITION)
402 {
403 int i = 0, j = 0, size = stride/sizeof(float);
404 float vxmin, vymin, vzmin, vxmax, vymax, vzmax;
405 float *minmaxdata = (float *)data;
406 Evas_Box3 box3;
407
408 element_count = 3;
409
410 if (minmaxdata)
411 {
412 vxmax = vxmin = minmaxdata[0];
413 vymax = vymin = minmaxdata[1];
414 vzmax = vzmin = minmaxdata[2];
415 j += size;
416
417 for (i = 1; i < size; ++i)
418 {
419 vxmin > minmaxdata[j] ? vxmin = minmaxdata[j] : 0;
420 vxmax < minmaxdata[j] ? vxmax = minmaxdata[j] : 0;
421 vymin > minmaxdata[j + 1] ? vymin = minmaxdata[j + 1] : 0;
422 vymax < minmaxdata[j + 1] ? vymax = minmaxdata[j + 1] : 0;
423 vzmin > minmaxdata[j + 2] ? vzmin = minmaxdata[j + 2] : 0;
424 vzmax < minmaxdata[j + 2] ? vzmax = minmaxdata[j + 2] : 0;
425 j += size;
426 }
427
428 evas_box3_empty_set(&box3);
429 evas_box3_set(&box3, vxmin, vymin, vzmin, vxmax, vymax, vzmax);
430 f->aabb = box3;
431 }
432 else
433 {
434 ERR("Axis-Aligned Bounding Box wasn't added in frame %d ", frame);
435 }
436 }
437 else if (attrib == EVAS_CANVAS3D_VERTEX_NORMAL)
438 {
439 element_count = 3;
440 }
441 else if (attrib == EVAS_CANVAS3D_VERTEX_TANGENT)
442 {
443 element_count = 3;
444 }
445 else if (attrib == EVAS_CANVAS3D_VERTEX_COLOR)
446 {
447 element_count = 4;
448 }
449 else if (attrib == EVAS_CANVAS3D_VERTEX_TEXCOORD)
450 {
451 element_count = 2;
452 }
453 else
454 {
455 ERR("Invalid vertex attrib.");
456 return;
457 }
458
459 if (f->vertices[attrib].owns_data && f->vertices[attrib].data)
460 free(f->vertices[attrib].data);
461
462 f->vertices[attrib].size = 0;
463 f->vertices[attrib].stride = stride;
464 f->vertices[attrib].data = (void *)data;
465 f->vertices[attrib].owns_data = EINA_FALSE;
466 f->vertices[attrib].element_count = element_count;
467
468 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_VERTEX_DATA, NULL));
469}
470
471EOLIAN static void
472_evas_canvas3d_mesh_frame_vertex_data_copy_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, int frame, Evas_Canvas3D_Vertex_Attrib attrib, int stride, const void *data)
473{
474 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
475 Evas_Canvas3D_Vertex_Buffer *vb;
476 int size, element_count;
477
478 if (f == NULL)
479 {
480 ERR("Not existing mesh frame.");
481 return;
482 }
483
484 if (attrib == EVAS_CANVAS3D_VERTEX_POSITION)
485 {
486 element_count = 3;
487 }
488 else if (attrib == EVAS_CANVAS3D_VERTEX_NORMAL)
489 {
490 element_count = 3;
491 }
492 else if (attrib == EVAS_CANVAS3D_VERTEX_TANGENT)
493 {
494 element_count = 3;
495 }
496 else if (attrib == EVAS_CANVAS3D_VERTEX_COLOR)
497 {
498 element_count = 4;
499 }
500 else if (attrib == EVAS_CANVAS3D_VERTEX_TEXCOORD)
501 {
502 element_count = 2;
503 }
504 else
505 {
506 ERR("Invalid vertex attrib.");
507 return;
508 }
509
510 vb = &f->vertices[attrib];
511 size = element_count * sizeof(float) * pd->vertex_count;
512
513 if (!vb->owns_data || vb->size < size)
514 {
515 if (vb->owns_data && vb->data)
516 free(vb->data);
517
518 vb->data = malloc(size);
519
520 if (vb->data == NULL)
521 {
522 vb->element_count = 0;
523 vb->size = 0;
524 vb->stride = 0;
525 vb->owns_data = EINA_FALSE;
526
527 ERR("Failed to allocate memory.");
528 return;
529 }
530
531 vb->size = size;
532 vb->owns_data = EINA_TRUE;
533 }
534
535 vb->element_count = element_count;
536 vb->stride = 0;
537
538 if (data == NULL)
539 return;
540
541 if (stride == 0 || stride == (int)(element_count * sizeof(float)))
542 {
543 memcpy(vb->data, data, size);
544 }
545 else
546 {
547 int i;
548 float *dst = (float *)vb->data;
549 float *src = (float *)data;
550
551 if (element_count == 2)
552 {
553 for (i = 0; i <pd->vertex_count; i++)
554 {
555 *dst++ = src[0];
556 *dst++ = src[1];
557
558 src = (float *)((char *)src + stride);
559 }
560 }
561 else if (element_count == 3)
562 {
563 for (i = 0; i <pd->vertex_count; i++)
564 {
565 *dst++ = src[0];
566 *dst++ = src[1];
567 *dst++ = src[2];
568
569 src = (float *)((char *)src + stride);
570 }
571 }
572 else if (element_count == 4)
573 {
574 for (i = 0; i <pd->vertex_count; i++)
575 {
576 *dst++ = src[0];
577 *dst++ = src[1];
578 *dst++ = src[2];
579 *dst++ = src[3];
580
581 src = (float *)((char *)src + stride);
582 }
583 }
584 }
585
586 if (attrib == EVAS_CANVAS3D_VERTEX_POSITION &&
587 !evas_canvas3d_mesh_aabb_add_to_frame(pd, frame, stride))
588 {
589 ERR("Axis-Aligned Bounding Box wasn't added in frame %d ", frame);
590 }
591
592 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_VERTEX_DATA, NULL));
593}
594
595EOLIAN static void *
596_evas_canvas3d_mesh_frame_vertex_data_map(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, int frame, Evas_Canvas3D_Vertex_Attrib attrib)
597{
598 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
599
600 if (f == NULL)
601 {
602 ERR("Not existing mesh frame.");
603 return NULL;
604 }
605
606 if (f->vertices[attrib].mapped)
607 {
608 ERR("Try to map alreadly mapped data.");
609 return NULL;
610 }
611
612 f->vertices[attrib].mapped = EINA_TRUE;
613 return f->vertices[attrib].data;
614}
615
616EOLIAN static void
617_evas_canvas3d_mesh_frame_vertex_data_unmap(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, int frame, Evas_Canvas3D_Vertex_Attrib attrib)
618{
619 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
620
621 if (f == NULL)
622 {
623 ERR("Not existing mesh frame.");
624 return;
625 }
626
627 if (!f->vertices[attrib].mapped)
628 {
629 ERR("Try to unmap data which is not mapped yet.");
630 return;
631 }
632
633 f->vertices[attrib].mapped = EINA_FALSE;
634}
635
636EOLIAN static int
637_evas_canvas3d_mesh_frame_vertex_stride_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, int frame, Evas_Canvas3D_Vertex_Attrib attrib)
638{
639 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, frame);
640
641 if (f == NULL)
642 {
643 ERR("Not existing mesh frame.");
644 return 0;
645 }
646
647 return f->vertices[attrib].stride;
648}
649
650EOLIAN static void
651_evas_canvas3d_mesh_index_data_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Index_Format format, int count, const void *indices)
652{
653 if (pd->owns_indices && pd->indices)
654 free(pd->indices);
655
656 pd->index_format = format;
657 pd->index_count = count;
658 pd->index_size = 0;
659 pd->indices = (void *)indices;
660 pd->owns_indices = EINA_FALSE;
661
662 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_INDEX_DATA, NULL));
663}
664
665EOLIAN static void
666_evas_canvas3d_mesh_index_data_copy_set(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Index_Format format, int count, const void *indices)
667{
668 int size;
669
670 if (format == EVAS_CANVAS3D_INDEX_FORMAT_UNSIGNED_BYTE)
671 {
672 size = count * sizeof(unsigned char);
673 }
674 else if (format == EVAS_CANVAS3D_INDEX_FORMAT_UNSIGNED_SHORT)
675 {
676 size = count * sizeof(unsigned short);
677 }
678 else
679 {
680 ERR("Invalid index format.");
681 return;
682 }
683
684 if (!pd->owns_indices || pd->index_size < size)
685 {
686 if (pd->owns_indices && pd->indices)
687 free(pd->indices);
688
689 pd->indices = malloc(size);
690
691 if (pd->indices == NULL)
692 {
693 ERR("Failed to allocate memory.");
694 return;
695 }
696
697 pd->index_size = size;
698 pd->owns_indices = EINA_TRUE;
699 }
700
701 pd->index_format = format;
702 pd->index_count = count;
703
704 if (indices)
705 memcpy(pd->indices, indices, size);
706}
707
708EOLIAN static Evas_Canvas3D_Index_Format
709_evas_canvas3d_mesh_index_format_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
710{
711 return pd->index_format;
712}
713
714EOLIAN static int
715_evas_canvas3d_mesh_index_count_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
716{
717 return pd->index_count;
718}
719
720EOLIAN static void *
721_evas_canvas3d_mesh_index_data_map(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
722{
723 if (pd->index_mapped)
724 {
725 ERR("Try to map alreadly mapped data.");
726 return NULL;
727 }
728
729 pd->index_mapped = EINA_TRUE;
730 return pd->indices;
731}
732
733EOLIAN static void
734_evas_canvas3d_mesh_index_data_unmap(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
735{
736 if (!pd->index_mapped)
737 {
738 ERR("Try to unmap data which is not mapped yet.");
739 return;
740 }
741
742 pd->index_mapped = EINA_FALSE;
743}
744
745EOLIAN static void
746_evas_canvas3d_mesh_vertex_assembly_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Vertex_Assembly assembly)
747{
748 pd->assembly = assembly;
749 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_VERTEX_ASSEMBLY, NULL));
750}
751
752EOLIAN static Evas_Canvas3D_Vertex_Assembly
753_evas_canvas3d_mesh_vertex_assembly_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
754{
755 return pd->assembly;
756}
757
758EOLIAN static void
759_evas_canvas3d_mesh_fog_color_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
760{
761 evas_color_set(&pd->fog_color, r, g, b, a);
762 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_FOG, NULL));
763}
764
765EOLIAN static void
766_evas_canvas3d_mesh_fog_color_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd,
767 Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
768{
769 if (r) *r = pd->fog_color.r;
770 if (g) *g = pd->fog_color.g;
771 if (b) *b = pd->fog_color.b;
772 if (a) *a = pd->fog_color.a;
773}
774
775EOLIAN static void
776_evas_canvas3d_mesh_fog_enable_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Eina_Bool enabled)
777{
778 pd->fog_enabled = enabled;
779 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_FOG, NULL));
780}
781
782EOLIAN static Eina_Bool
783_evas_canvas3d_mesh_fog_enable_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
784{
785 return pd->fog_enabled;
786}
787
788EOLIAN static void
789_evas_canvas3d_mesh_blending_enable_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Eina_Bool blending)
790{
791 pd->blending = blending;
792 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_BLENDING, NULL));
793}
794
795EOLIAN static Eina_Bool
796_evas_canvas3d_mesh_blending_enable_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
797{
798 return pd->blending;
799}
800
801EOLIAN static void
802_evas_canvas3d_mesh_blending_func_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Blend_Func sfactor, Evas_Canvas3D_Blend_Func dfactor)
803{
804 pd->blend_sfactor = sfactor;
805 pd->blend_dfactor = dfactor;
806 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_BLENDING, NULL));
807}
808
809EOLIAN static void
810_evas_canvas3d_mesh_blending_func_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd,
811 Evas_Canvas3D_Blend_Func *sfactor, Evas_Canvas3D_Blend_Func *dfactor)
812{
813 if (sfactor) *sfactor = pd->blend_sfactor;
814 if (dfactor) *dfactor = pd->blend_dfactor;
815}
816
817EOLIAN static void
818_evas_canvas3d_mesh_alpha_func_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Evas_Canvas3D_Comparison comparison,
819 Evas_Real ref_value)
820{
821 if (pd->alpha_comparison == comparison && pd->alpha_ref_value == ref_value)
822 return;
823 pd->alpha_comparison = comparison;
824 pd->alpha_ref_value = ref_value;
825 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_ALPHA_TEST, NULL));
826}
827
828EOLIAN static void
829_evas_canvas3d_mesh_alpha_func_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd,
830 Evas_Canvas3D_Comparison *comparison,
831 Evas_Real *ref_value)
832{
833 if (comparison) *comparison = pd->alpha_comparison;
834 if (ref_value) *ref_value = pd->alpha_ref_value;
835}
836
837EOLIAN static void
838_evas_canvas3d_mesh_alpha_test_enable_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Eina_Bool enabled)
839{
840 pd->alpha_test_enabled = enabled;
841 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_ALPHA_TEST, NULL));
842}
843
844EOLIAN static Eina_Bool
845_evas_canvas3d_mesh_alpha_test_enable_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
846{
847 return pd->alpha_test_enabled;
848}
849
850EOLIAN static Eina_Bool
851_evas_canvas3d_mesh_efl_file_mmap_set(Eo *obj,
852 Evas_Canvas3D_Mesh_Data *pd,
853 const Eina_File *f, const char *key EINA_UNUSED)
854{
855 _mesh_fini(pd);
856 _mesh_init(pd);
857
858 if (f == NULL) return EINA_FALSE;
859
860 evas_common_load_model_from_eina_file(obj, f);
861
862 return EINA_TRUE;
863}
864
865/* FIXME: Imelemnt mmap_get and file_get. */
866
867EOLIAN static Eina_Bool
868_evas_canvas3d_mesh_efl_file_file_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd,
869 const char *file,
870 const char *key EINA_UNUSED)
871{
872 _mesh_fini(pd);
873 _mesh_init(pd);
874
875 if (file == NULL) return EINA_FALSE;
876
877 evas_common_load_model_from_file(obj, file);
878 return EINA_TRUE;
879}
880
881EOLIAN static Eina_Bool
882_evas_canvas3d_mesh_efl_file_save(Eo *obj, Evas_Canvas3D_Mesh_Data *pd,
883 const char *file,
884 const char *key EINA_UNUSED,
885 const char *flags EINA_UNUSED)
886{
887 if ((file == NULL) || (obj == NULL) || (pd == NULL)) return EINA_FALSE;
888
889 Evas_Canvas3D_Mesh_Frame *f = evas_canvas3d_mesh_frame_find(pd, 0);
890
891 if (f == NULL)
892 {
893 ERR("Not existing mesh frame.");
894 return EINA_FALSE;
895 }
896
897 evas_common_save_model_to_file(obj, file, f);
898 return EINA_TRUE;
899}
900
901EOLIAN static void
902_evas_canvas3d_mesh_from_primitive_set(Eo *obj,
903 Evas_Canvas3D_Mesh_Data *pd EINA_UNUSED,
904 int frame,
905 Eo *primitive)
906{
907 if ((primitive == NULL) || (obj == NULL)) return;
908
909 Evas_Canvas3D_Primitive_Data *ppd = eo_data_scope_get(primitive, EVAS_CANVAS3D_PRIMITIVE_CLASS);
910
911 evas_common_set_model_from_primitive(obj, frame, ppd);
912}
913
914void
915evas_canvas3d_mesh_interpolate_position_get(Evas_Vec3 *out, const Evas_Canvas3D_Vertex_Buffer *pos0, const Evas_Canvas3D_Vertex_Buffer *pos1,
916 Evas_Real weight, int index)
917{
918 if (pos1->data == NULL)
919 {
920 float *ptr;
921
922 if (pos0->stride != 0.0)
923 ptr = (float *)((char *)pos0->data + pos0->stride * index);
924 else
925 ptr = (float *)pos0->data + 3 * index;
926
927 out->x = ptr[0];
928 out->y = ptr[1];
929 out->z = ptr[2];
930 }
931 else
932 {
933 float *ptr0, *ptr1;
934
935 if (pos0->stride != 0.0)
936 ptr0 = (float *)((char *)pos0->data + pos0->stride * index);
937 else
938 ptr0 = (float *)pos0->data + 3 * index;
939
940 if (pos1->stride != 0.0)
941 ptr1 = (float *)((char *)pos1->data + pos1->stride * index);
942 else
943 ptr1 = (float *)pos1->data + 3 * index;
944
945 out->x = ptr0[0] * weight + ptr1[0] * (1.0 - weight);
946 out->y = ptr0[1] * weight + ptr1[1] * (1.0 - weight);
947 out->z = ptr0[2] * weight + ptr1[2] * (1.0 - weight);
948 }
949}
950
951static inline void
952_mesh_frame_find(Evas_Canvas3D_Mesh *mesh, int frame,
953 Eina_List **l, Eina_List **r)
954{
955 Eina_List *left, *right;
956 Evas_Canvas3D_Mesh_Frame *f0 = NULL, *f1;
957 Evas_Canvas3D_Mesh_Data *pdmesh = eo_data_scope_get(mesh, EVAS_CANVAS3D_MESH_CLASS);
958
959 left = pdmesh->frames;
960 right = eina_list_next(left);
961
962 while (right)
963 {
964 f0 = (Evas_Canvas3D_Mesh_Frame *)eina_list_data_get(left);
965 f1 = (Evas_Canvas3D_Mesh_Frame *)eina_list_data_get(right);
966
967 if (frame >= f0->frame && frame <= f1->frame)
968 break;
969
970 left = right;
971 right = eina_list_next(left);
972 }
973
974 if (right == NULL)
975 {
976 if (f0 && frame <= f0->frame)
977 {
978 *l = NULL;
979 *r = left;
980 }
981 else
982 {
983 *l = left;
984 *r = NULL;
985 }
986 return;
987 }
988
989 *l = left;
990 *r = right;
991}
992
993void
994evas_canvas3d_mesh_interpolate_vertex_buffer_get(Evas_Canvas3D_Mesh *mesh, int frame,
995 Evas_Canvas3D_Vertex_Attrib attrib,
996 Evas_Canvas3D_Vertex_Buffer *buf0,
997 Evas_Canvas3D_Vertex_Buffer *buf1,
998 Evas_Real *weight)
999{
1000 Eina_List *l, *r;
1001 const Evas_Canvas3D_Mesh_Frame *f0 = NULL, *f1 = NULL;
1002 _mesh_frame_find(mesh, frame, &l, &r);
1003
1004 while (l)
1005 {
1006 f0 = (const Evas_Canvas3D_Mesh_Frame *)eina_list_data_get(l);
1007
1008 if (f0->vertices[attrib].data != NULL)
1009 break;
1010
1011 l = eina_list_prev(l);
1012 f0 = NULL;
1013 }
1014
1015 while (r)
1016 {
1017 f1 = (const Evas_Canvas3D_Mesh_Frame *)eina_list_data_get(r);
1018
1019 if (f1->vertices[attrib].data != NULL)
1020 break;
1021
1022 r = eina_list_next(r);
1023 f1 = NULL;
1024 }
1025
1026 if (f0 == NULL && f1 == NULL)
1027 return;
1028
1029 if (f0 == NULL)
1030 {
1031 f0 = f1;
1032 }
1033 else if (f1 != NULL)
1034 {
1035 if (frame == f0->frame)
1036 {
1037 f1 = NULL;
1038 }
1039 else if (frame == f1->frame)
1040 {
1041 f0 = f1;
1042 f1 = NULL;
1043 }
1044 }
1045
1046 buf0->data = f0->vertices[attrib].data;
1047 buf0->stride = f0->vertices[attrib].stride;
1048 buf0->size = f0->vertices[attrib].size;
1049
1050 if (f1)
1051 {
1052 buf1->data = f1->vertices[attrib].data;
1053 buf1->stride = f1->vertices[attrib].stride;
1054 buf1->size = f1->vertices[attrib].size;
1055
1056 *weight = (f1->frame - frame) / (Evas_Real)(f1->frame - f0->frame);
1057 }
1058 else
1059 {
1060 buf1->data = NULL;
1061 buf1->stride = 0;
1062 buf1->size = 0;
1063
1064 *weight = 1.0;
1065 }
1066}
1067
1068EOLIAN static Eina_Bool
1069_evas_canvas3d_mesh_color_pick_enable_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Mesh_Data *pd)
1070{
1071 return pd->color_pick_enabled;
1072}
1073EOLIAN static void
1074_evas_canvas3d_mesh_color_pick_enable_set(Eo *obj, Evas_Canvas3D_Mesh_Data *pd, Eina_Bool enabled)
1075{
1076 if (pd->color_pick_enabled != enabled)
1077 pd->color_pick_enabled = enabled;
1078 eo_do(obj, evas_canvas3d_object_change(EVAS_CANVAS3D_STATE_MESH_COLOR_PICK, NULL));
1079}
1080
1081#include "canvas/evas_canvas3d_mesh.eo.c"