summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Shcherbina <o.shcherbina@samsung.com>2014-12-01 06:26:28 +0100
committerCedric BAIL <cedric@osg.samsung.com>2014-12-01 06:26:32 +0100
commit54c1667d4e4dfc160fa8a7ce6118d6032645314a (patch)
treec5c1162727d02b2b50b5a83f19cf25b7043a6343
parent4366057dc640283d450701b828e48ff83e19f612 (diff)
evas: Evas_3D - add bounding sphere, revision frustum culling
Summary: Move check visibility of node from evas_3d_node to evas_3d_camera Move functionality (normalize, check distance, calculate frustum) in evas_3d_utils.h (we are planing use evas_is_sphere_in_frustum in evas_gl_3d.c - don't render mesh if it non visible) Add possibility check frustum by box, aabb, central point Refactor example frustum culling @feature Reviewers: Hermet, raster, cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D1420 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/lib/evas/Evas_Eo.h14
-rw-r--r--src/lib/evas/canvas/evas_3d_camera.c44
-rw-r--r--src/lib/evas/canvas/evas_3d_camera.eo19
-rw-r--r--src/lib/evas/canvas/evas_3d_node.c120
-rw-r--r--src/lib/evas/canvas/evas_3d_node.eo33
-rw-r--r--src/lib/evas/include/evas_3d_utils.h264
-rw-r--r--src/lib/evas/include/evas_private.h1
7 files changed, 378 insertions, 117 deletions
diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h
index fd48f74..9d8e93f 100644
--- a/src/lib/evas/Evas_Eo.h
+++ b/src/lib/evas/Evas_Eo.h
@@ -566,6 +566,20 @@ typedef enum _Evas_3D_Index_Format
566} Evas_3D_Index_Format; 566} Evas_3D_Index_Format;
567 567
568/** 568/**
569 * Frustum modes
570 *
571 * @since 1.12
572 * @ingroup Evas_3D_Types
573 */
574typedef enum _Evas_3D_Frustum_Mode
575{
576 EVAS_3D_FRUSTUM_MODE_BSPHERE,
577 EVAS_3D_FRUSTUM_MODE_AABB,
578 EVAS_3D_FRUSTUM_MODE_CENTRAL_POINT
579} Evas_3D_Frustum_Mode;
580
581
582/**
569 * Vertex assembly modes 583 * Vertex assembly modes
570 * 584 *
571 * Vertex assembly represents how the vertices are organized into geometric 585 * Vertex assembly represents how the vertices are organized into geometric
diff --git a/src/lib/evas/canvas/evas_3d_camera.c b/src/lib/evas/canvas/evas_3d_camera.c
index d8a7d24..c6da2d3 100644
--- a/src/lib/evas/canvas/evas_3d_camera.c
+++ b/src/lib/evas/canvas/evas_3d_camera.c
@@ -140,5 +140,49 @@ _evas_3d_camera_projection_ortho_set(Eo *obj, Evas_3D_Camera_Data *pd,
140 eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_CAMERA_PROJECTION, NULL)); 140 eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_CAMERA_PROJECTION, NULL));
141} 141}
142 142
143EOLIAN static Eina_Bool
144_evas_3d_camera_node_visible_get(Eo *obj EINA_UNUSED, Evas_3D_Camera_Data *pd, Evas_3D_Node *camera_node, Evas_3D_Node *node, Evas_3D_Frustum_Mode key)
145{
146 Evas_Mat4 matrix_vp;
147 Evas_Vec4 planes[6];
148 Evas_3D_Node_Data *pd_node = eo_data_scope_get(node, EVAS_3D_NODE_CLASS);
149 Evas_3D_Node_Data *pd_camera = eo_data_scope_get(camera_node, EVAS_3D_NODE_CLASS);
150 Evas_Vec3 central_point;
151
152 if (!node || pd_node->type != EVAS_3D_NODE_TYPE_MESH)
153 {
154 ERR("Mesh node %p type mismatch.", node);
155 return EINA_FALSE;
156 }
157
158 if (!camera_node || pd_camera->type != EVAS_3D_NODE_TYPE_CAMERA)
159 {
160 ERR("Camera node %p type mismatch.", camera_node);
161 return EINA_FALSE;
162 }
163
164 /*get need matrix like multiply projection matrix with view matrix*/
165 evas_mat4_multiply(&matrix_vp, &pd->projection, &pd_camera->data.camera.matrix_world_to_eye);
166
167 evas_frustum_calculate(planes, &matrix_vp);
168
169 if (key == EVAS_3D_FRUSTUM_MODE_BSPHERE)
170 return evas_is_sphere_in_frustum(&pd_node->bsphere, planes);
171 else if (key == EVAS_3D_FRUSTUM_MODE_AABB)
172 return evas_is_box_in_frustum(&pd_node->aabb, planes);
173 else if (key == EVAS_3D_FRUSTUM_MODE_CENTRAL_POINT)
174 {
175 central_point.x = (pd_node->aabb.p0.x + pd_node->aabb.p1.x) / 2;
176 central_point.y = (pd_node->aabb.p0.y + pd_node->aabb.p1.y) / 2;
177 central_point.z = (pd_node->aabb.p0.z + pd_node->aabb.p1.z) / 2;
178 return evas_is_point_in_frustum(&central_point, planes);
179 }
180 else
181 {
182 ERR("Unknown frustun mode.");
183 return EINA_TRUE;
184 }
185}
186
143#include "canvas/evas_3d_camera.eo.c" 187#include "canvas/evas_3d_camera.eo.c"
144 188
diff --git a/src/lib/evas/canvas/evas_3d_camera.eo b/src/lib/evas/canvas/evas_3d_camera.eo
index 4b4d95e..45e9e9a 100644
--- a/src/lib/evas/canvas/evas_3d_camera.eo
+++ b/src/lib/evas/canvas/evas_3d_camera.eo
@@ -96,6 +96,25 @@ class Evas_3D_Camera (Evas_3D_Object, Evas.Common_Interface)
96 Evas_Real dfar; /*@ Distance to far clipping plane. */ 96 Evas_Real dfar; /*@ Distance to far clipping plane. */
97 } 97 }
98 } 98 }
99 node_visible_get {
100 /*@
101 Check is bounding sphere of given node inside frustum of camera node.
102 *
103 * @param camera The given camera node.
104 * @param node The given node.
105 * @return @c EINA_TRUE in frustum, @c EINA_FALSE otherwise
106
107 * If the nodes are @ NULL or nodes type mismatch error wrong type of nodes will be generated and returned @ EINA_FALSE.
108
109 * @ingroup Evas_3D_Camera
110 */
111 return: bool;
112 params {
113 @in Evas_3D_Node *camera_node;
114 @in Evas_3D_Node *node;
115 @in Evas_3D_Frustum_Mode key;
116 }
117 }
99 } 118 }
100 119
101 implements { 120 implements {
diff --git a/src/lib/evas/canvas/evas_3d_node.c b/src/lib/evas/canvas/evas_3d_node.c
index 7b30486..bcbb1db 100644
--- a/src/lib/evas/canvas/evas_3d_node.c
+++ b/src/lib/evas/canvas/evas_3d_node.c
@@ -204,6 +204,7 @@ _node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
204 Eina_Bool transform_dirty = EINA_FALSE, mesh_geom_dirty = EINA_FALSE; 204 Eina_Bool transform_dirty = EINA_FALSE, mesh_geom_dirty = EINA_FALSE;
205 Eina_Bool mesh_frame_dirty = EINA_FALSE, member_dirty = EINA_FALSE; 205 Eina_Bool mesh_frame_dirty = EINA_FALSE, member_dirty = EINA_FALSE;
206 Eina_Bool frame_found = EINA_FALSE, is_change_orientation = EINA_FALSE; 206 Eina_Bool frame_found = EINA_FALSE, is_change_orientation = EINA_FALSE;
207 Eina_Bool parent_dirty = EINA_FALSE;
207 const Eina_List *m, *l; 208 const Eina_List *m, *l;
208 Evas_3D_Mesh *mesh; 209 Evas_3D_Mesh *mesh;
209 int frame, count, size, i, j; 210 int frame, count, size, i, j;
@@ -217,19 +218,21 @@ _node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
217 transform_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM), 218 transform_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM),
218 mesh_geom_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_GEOMETRY), 219 mesh_geom_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_GEOMETRY),
219 mesh_frame_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_FRAME), 220 mesh_frame_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_FRAME),
221 parent_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT),
220 member_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MEMBER)); 222 member_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MEMBER));
221 223
222 if (transform_dirty || 224 if (transform_dirty ||
223 mesh_geom_dirty || 225 mesh_geom_dirty ||
224 mesh_frame_dirty || 226 mesh_frame_dirty ||
225 member_dirty) 227 member_dirty ||
228 parent_dirty)
226 { 229 {
227 if (pd->type == EVAS_3D_NODE_TYPE_MESH) 230 if (pd->type == EVAS_3D_NODE_TYPE_MESH)
228 { 231 {
229 232
230 if (pd->orientation.x || pd->orientation.y || pd->orientation.z) 233 if (pd->orientation_world.x || pd->orientation_world.y || pd->orientation_world.z)
231 { 234 {
232 evas_vec4_set(&orientation, pd->orientation.x, pd->orientation.y, pd->orientation.z, pd->orientation.w); 235 evas_vec4_set(&orientation, pd->orientation_world.x, pd->orientation_world.y, pd->orientation_world.z, pd->orientation_world.w);
233 is_change_orientation = EINA_TRUE; 236 is_change_orientation = EINA_TRUE;
234 } 237 }
235 238
@@ -347,19 +350,19 @@ _node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
347 evas_vec3_quaternion_rotate(&pd->obb.p0, &pd->obb.p0, &orientation); 350 evas_vec3_quaternion_rotate(&pd->obb.p0, &pd->obb.p0, &orientation);
348 evas_vec3_quaternion_rotate(&pd->obb.p1, &pd->obb.p1, &orientation); 351 evas_vec3_quaternion_rotate(&pd->obb.p1, &pd->obb.p1, &orientation);
349 } 352 }
350 if ((pd->scale.x != 1 || pd->scale.y != 1 || pd->scale.z != 1)) 353 if ((pd->scale_world.x != 1 || pd->scale_world.y != 1 || pd->scale_world.z != 1))
351 { 354 {
352 Evas_Vec3 scale; 355 Evas_Vec3 scale;
353 evas_vec3_set(&scale, pd->scale.x, pd->scale.y, pd->scale.z); 356 evas_vec3_set(&scale, pd->scale_world.x, pd->scale_world.y, pd->scale_world.z);
354 evas_vec3_multiply(&pd->obb.p0, &scale, &pd->obb.p0); 357 evas_vec3_multiply(&pd->obb.p0, &scale, &pd->obb.p0);
355 evas_vec3_multiply(&pd->obb.p1, &scale, &pd->obb.p1); 358 evas_vec3_multiply(&pd->obb.p1, &scale, &pd->obb.p1);
356 evas_vec3_multiply(&pd->aabb.p0, &scale, &pd->aabb.p0); 359 evas_vec3_multiply(&pd->aabb.p0, &scale, &pd->aabb.p0);
357 evas_vec3_multiply(&pd->aabb.p1, &scale, &pd->aabb.p1); 360 evas_vec3_multiply(&pd->aabb.p1, &scale, &pd->aabb.p1);
358 } 361 }
359 if ((pd->position.x || pd->position.y || pd->position.z)) 362 if ((pd->position_world.x || pd->position_world.y || pd->position_world.z))
360 { 363 {
361 Evas_Vec3 position; 364 Evas_Vec3 position;
362 evas_vec3_set(&position, pd->position.x, pd->position.y, pd->position.z); 365 evas_vec3_set(&position, pd->position_world.x, pd->position_world.y, pd->position_world.z);
363 evas_vec3_add(&pd->obb.p0, &position, &pd->obb.p0); 366 evas_vec3_add(&pd->obb.p0, &position, &pd->obb.p0);
364 evas_vec3_add(&pd->obb.p1, &position, &pd->obb.p1); 367 evas_vec3_add(&pd->obb.p1, &position, &pd->obb.p1);
365 evas_vec3_add(&pd->aabb.p0, &position, &pd->aabb.p0); 368 evas_vec3_add(&pd->aabb.p0, &position, &pd->aabb.p0);
@@ -372,7 +375,7 @@ _node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
372 Eina_List *current; 375 Eina_List *current;
373 Evas_3D_Node *datanode; 376 Evas_3D_Node *datanode;
374 377
375 /* Update AABB and OBB of this node. */ 378 /* Update AABB, OBB, bounding sphere of this node. */
376 evas_box3_empty_set(&pd->aabb); 379 evas_box3_empty_set(&pd->aabb);
377 evas_box3_empty_set(&pd->obb); 380 evas_box3_empty_set(&pd->obb);
378 381
@@ -383,6 +386,7 @@ _node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
383 evas_box3_union(&pd->aabb, &pd->aabb, &datapd->aabb); 386 evas_box3_union(&pd->aabb, &pd->aabb, &datapd->aabb);
384 } 387 }
385 } 388 }
389 evas_build_sphere(&pd->obb, &pd->bsphere);
386 } 390 }
387 391
388 return EINA_TRUE; 392 return EINA_TRUE;
@@ -1362,99 +1366,13 @@ _evas_3d_node_bounding_box_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Evas_
1362 if (z2) *z2 = pd->aabb.p1.z; 1366 if (z2) *z2 = pd->aabb.p1.z;
1363} 1367}
1364 1368
1365EOLIAN static int 1369EOLIAN static void
1366_evas_3d_node_obb_frustum_check(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Evas_3D_Node *camera_node) 1370_evas_3d_node_bounding_sphere_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Evas_Real *x, Evas_Real *y, Evas_Real *z, Evas_Real *r)
1367{ 1371{
1368 Evas_Mat4 matrix_eye = { { 0 } }; 1372 if (x) *x = pd->bsphere.center.x;
1369 Evas_Mat4 matrix_local_to_world; 1373 if (y) *y = pd->bsphere.center.y;
1370 Evas_Mat4 matrix_mv; 1374 if (z) *z = pd->bsphere.center.z;
1371 Evas_Mat4 matrix_mvp; 1375 if (r) *r = pd->bsphere.radius;
1372 Evas_Vec4 plane_right, plane_left, plane_bottom, plane_top, plane_far, plane_near, tmp;
1373 int frustum = 0;
1374 Evas_3D_Node_Data *camera_pd = eo_data_scope_get(camera_node, EVAS_3D_CAMERA_CLASS);
1375 Evas_3D_Camera_Data *camera = eo_data_scope_get(camera_pd->data.camera.camera, EVAS_3D_CAMERA_CLASS);
1376
1377
1378 if (camera_pd->type != EVAS_3D_NODE_TYPE_CAMERA)
1379 {
1380 ERR("Nodes type mismatch.");
1381 return -1;
1382 }
1383
1384#define CHECK_IN_FRUSTUM_MIN(name) \
1385 (((plane_##name.x * pd->obb.p0.x + plane_##name.y * pd->obb.p0.y + plane_##name.z * pd->obb.p0.z + plane_##name.w) >= 0) ? EINA_TRUE : EINA_FALSE)
1386
1387#define CHECK_IN_FRUSTUM_MAX(name) \
1388 (((plane_##name.x * pd->obb.p1.x + plane_##name.y * pd->obb.p1.y + plane_##name.z * pd->obb.p1.z + plane_##name.w) >= 0) ? EINA_TRUE : EINA_FALSE)
1389
1390#define NORMALIZE(name) \
1391 evas_vec4_copy(&tmp, &plane_##name); \
1392 plane_##name.x = plane_##name.x / sqrtf(evas_vec4_length_square_get(&tmp)); \
1393 plane_##name.y = plane_##name.y / sqrtf(evas_vec4_length_square_get(&tmp)); \
1394 plane_##name.z = plane_##name.z / sqrtf(evas_vec4_length_square_get(&tmp)); \
1395 plane_##name.w = plane_##name.w / sqrtf(evas_vec4_length_square_get(&tmp));
1396
1397 /*get need matrix like multiply view matrix with projection matrix*/
1398 evas_mat4_inverse_build(&matrix_eye, &camera_pd->position_world, &camera_pd->orientation_world, &camera_pd->scale_world);
1399 evas_mat4_build(&matrix_local_to_world, &pd->position_world, &pd->orientation_world, &pd->scale_world);
1400 evas_mat4_multiply(&matrix_mv, &matrix_eye, &matrix_local_to_world);
1401 evas_mat4_multiply(&matrix_mvp, &camera->projection, &matrix_mv);
1402
1403 /*get planes and normilize results*/
1404 evas_vec4_set(&plane_right, matrix_mvp.m[3] - matrix_mvp.m[0],
1405 matrix_mvp.m[7] - matrix_mvp.m[4],
1406 matrix_mvp.m[11] - matrix_mvp.m[8],
1407 matrix_mvp.m[15] - matrix_mvp.m[12]);
1408 NORMALIZE(right)
1409
1410 evas_vec4_set(&plane_left, matrix_mvp.m[3] + matrix_mvp.m[0],
1411 matrix_mvp.m[7] + matrix_mvp.m[4],
1412 matrix_mvp.m[11] + matrix_mvp.m[8],
1413 matrix_mvp.m[15] + matrix_mvp.m[12]);
1414 NORMALIZE(left)
1415
1416 evas_vec4_set(&plane_bottom, matrix_mvp.m[3] + matrix_mvp.m[1],
1417 matrix_mvp.m[7] + matrix_mvp.m[5],
1418 matrix_mvp.m[11] + matrix_mvp.m[9],
1419 matrix_mvp.m[15] + matrix_mvp.m[13]);
1420 NORMALIZE(bottom)
1421
1422 evas_vec4_set(&plane_top, matrix_mvp.m[3] - matrix_mvp.m[1],
1423 matrix_mvp.m[7] - matrix_mvp.m[5],
1424 matrix_mvp.m[11] - matrix_mvp.m[9],
1425 matrix_mvp.m[15] - matrix_mvp.m[13]);
1426 NORMALIZE(top)
1427
1428 evas_vec4_set(&plane_far, matrix_mvp.m[3] - matrix_mvp.m[2],
1429 matrix_mvp.m[7] - matrix_mvp.m[6],
1430 matrix_mvp.m[11] - matrix_mvp.m[10],
1431 matrix_mvp.m[15] - matrix_mvp.m[14]);
1432 NORMALIZE(far)
1433
1434 evas_vec4_set(&plane_near, matrix_mvp.m[3] + matrix_mvp.m[2],
1435 matrix_mvp.m[7] + matrix_mvp.m[6],
1436 matrix_mvp.m[11] + matrix_mvp.m[10],
1437 matrix_mvp.m[15] + matrix_mvp.m[14]);
1438 NORMALIZE(near)
1439
1440#undef NORMALIZE
1441
1442 /*check OBB points in frustum (Ax + By + Cz + D >= 0)*/
1443 if (CHECK_IN_FRUSTUM_MIN(right) && CHECK_IN_FRUSTUM_MIN(left)
1444 && CHECK_IN_FRUSTUM_MIN(bottom) && CHECK_IN_FRUSTUM_MIN(top)
1445 && CHECK_IN_FRUSTUM_MIN(far) && CHECK_IN_FRUSTUM_MIN(near))
1446 frustum |= 1;
1447
1448 if (CHECK_IN_FRUSTUM_MAX(right) && CHECK_IN_FRUSTUM_MAX(left)
1449 && CHECK_IN_FRUSTUM_MAX(bottom) && CHECK_IN_FRUSTUM_MAX(top)
1450 && CHECK_IN_FRUSTUM_MAX(far) && CHECK_IN_FRUSTUM_MAX(near))
1451 frustum |= 2;
1452
1453#undef CHECK_IN_FRUSTUM_MIN
1454#undef CHECK_IN_FRUSTUM_MAX
1455
1456 return frustum;
1457} 1376}
1458 1377
1459
1460#include "canvas/evas_3d_node.eo.c" 1378#include "canvas/evas_3d_node.eo.c"
diff --git a/src/lib/evas/canvas/evas_3d_node.eo b/src/lib/evas/canvas/evas_3d_node.eo
index 5046f44..b82b90e 100644
--- a/src/lib/evas/canvas/evas_3d_node.eo
+++ b/src/lib/evas/canvas/evas_3d_node.eo
@@ -324,13 +324,12 @@ class Evas_3D_Node (Evas_3D_Object, Evas.Common_Interface)
324 324
325 bounding_box_get{ 325 bounding_box_get{
326 /* 326 /*
327 327 Get axis-aligned bounding box (AABB) of the given node.
328 * Get axis-aligned bounding box (AABB) of the given node.
329 * 328 *
330 * @param node The given node. 329 * @param node The given node.
331 * @param x Pointer to receive X coordinate of the first point of AABB. 330 * @param x Pointer to receive X coordinate of the first point of AABB.
332 * @param y Pointer to receive Y coordinate of the first point of AABB. 331 * @param y Pointer to receive Y coordinate of the first point of AABB.
333 * @param z Pointer to receive Z coordinate of the first point of AABB. 332 * @param z Pointer to receive Z coordinate of the first point of AABB.
334 * @param x2 Pointer to receive X coordinate of the second point of AABB. 333 * @param x2 Pointer to receive X coordinate of the second point of AABB.
335 * @param y2 Pointer to receive Y coordinate of the second point of AABB. 334 * @param y2 Pointer to receive Y coordinate of the second point of AABB.
336 * @param z2 Pointer to receive Z coordinate of the second point of AABB. 335 * @param z2 Pointer to receive Z coordinate of the second point of AABB.
@@ -347,23 +346,25 @@ class Evas_3D_Node (Evas_3D_Object, Evas.Common_Interface)
347 } 346 }
348 } 347 }
349 348
350 obb_frustum_check { 349 bounding_sphere_get {
351 /* 350 /*
352 351 Get bounding sphere of the given node.
353 * Check is the obb of node in frustum of camera node.
354 * 352 *
355 * @param camera_node The given node of camera. 353 * @param node The given node.
356 * @param node The given node.
357 * @return @c 0 if the obb is not in frustum, @c 1 if only min coordinate of obb is in frustum,
358 * @c 2 if only max coordinate of obb is in frustum, @c 3 if both coordinates of obb is in frustum.
359 354
360 * If the camera_node is not of type EVAS_3D_NODE_TYPE_CAMERA error wrong type of node will be generated and returned @ -1. 355 * @param x Pointer to receive X coordinate of the center of sphere.
356 * @param y Pointer to receive Y coordinate of the center of sphere.
357 * @param z Pointer to receive Z coordinate of center of sphere.
358 * @param r Pointer to receive radius of center of sphere.
361 359
362 * @ingroup Evas_3D_Node 360 @ingroup Evas_3D_Node
363 */ 361 */
364 return: int;
365 params { 362 params {
366 @in Evas_3D_Node *camera_node; 363
364 @in Evas_Real *x; /*@ Coordinates of vector.*/
365 @in Evas_Real *y;
366 @in Evas_Real *z;
367 @in Evas_Real *r;
367 } 368 }
368 } 369 }
369 } 370 }
diff --git a/src/lib/evas/include/evas_3d_utils.h b/src/lib/evas/include/evas_3d_utils.h
index 8e02a07..139351d 100644
--- a/src/lib/evas/include/evas_3d_utils.h
+++ b/src/lib/evas/include/evas_3d_utils.h
@@ -17,8 +17,10 @@ typedef struct _Evas_Mat3 Evas_Mat3;
17typedef struct _Evas_Mat4 Evas_Mat4; 17typedef struct _Evas_Mat4 Evas_Mat4;
18typedef struct _Evas_Box2 Evas_Box2; 18typedef struct _Evas_Box2 Evas_Box2;
19typedef struct _Evas_Box3 Evas_Box3; 19typedef struct _Evas_Box3 Evas_Box3;
20typedef struct _Evas_Line3 Evas_Line3;
20typedef struct _Evas_Triangle3 Evas_Triangle3; 21typedef struct _Evas_Triangle3 Evas_Triangle3;
21typedef struct _Evas_Ray3 Evas_Ray3; 22typedef struct _Evas_Ray3 Evas_Ray3;
23typedef struct _Evas_Sphere Evas_Sphere;
22 24
23struct _Evas_Color 25struct _Evas_Color
24{ 26{
@@ -79,6 +81,12 @@ struct _Evas_Box3
79 Evas_Vec3 p1; 81 Evas_Vec3 p1;
80}; 82};
81 83
84struct _Evas_Line3
85{
86 Evas_Vec3 point;
87 Evas_Vec3 direction;
88};
89
82struct _Evas_Triangle3 90struct _Evas_Triangle3
83{ 91{
84 Evas_Vec3 p0; 92 Evas_Vec3 p0;
@@ -92,6 +100,12 @@ struct _Evas_Ray3
92 Evas_Vec3 dir; 100 Evas_Vec3 dir;
93}; 101};
94 102
103struct _Evas_Sphere
104{
105 Evas_Vec3 center;
106 Evas_Real radius;
107};
108
95/* 2D vector */ 109/* 2D vector */
96static inline void 110static inline void
97evas_vec2_set(Evas_Vec2 *dst, Evas_Real x, Evas_Real y) 111evas_vec2_set(Evas_Vec2 *dst, Evas_Real x, Evas_Real y)
@@ -1594,6 +1608,17 @@ evas_box2_intersect_2d(const Evas_Box2 *box, const Evas_Vec2 *org, const Evas_Ve
1594 return EINA_TRUE; 1608 return EINA_TRUE;
1595} 1609}
1596 1610
1611static inline Evas_Real
1612evas_determinant_3D(Evas_Real matrix[3][3])
1613{
1614 return (matrix[0][0] * matrix[1][1] * matrix[2][2]) +
1615 (matrix[0][1] * matrix[1][2] * matrix[2][0]) +
1616 (matrix[0][2] * matrix[1][0] * matrix[2][1]) -
1617 (matrix[0][2] * matrix[1][1] * matrix[2][0]) -
1618 (matrix[0][1] * matrix[1][0] * matrix[2][2]) -
1619 (matrix[0][0] * matrix[1][2] * matrix[2][1]);
1620}
1621
1597static inline Eina_Bool 1622static inline Eina_Bool
1598evas_box3_ray3_intersect(const Evas_Box3 *box, const Evas_Ray3 *ray) 1623evas_box3_ray3_intersect(const Evas_Box3 *box, const Evas_Ray3 *ray)
1599{ 1624{
@@ -1722,3 +1747,242 @@ evas_reciprocal_sqrt(Evas_Real x)
1722 u.i = 0x5f3759df - (u.i >> 1); 1747 u.i = 0x5f3759df - (u.i >> 1);
1723 return u.f * (1.5f - u.f * u.f * x * 0.5f); 1748 return u.f * (1.5f - u.f * u.f * x * 0.5f);
1724} 1749}
1750
1751static inline void
1752evas_build_sphere(const Evas_Box3 *box, Evas_Sphere *sphere)
1753{
1754 Evas_Vec3 tmp;
1755
1756 evas_vec3_set(&sphere->center, (0.5 * (box->p0.x + box->p1.x)), (0.5 * (box->p0.y + box->p1.y)), (0.5 * (box->p0.z + box->p1.z)));
1757 evas_vec3_set(&tmp, sphere->center.x - box->p0.x, sphere->center.y - box->p0.y, sphere->center.z - box->p0.z);
1758
1759 sphere->radius = sqrtf(evas_vec3_dot_product(&tmp, &tmp));
1760}
1761
1762static inline void
1763evas_plane_normalize(Evas_Vec4 *plane)
1764{
1765 Evas_Vec3 tmp;
1766 Evas_Real length;
1767 evas_vec3_set(&tmp, plane->x, plane->y, plane->z);
1768 length = evas_vec3_length_get(&tmp);
1769 plane->x = plane->x / length;
1770 plane->y = plane->y / length;
1771 plane->z = plane->z / length;
1772 plane->w = plane->w / length;
1773}
1774
1775static inline Eina_Bool
1776evas_intersection_line_of_two_planes(Evas_Line3 *line, Evas_Vec4 *plane1, Evas_Vec4 *plane2)
1777{
1778 //TODO:parallel case
1779 Evas_Vec3 planes3D[2];
1780
1781 evas_vec3_set(&planes3D[0], plane1->x, plane1->y, plane1->z);
1782 evas_vec3_set(&planes3D[1], plane2->x, plane2->y, plane2->z);
1783
1784 evas_vec3_cross_product(&line->direction, &planes3D[0], &planes3D[1]);
1785
1786#define SOLVE_EQUATION(x, y, z) \
1787 line->point.x = 0; \
1788 line->point.y = (plane2->w * plane1->z - plane1->w * plane2->z) / line->direction.x; \
1789 line->point.z = (plane2->y * plane1->w - plane1->y * plane2->w) / line->direction.x;
1790
1791 if (line->direction.x && plane1->z)
1792 {
1793 SOLVE_EQUATION(x, y, z)
1794 }
1795 else if (line->direction.y && plane1->x)
1796 {
1797 SOLVE_EQUATION(y, z, x)
1798 }
1799 else
1800 {
1801 SOLVE_EQUATION(z, x, y)
1802 }
1803#undef SOLVE_EQUATION
1804
1805 return EINA_TRUE;
1806}
1807
1808static inline Eina_Bool
1809evas_intersection_point_of_three_planes(Evas_Vec3 *point, Evas_Vec4 *plane1, Evas_Vec4 *plane2, Evas_Vec4 *plane3)
1810{
1811 //TODO:parallel case
1812 int i;
1813 Evas_Real delta, deltax, deltay, deltaz;
1814 Evas_Real matrix_to_det[3][3];
1815 Evas_Vec4 planes[3];
1816
1817 planes[0] = *plane1;
1818 planes[1] = *plane2;
1819 planes[2] = *plane3;
1820
1821 for (i = 0; i < 3; i++)
1822 {
1823 matrix_to_det[0][i] = planes[i].x;
1824 matrix_to_det[1][i] = planes[i].y;
1825 matrix_to_det[2][i] = planes[i].z;
1826 }
1827 delta = evas_determinant_3D(matrix_to_det);
1828
1829 for (i = 0; i < 3; i++)
1830 matrix_to_det[0][i] = planes[i].w;
1831 deltax = evas_determinant_3D(matrix_to_det);
1832
1833 for (i = 0; i < 3; i++)
1834 {
1835 matrix_to_det[0][i] = planes[i].x;
1836 matrix_to_det[1][i] = planes[i].w;
1837 }
1838 deltay = evas_determinant_3D(matrix_to_det);
1839
1840 for (i = 0; i < 3; i++)
1841 {
1842 matrix_to_det[1][i] = planes[i].y;
1843 matrix_to_det[2][i] = planes[i].w;
1844 }
1845 deltaz = evas_determinant_3D(matrix_to_det);
1846
1847 evas_vec3_set(point, -deltax/delta, -deltay/delta, -deltaz/delta);
1848
1849 return EINA_TRUE;
1850}
1851
1852static inline Evas_Real
1853evas_point_plane_distance(Evas_Vec3 *point, Evas_Vec4 *plane)
1854{
1855 return plane->x * point->x + plane->y * point->y + plane->z * point->z + plane->w;
1856}
1857
1858static inline Evas_Real
1859evas_point_line_distance(Evas_Vec3 *point, Evas_Line3 *line)
1860{
1861 Evas_Vec3 temp, sub;
1862
1863 evas_vec3_subtract(&sub, point, &line->point);
1864 evas_vec3_cross_product(&temp, &sub, &line->direction);
1865
1866 return evas_vec3_length_get(&temp) / evas_vec3_length_get(&line->direction);
1867}
1868
1869static inline Eina_Bool
1870evas_is_sphere_in_frustum(Evas_Sphere *bsphere, Evas_Vec4 *planes)
1871{
1872 int i;
1873 Evas_Line3 line;
1874 Evas_Vec3 point, sub;
1875 Evas_Real distances[6] = {0};
1876 int intersected_planes[3];
1877 int intersected_planes_count = 0;
1878
1879 for (i = 0; i < 6; i++)
1880 {
1881 distances[i] = evas_point_plane_distance(&bsphere->center, &planes[i]);
1882 }
1883
1884 for (i = 0; i < 6; i++)
1885 {
1886 if (distances[i] <= -bsphere->radius)
1887 {
1888 return EINA_FALSE;
1889 }
1890 else if (distances[i] <= 0)
1891 {
1892 intersected_planes[intersected_planes_count] = i;
1893 intersected_planes_count++;
1894 }
1895 }
1896
1897 if ((intersected_planes_count == 0) || (intersected_planes_count == 1))
1898 return EINA_TRUE;
1899 else if (intersected_planes_count == 2)
1900 {
1901 evas_intersection_line_of_two_planes(&line, &planes[intersected_planes[0]], &planes[intersected_planes[1]]);
1902 return (evas_point_line_distance(&bsphere->center, &line) < bsphere->radius) ? EINA_TRUE : EINA_FALSE;
1903 }
1904 else if (intersected_planes_count == 3)
1905 {
1906 evas_intersection_point_of_three_planes(&point, &planes[intersected_planes[0]], &planes[intersected_planes[1]], &planes[intersected_planes[2]]);
1907 evas_vec3_subtract(&sub, &point, &bsphere->center);
1908 return (evas_vec3_length_get(&sub) < bsphere->radius) ? EINA_TRUE : EINA_FALSE;
1909 }
1910
1911 return EINA_FALSE;
1912}
1913
1914static inline Eina_Bool
1915evas_is_point_in_frustum(Evas_Vec3 *point, Evas_Vec4 *planes)
1916{
1917 int i;
1918 for (i = 0; i < 6; i++)
1919 if (evas_point_plane_distance(point, &planes[i]) <= 0) return EINA_FALSE;
1920 return EINA_TRUE;
1921}
1922
1923static inline Eina_Bool
1924evas_is_box_in_frustum(Evas_Box3 *box, Evas_Vec4 *planes)
1925{
1926 int i;
1927 for (i = 0; i < 6; i++)
1928 {
1929 if (planes[i].x * box->p0.x + planes[i].y * box->p0.y + planes[i].z * box->p0.z + planes[i].w > 0)
1930 continue;
1931 if (planes[i].x * box->p1.x + planes[i].y * box->p0.y + planes[i].z * box->p0.z + planes[i].w > 0)
1932 continue;
1933 if (planes[i].x * box->p1.x + planes[i].y * box->p1.y + planes[i].z * box->p0.z + planes[i].w > 0)
1934 continue;
1935 if (planes[i].x * box->p0.x + planes[i].y * box->p1.y + planes[i].z * box->p0.z + planes[i].w > 0)
1936 continue;
1937 if (planes[i].x * box->p0.x + planes[i].y * box->p0.y + planes[i].z * box->p1.z + planes[i].w > 0)
1938 continue;
1939 if (planes[i].x * box->p1.x + planes[i].y * box->p0.y + planes[i].z * box->p1.z + planes[i].w > 0)
1940 continue;
1941 if (planes[i].x * box->p1.x + planes[i].y * box->p1.y + planes[i].z * box->p1.z + planes[i].w > 0)
1942 continue;
1943 if (planes[i].x * box->p0.x + planes[i].y * box->p1.y + planes[i].z * box->p1.z + planes[i].w > 0)
1944 continue;
1945 return EINA_FALSE;
1946 }
1947
1948 return EINA_TRUE;
1949}
1950
1951static inline void
1952evas_frustum_calculate(Evas_Vec4 *planes, Evas_Mat4 *matrix_vp)
1953{
1954 int i;
1955 evas_vec4_set(&planes[0], matrix_vp->m[3] - matrix_vp->m[0],
1956 matrix_vp->m[7] - matrix_vp->m[4],
1957 matrix_vp->m[11] - matrix_vp->m[8],
1958 matrix_vp->m[15] - matrix_vp->m[12]);
1959
1960 evas_vec4_set(&planes[1], matrix_vp->m[3] + matrix_vp->m[0],
1961 matrix_vp->m[7] + matrix_vp->m[4],
1962 matrix_vp->m[11] + matrix_vp->m[8],
1963 matrix_vp->m[15] + matrix_vp->m[12]);
1964
1965 evas_vec4_set(&planes[2], matrix_vp->m[3] + matrix_vp->m[1],
1966 matrix_vp->m[7] + matrix_vp->m[5],
1967 matrix_vp->m[11] + matrix_vp->m[9],
1968 matrix_vp->m[15] + matrix_vp->m[13]);
1969
1970 evas_vec4_set(&planes[3], matrix_vp->m[3] - matrix_vp->m[1],
1971 matrix_vp->m[7] - matrix_vp->m[5],
1972 matrix_vp->m[11] - matrix_vp->m[9],
1973 matrix_vp->m[15] - matrix_vp->m[13]);
1974
1975 evas_vec4_set(&planes[4], matrix_vp->m[3] - matrix_vp->m[2],
1976 matrix_vp->m[7] - matrix_vp->m[6],
1977 matrix_vp->m[11] - matrix_vp->m[10],
1978 matrix_vp->m[15] - matrix_vp->m[14]);
1979
1980 evas_vec4_set(&planes[5], matrix_vp->m[3] + matrix_vp->m[2],
1981 matrix_vp->m[7] + matrix_vp->m[6],
1982 matrix_vp->m[11] + matrix_vp->m[10],
1983 matrix_vp->m[15] + matrix_vp->m[14]);
1984 for (i = 0; i < 6; i++)
1985 {
1986 evas_plane_normalize(&planes[i]);
1987 }
1988}
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index 50f9fa5..6cf5c06 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -219,6 +219,7 @@ struct _Evas_3D_Node
219 219
220 Evas_Box3 aabb; 220 Evas_Box3 aabb;
221 Evas_Box3 obb; 221 Evas_Box3 obb;
222 Evas_Sphere bsphere;
222 223
223 Evas_3D_Node_Type type; 224 Evas_3D_Node_Type type;
224 225