summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmytro Dadyka <d.dadyka@samsung.com>2015-02-17 15:33:05 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-02-17 15:39:48 +0100
commit1c74a1afe2d6353931ad4bab55a5ecbbd270b10a (patch)
tree1eb9a7d88e26dde429fecd7fdc6134138ed79e61
parent88932d3645ebcd5b52a3b133479f599006e5ab5b (diff)
evas: Evas_3D - refactor node shapes update mechanism.
Reviewers: cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D1984 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/lib/evas/canvas/evas_3d_node.c389
-rw-r--r--src/lib/evas/include/evas_3d_utils.h9
-rw-r--r--src/lib/evas/include/evas_private.h3
3 files changed, 233 insertions, 168 deletions
diff --git a/src/lib/evas/canvas/evas_3d_node.c b/src/lib/evas/canvas/evas_3d_node.c
index 62e2c1cb01..87de24801b 100644
--- a/src/lib/evas/canvas/evas_3d_node.c
+++ b/src/lib/evas/canvas/evas_3d_node.c
@@ -248,198 +248,251 @@ _node_item_update(Evas_3D_Node *node, void *data EINA_UNUSED)
248 return EINA_TRUE; 248 return EINA_TRUE;
249} 249}
250 250
251static Eina_Bool 251static void
252_node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED) 252_rotate_vertices(Evas_Vec4* orientation, int vertex_count, Evas_Vec3* vertex_position)
253{ 253{
254 Evas_3D_Node_Data *pd = eo_data_scope_get(node, EVAS_3D_NODE_CLASS); 254 int i;
255 Eina_Bool transform_dirty = EINA_FALSE, mesh_geom_dirty = EINA_FALSE; 255 if (orientation->x || orientation->y || orientation->z)
256 Eina_Bool mesh_frame_dirty = EINA_FALSE, member_dirty = EINA_FALSE; 256 for (i = 0; i < vertex_count; i++)
257 Eina_Bool frame_found = EINA_FALSE, is_change_orientation = EINA_FALSE; 257 evas_vec3_quaternion_rotate(&vertex_position[i], &vertex_position[i], orientation);
258 const Eina_List *m, *l; 258}
259 Evas_3D_Mesh *mesh;
260 int frame, count, size, i, j;
261 Evas_3D_Mesh_Frame *f;
262 float minx, miny, minz, maxx, maxy, maxz, vxmin, vymin, vzmin, vxmax, vymax, vzmax;
263 float *minmaxdata;
264 Evas_Vec4 orientation = {0};
265 Evas_Box3 box3;
266 259
267 eo_do(node, 260static void
268 transform_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_POSITION), 261_scale_vertices(Evas_Vec3* scale, int vertex_count, Evas_Vec3* vertex_position)
269 transform_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_ORIENTATION), 262{
270 transform_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_SCALE), 263 int i;
271 transform_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_ORIENTATION), 264 if ((scale->x != 1) || (scale->y != 1) || (scale->z != 1))
272 transform_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_POSITION), 265 for (i = 0; i < vertex_count; i++)
273 transform_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_SCALE), 266 evas_vec3_multiply(&vertex_position[i], &vertex_position[i], scale);
274 mesh_geom_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_GEOMETRY), 267}
275 mesh_frame_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_FRAME),
276 member_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MEMBER));
277 268
278 if (transform_dirty || 269static void
279 mesh_geom_dirty || 270_calculate_sphere(Evas_Sphere *sphere, int vertex_count, Evas_Vec3 *vertex_position)
280 mesh_frame_dirty || 271{
281 member_dirty) 272 float radius = 0.0001f;
282 { 273 Evas_Vec3 center, pos, diff;
283 if (pd->type == EVAS_3D_NODE_TYPE_MESH) 274 float len, alpha, alpha2;
284 { 275 int i, k;
285 276
286 if (pd->orientation_world.x || pd->orientation_world.y || pd->orientation_world.z) 277 // shuffle array for averaging algorithms error
287 { 278 for (i = 0; i < vertex_count; i++)
288 evas_vec4_set(&orientation, pd->orientation_world.x, pd->orientation_world.y, pd->orientation_world.z, pd->orientation_world.w); 279 {
289 is_change_orientation = EINA_TRUE; 280 k = i + rand()%(vertex_count-i);
290 } 281 pos = vertex_position[i];
282 vertex_position[i] = vertex_position[k];
283 vertex_position[k] = pos;
284 }
291 285
292 eo_do (node, m = (Eina_List *)evas_3d_node_mesh_list_get()); 286 center = vertex_position[0];
293 287
294 EINA_LIST_FOREACH(m, l, mesh) 288 for (k = 0; k < 2; k++)
289 {
290 for (i = 0; i < vertex_count; ++i)
291 {
292 pos = vertex_position[i];
293 evas_vec3_subtract(&diff, &pos, &center);
294 len = evas_vec3_length_get(&diff);
295 if (len > radius)
295 { 296 {
296 eo_do(node, frame = evas_3d_node_mesh_frame_get(mesh)); 297 alpha = len / radius;
297 Evas_3D_Mesh_Data *mpd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS); 298 alpha2 = alpha * alpha;
298 f = evas_3d_mesh_frame_find(mpd, frame); 299 radius = 0.5f * (alpha + 1 / alpha) * radius;
299 300 evas_vec3_scale(&pos, &pos, 1 - 1 / alpha2);
300 if (f) 301 evas_vec3_scale(&center, &center, (1 + 1 / alpha2));
301 { 302 evas_vec3_add(&center, &center, &pos);
302 i = 0, j = 0; 303 evas_vec3_scale(&center, &center, 0.5f);
304 }
305 }
306 }
303 307
304 evas_box3_empty_set(&box3); 308 for (i = 0; i < vertex_count; ++i)
305 count = f->vertices[EVAS_3D_VERTEX_POSITION].element_count; 309 {
306 size = f->vertices[EVAS_3D_VERTEX_POSITION].size; 310 pos = vertex_position[i];
307 if (!size) size = count * sizeof(float) * mpd->vertex_count; 311 evas_vec3_subtract(&diff, &pos, &center);
308 minmaxdata = (float *)malloc(size); 312 len = evas_vec3_length_get(&diff);
309 313
310 if (!minmaxdata) 314 if (len > radius)
311 { 315 {
312 ERR("Not enough memory."); 316 radius = (radius + len) / 2.0f;
313 return EINA_FALSE; 317 evas_vec3_scale(&diff, &diff, (len - radius) / len);
314 } 318 evas_vec3_add(&center, &center, &diff);
319 }
320 }
315 321
316 memcpy(minmaxdata, f->vertices[EVAS_3D_VERTEX_POSITION].data, size); 322 sphere->radius = radius;
323 sphere->center = center;
324}
317 325
318 /*get current coordinates, set orientation and find min/max*/ 326static void
319 if (is_change_orientation) 327_calculate_box(Evas_Box3 *box3, int vertex_count, Evas_Vec3 *vertex_position)
320 { 328{
321 Evas_Vec3 rotate; 329 int i = 0;
322 evas_vec3_set(&rotate, minmaxdata[0], minmaxdata[1], minmaxdata[2]); 330 float vxmin, vymin, vzmin, vxmax, vymax, vzmax;
323 evas_vec3_quaternion_rotate(&rotate, &rotate, &orientation);
324 vxmax = vxmin = minmaxdata[0] = rotate.x;
325 vymax = vymin = minmaxdata[1] = rotate.y;
326 vzmax = vzmin = minmaxdata[2] = rotate.z;
327 }
328 else
329 {
330 vxmax = vxmin = minmaxdata[0];
331 vymax = vymin = minmaxdata[1];
332 vzmax = vzmin = minmaxdata[2];
333 }
334 331
335 j += count; 332 vxmax = vxmin = vertex_position[0].x;
333 vymax = vymin = vertex_position[0].y;
334 vzmax = vzmin = vertex_position[0].z;
336 335
337 if (is_change_orientation) 336 for (i = 1; i < vertex_count; ++i)
338 { 337 {
339 for (i = 1; i < mpd->vertex_count; ++i) 338 if (vxmin > vertex_position[i].x) vxmin = vertex_position[i].x;
340 { 339 if (vxmax < vertex_position[i].x) vxmax = vertex_position[i].x;
341 Evas_Vec3 rotate; 340 if (vymin > vertex_position[i].y) vymin = vertex_position[i].y;
342 evas_vec3_set(&rotate, minmaxdata[j], minmaxdata[j + 1], minmaxdata[j + 2]); 341 if (vymax < vertex_position[i].y) vymax = vertex_position[i].y;
343 evas_vec3_quaternion_rotate(&rotate, &rotate, &orientation); 342 if (vzmin > vertex_position[i].z) vzmin = vertex_position[i].z;
344 minmaxdata[j] = rotate.x; 343 if (vzmax < vertex_position[i].z) vzmax = vertex_position[i].z;
345 minmaxdata[j + 1] = rotate.y; 344 }
346 minmaxdata[j + 2] = rotate.z; 345 evas_box3_set(box3, vxmin, vymin, vzmin, vxmax, vymax, vzmax);
347 vxmin > minmaxdata[j] ? vxmin = minmaxdata[j] : 0; 346}
348 vxmax < minmaxdata[j] ? vxmax = minmaxdata[j] : 0;
349 vymin > minmaxdata[j + 1] ? vymin = minmaxdata[j + 1] : 0;
350 vymax < minmaxdata[j + 1] ? vymax = minmaxdata[j + 1] : 0;
351 vzmin > minmaxdata[j + 2] ? vzmin = minmaxdata[j + 2] : 0;
352 vzmax < minmaxdata[j + 2] ? vzmax = minmaxdata[j + 2] : 0;
353 j += count;
354 }
355 }
356 else
357 {
358 for (i = 1; i < mpd->vertex_count; ++i)
359 {
360 vxmin > minmaxdata[j] ? vxmin = minmaxdata[j] : 0;
361 vxmax < minmaxdata[j] ? vxmax = minmaxdata[j] : 0;
362 vymin > minmaxdata[j + 1] ? vymin = minmaxdata[j + 1] : 0;
363 vymax < minmaxdata[j + 1] ? vymax = minmaxdata[j + 1] : 0;
364 vzmin > minmaxdata[j + 2] ? vzmin = minmaxdata[j + 2] : 0;
365 vzmax < minmaxdata[j + 2] ? vzmax = minmaxdata[j + 2] : 0;
366 j += count;
367 }
368 }
369 347
370 if (!frame_found) 348static void
371 { 349_pack_meshes_vertex_data(Evas_3D_Node *node, Evas_Vec3 **vertices, int *count)
372 evas_box3_empty_set(&pd->aabb); 350{
373 evas_box3_empty_set(&pd->obb); 351 const Eina_List *m, *l;
374 minx = vxmin; 352 Evas_3D_Mesh *mesh;
375 miny = vymin; 353 Evas_3D_Mesh_Frame *f;
376 minz = vzmin; 354 int j;
377 maxx = vxmax; 355 int frame;
378 maxy = vymax; 356 Evas_3D_Mesh_Data *mpd;
379 maxz = vzmax; 357 Evas_Vec3 *it;
380 } 358
381 else 359 *count = 0;
382 { 360 eo_do(node, m = (Eina_List *)evas_3d_node_mesh_list_get());
383 minx > vxmin ? minx = vxmin : 0; 361 EINA_LIST_FOREACH(m, l, mesh)
384 maxx < vxmax ? maxx = vxmax : 0; 362 {
385 miny > vymin ? miny = vymin : 0; 363 eo_do(node, frame = evas_3d_node_mesh_frame_get(mesh));
386 maxy < vymax ? maxy = vymax : 0; 364 mpd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
387 minz > vzmin ? minz = vzmin : 0; 365 f = evas_3d_mesh_frame_find(mpd, frame);
388 maxz < vzmax ? maxz = vzmax : 0; 366 if (f) *count += mpd->vertex_count;
389 } 367 }
390 368
391 frame_found = EINA_TRUE; 369 *vertices = (Evas_Vec3*)malloc(*count * sizeof(Evas_Vec3));
392 free(minmaxdata); 370 it = *vertices;
393 evas_box3_set(&box3, minx, miny, minz, maxx, maxy, maxz); 371 if (!*vertices)
394 evas_box3_union(&pd->aabb, &pd->aabb, &box3); 372 {
395 evas_box3_union(&pd->obb, &pd->obb, &f->aabb); 373 ERR("Not enough memory.");
396 } 374 return;
397 } 375 }
398 376
399 if (frame_found) 377 EINA_LIST_FOREACH(m, l, mesh)
378 {
379 eo_do(node, frame = evas_3d_node_mesh_frame_get(mesh));
380 mpd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
381 f = evas_3d_mesh_frame_find(mpd, frame);
382 if (f)
383 {
384 float *src = (float *)f->vertices[EVAS_3D_VERTEX_POSITION].data;
385 int stride = f->vertices[EVAS_3D_VERTEX_POSITION].stride;
386 if (!stride) stride = sizeof(float) * 3;
387 for (j = 0; j < mpd->vertex_count; j++)
400 { 388 {
401 if ((pd->scale_world.x != 1 || pd->scale_world.y != 1 || pd->scale_world.z != 1)) 389 it->x = src[0];
402 { 390 it->y = src[1];
403 Evas_Vec3 scale; 391 it->z = src[2];
404 evas_vec3_set(&scale, pd->scale_world.x, pd->scale_world.y, pd->scale_world.z); 392 it++;
405 evas_vec3_multiply(&pd->obb.p0, &scale, &pd->obb.p0); 393 src = (float *)((char *)src + stride);
406 evas_vec3_multiply(&pd->obb.p1, &scale, &pd->obb.p1);
407 evas_vec3_multiply(&pd->aabb.p0, &scale, &pd->aabb.p0);
408 evas_vec3_multiply(&pd->aabb.p1, &scale, &pd->aabb.p1);
409 }
410 if (is_change_orientation)
411 {
412 evas_vec3_quaternion_rotate(&pd->obb.p0, &pd->obb.p0, &orientation);
413 evas_vec3_quaternion_rotate(&pd->obb.p1, &pd->obb.p1, &orientation);
414 }
415 if ((pd->position_world.x || pd->position_world.y || pd->position_world.z))
416 {
417 Evas_Vec3 position;
418 evas_vec3_set(&position, pd->position_world.x, pd->position_world.y, pd->position_world.z);
419 evas_vec3_add(&pd->obb.p0, &position, &pd->obb.p0);
420 evas_vec3_add(&pd->obb.p1, &position, &pd->obb.p1);
421 evas_vec3_add(&pd->aabb.p0, &position, &pd->aabb.p0);
422 evas_vec3_add(&pd->aabb.p1, &position, &pd->aabb.p1);
423 }
424 } 394 }
425 } 395 }
426 else 396 }
427 { 397}
428 Eina_List *current;
429 Evas_3D_Node *datanode;
430 398
431 /* Update AABB, OBB, bounding sphere of this node. */ 399static void
432 evas_box3_empty_set(&pd->aabb); 400_update_node_shapes(Evas_3D_Node *node)
433 evas_box3_empty_set(&pd->obb); 401{
402 Evas_3D_Node_Data *pd = eo_data_scope_get(node, EVAS_3D_NODE_CLASS);
403 Eina_Bool transform_orientation_dirty;
404 Eina_Bool transform_scale_dirty;
405 Eina_Bool mesh_geom_dirty;
406 Evas_Vec3 scale;
407 Evas_Vec3 position = pd->position_world;
408 evas_vec3_set(&scale, pd->scale_world.x, pd->scale.y, pd->scale.z);
434 409
435 EINA_LIST_FOREACH(pd->members, current, datanode) 410 if (pd->type != EVAS_3D_NODE_TYPE_MESH)
411 {
412 evas_box3_empty_set(&pd->local_aabb);
413 evas_box3_empty_set(&pd->local_obb);
414 pd->local_bsphere.radius = 0;
415 evas_vec3_set(&pd->local_bsphere.center, 0, 0, 0);
416
417 pd->aabb.p0 = position;
418 pd->aabb.p1 = position;
419 pd->obb.p0 = position;
420 pd->obb.p1 = position;
421 pd->bsphere.radius = 0;
422 pd->bsphere.center = position;
423 return;
424 }
425
426 eo_do(node,
427 transform_orientation_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_ORIENTATION),
428 transform_orientation_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_ORIENTATION),
429 transform_scale_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_SCALE),
430 transform_scale_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_SCALE),
431 mesh_geom_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_GEOMETRY),
432 mesh_geom_dirty |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_FRAME));
433
434 if ( transform_orientation_dirty || transform_scale_dirty || mesh_geom_dirty)
435 {
436 int count;
437 Evas_Vec3 *vertices = NULL;
438 _pack_meshes_vertex_data(node, &vertices, &count);
439 if (count > 0)
440 {
441 _scale_vertices(&pd->scale_world, count, vertices);
442 if (mesh_geom_dirty)
443 _calculate_box(&pd->local_obb, count, vertices);
444
445 if (transform_scale_dirty || mesh_geom_dirty)
446 {
447 _calculate_sphere(&pd->local_bsphere, count, vertices);
448 }
449 if (transform_orientation_dirty || mesh_geom_dirty)
436 { 450 {
437 Evas_3D_Node_Data *datapd = eo_data_scope_get(datanode, EVAS_3D_NODE_CLASS); 451 _rotate_vertices(&pd->orientation_world, count, vertices);
438 evas_box3_union(&pd->obb, &pd->obb, &datapd->obb); 452 _calculate_box(&pd->local_aabb, count, vertices);
439 evas_box3_union(&pd->aabb, &pd->aabb, &datapd->aabb);
440 } 453 }
454 free(vertices);
441 } 455 }
442 evas_build_sphere(&pd->obb, &pd->bsphere); 456 }
457
458 pd->bsphere.radius = pd->local_bsphere.radius;
459 evas_vec3_quaternion_rotate(&pd->bsphere.center, &pd->local_bsphere.center, &pd->orientation_world);
460 evas_vec3_add(&pd->obb.p0, &position, &pd->local_obb.p0);
461 evas_vec3_add(&pd->obb.p1, &position, &pd->local_obb.p1);
462 evas_vec3_add(&pd->aabb.p0, &position, &pd->local_aabb.p0);
463 evas_vec3_add(&pd->aabb.p1, &position, &pd->local_aabb.p1);
464 evas_vec3_add(&pd->bsphere.center, &position, &pd->bsphere.center);
465}
466
467static Eina_Bool
468_node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
469{
470 Evas_3D_Node_Data *pd = eo_data_scope_get(node, EVAS_3D_NODE_CLASS);
471 Eina_Bool need_recalc;
472 Eina_List *current;
473 Evas_3D_Node *datanode;
474
475 eo_do(node,
476 need_recalc = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_ORIENTATION),
477 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_ORIENTATION),
478 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_POSITION),
479 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_POSITION),
480 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM_SCALE),
481 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT_SCALE),
482 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_GEOMETRY),
483 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_FRAME),
484 need_recalc |= evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MEMBER));
485
486 if (!need_recalc) return EINA_TRUE;
487
488 _update_node_shapes(node);
489
490 EINA_LIST_FOREACH(pd->members, current, datanode)
491 {
492 Evas_3D_Node_Data *datapd = eo_data_scope_get(datanode, EVAS_3D_NODE_CLASS);
493 evas_box3_union(&pd->obb, &pd->obb, &datapd->obb);
494 evas_box3_union(&pd->aabb, &pd->aabb, &datapd->aabb);
495 evas_build_sphere(&pd->aabb, &pd->bsphere);
443 } 496 }
444 497
445 return EINA_TRUE; 498 return EINA_TRUE;
diff --git a/src/lib/evas/include/evas_3d_utils.h b/src/lib/evas/include/evas_3d_utils.h
index 0cf9f34928..6f7f477a77 100644
--- a/src/lib/evas/include/evas_3d_utils.h
+++ b/src/lib/evas/include/evas_3d_utils.h
@@ -1764,6 +1764,15 @@ evas_build_sphere(const Evas_Box3 *box, Evas_Sphere *sphere)
1764} 1764}
1765 1765
1766static inline void 1766static inline void
1767evas_sphere_empty_set(Evas_Sphere *dst)
1768{
1769 dst->radius = 0;
1770 dst->center.x = 0;
1771 dst->center.y = 0;
1772 dst->center.z = 0;
1773}
1774
1775static inline void
1767evas_plane_normalize(Evas_Vec4 *plane) 1776evas_plane_normalize(Evas_Vec4 *plane)
1768{ 1777{
1769 Evas_Vec3 tmp; 1778 Evas_Vec3 tmp;
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index 5f69b22d41..4f4ada41c0 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -225,6 +225,9 @@ struct _Evas_3D_Node
225 Evas_Box3 aabb; 225 Evas_Box3 aabb;
226 Evas_Box3 obb; 226 Evas_Box3 obb;
227 Evas_Sphere bsphere; 227 Evas_Sphere bsphere;
228 Evas_Box3 local_aabb;
229 Evas_Box3 local_obb;
230 Evas_Sphere local_bsphere;
228 231
229 Evas_3D_Node_Type type; 232 Evas_3D_Node_Type type;
230 233