/src/lib/evas/canvas/evas_3d_node.c

https://bitbucket.org/hchbaw/efl · C · 1460 lines · 1158 code · 218 blank · 84 comment · 269 complexity · ddf4c19d7b3c4f1a790b8a4d1f600b67 MD5 · raw file

  1. #include "evas_common_private.h"
  2. #include "evas_private.h"
  3. #define MY_CLASS EVAS_3D_NODE_CLASS
  4. #define MY_CLASS_NAME "Evas_3D_Node"
  5. Evas_3D_Mesh_Frame *evas_3d_mesh_frame_find(Evas_3D_Mesh_Data *pd, int frame);
  6. static inline Evas_3D_Node_Mesh *
  7. _node_mesh_new(Evas_3D_Node *node, Evas_3D_Mesh *mesh)
  8. {
  9. Evas_3D_Node_Mesh *nm = (Evas_3D_Node_Mesh *)malloc(sizeof(Evas_3D_Node_Mesh));
  10. if (nm == NULL)
  11. {
  12. ERR("Failed to allocate memory.");
  13. return NULL;
  14. }
  15. nm->node = node;
  16. nm->mesh = mesh;
  17. nm->frame = 0;
  18. return nm;
  19. }
  20. static inline void
  21. _node_mesh_free(Evas_3D_Node_Mesh *nm)
  22. {
  23. free(nm);
  24. }
  25. static void
  26. _node_mesh_free_func(void *data)
  27. {
  28. _node_mesh_free((Evas_3D_Node_Mesh *)data);
  29. }
  30. static Eina_Bool
  31. _node_scene_root_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
  32. void *data EINA_UNUSED, void *fdata)
  33. {
  34. Evas_3D_Scene *s = *(Evas_3D_Scene **)key;
  35. eo_do(s, evas_3d_object_change(EVAS_3D_STATE_SCENE_ROOT_NODE, (Evas_3D_Object *)fdata));
  36. return EINA_TRUE;
  37. }
  38. static Eina_Bool
  39. _node_scene_camera_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
  40. void *data EINA_UNUSED, void *fdata)
  41. {
  42. Evas_3D_Scene *s = *(Evas_3D_Scene **)key;
  43. eo_do(s, evas_3d_object_change(EVAS_3D_STATE_SCENE_CAMERA_NODE, (Evas_3D_Object *)fdata));
  44. return EINA_TRUE;
  45. }
  46. EOLIAN static void
  47. _evas_3d_node_evas_3d_object_change_notify(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_State state EINA_UNUSED , Evas_3D_Object *ref EINA_UNUSED)
  48. {
  49. Eina_List *l;
  50. Evas_3D_Node *n;
  51. /* Notify all scenes using this node that it has changed. */
  52. if (pd->scenes_root)
  53. eina_hash_foreach(pd->scenes_root, _node_scene_root_change_notify, obj);
  54. if (pd->scenes_camera)
  55. eina_hash_foreach(pd->scenes_camera, _node_scene_camera_change_notify, obj);
  56. /* Notify parent that a member has changed. */
  57. if (pd->parent)
  58. {
  59. eo_do(pd->parent, evas_3d_object_change(EVAS_3D_STATE_NODE_MEMBER, obj));
  60. }
  61. /* Notify members that the parent has changed. */
  62. EINA_LIST_FOREACH(pd->members, l, n)
  63. {
  64. eo_do(n, evas_3d_object_change(EVAS_3D_STATE_NODE_PARENT, obj));
  65. }
  66. }
  67. static Eina_Bool
  68. _node_transform_update(Evas_3D_Node *node, void *data EINA_UNUSED)
  69. {
  70. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  71. Eina_Bool transform_dirty = EINA_FALSE, parent_dirty = EINA_FALSE;
  72. eo_do(node,
  73. transform_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM),
  74. parent_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_PARENT));
  75. if (transform_dirty || parent_dirty)
  76. {
  77. if (pd->parent)
  78. {
  79. Evas_3D_Node_Data *pdparent = eo_data_scope_get(pd->parent, MY_CLASS);
  80. const Evas_Vec3 *scale_parent = &pdparent->scale_world;
  81. const Evas_Vec4 *orientation_parent = &pdparent->orientation_world;
  82. /* Orienatation */
  83. if (pd->orientation_inherit)
  84. {
  85. evas_vec4_quaternion_multiply(&pd->orientation_world,
  86. orientation_parent, &pd->orientation);
  87. }
  88. else
  89. {
  90. pd->orientation_world = pd->orientation;
  91. }
  92. /* Scale */
  93. if (pd->scale_inherit)
  94. evas_vec3_multiply(&pd->scale_world, scale_parent, &pd->scale);
  95. else
  96. pd->scale_world = pd->scale;
  97. /* Position */
  98. if (pd->position_inherit)
  99. {
  100. evas_vec3_multiply(&pd->position_world, &pd->position, scale_parent);
  101. evas_vec3_quaternion_rotate(&pd->position_world, &pd->position_world,
  102. orientation_parent);
  103. evas_vec3_add(&pd->position_world, &pd->position_world,
  104. &pdparent->position_world);
  105. }
  106. else
  107. {
  108. pd->position_world = pd->position;
  109. }
  110. }
  111. else
  112. {
  113. pd->position_world = pd->position;
  114. pd->orientation_world = pd->orientation;
  115. pd->scale_world = pd->scale;
  116. }
  117. if (pd->type == EVAS_3D_NODE_TYPE_CAMERA)
  118. {
  119. evas_mat4_inverse_build(&pd->data.camera.matrix_world_to_eye,
  120. &pd->position_world, &pd->orientation_world,
  121. &pd->scale_world);
  122. }
  123. else if (pd->type == EVAS_3D_NODE_TYPE_LIGHT)
  124. {
  125. }
  126. else if (pd->type == EVAS_3D_NODE_TYPE_MESH)
  127. {
  128. evas_mat4_build(&pd->data.mesh.matrix_local_to_world,
  129. &pd->position_world, &pd->orientation_world, &pd->scale_world);
  130. }
  131. /*
  132. if (pd->parent)
  133. {
  134. evas_mat4_nocheck_multiply(&pd->matrix_local_to_world,
  135. &pd->parent->matrix_local_to_world,
  136. &pd->matrix_local_to_parent);
  137. }
  138. else
  139. {
  140. evas_mat4_copy(&pd->matrix_local_to_world, &pd->matrix_local_to_parent);
  141. }*/
  142. }
  143. return EINA_TRUE;
  144. }
  145. static Eina_Bool
  146. _node_item_update(Evas_3D_Node *node, void *data EINA_UNUSED)
  147. {
  148. Evas_3D_Node_Data *pd = eo_data_scope_get(node, EVAS_3D_NODE_CLASS);
  149. if (pd->type == EVAS_3D_NODE_TYPE_CAMERA)
  150. {
  151. if (pd->data.camera.camera)
  152. {
  153. eo_do(pd->data.camera.camera, evas_3d_object_update());
  154. }
  155. }
  156. else if (pd->type == EVAS_3D_NODE_TYPE_LIGHT)
  157. {
  158. if (pd->data.light.light)
  159. {
  160. eo_do(pd->data.light.light, evas_3d_object_update());
  161. }
  162. }
  163. else if (pd->type == EVAS_3D_NODE_TYPE_MESH)
  164. {
  165. Eina_List *l;
  166. Evas_3D_Mesh *m;
  167. EINA_LIST_FOREACH(pd->data.mesh.meshes, l, m)
  168. {
  169. eo_do(m, evas_3d_object_update());
  170. }
  171. }
  172. return EINA_TRUE;
  173. }
  174. static Eina_Bool
  175. _node_aabb_update(Evas_3D_Node *node, void *data EINA_UNUSED)
  176. {
  177. Evas_3D_Node_Data *pd = eo_data_scope_get(node, EVAS_3D_NODE_CLASS);
  178. Eina_Bool transform_dirty = EINA_FALSE, mesh_geom_dirty = EINA_FALSE;
  179. Eina_Bool mesh_frame_dirty = EINA_FALSE, member_dirty = EINA_FALSE;
  180. Eina_Bool frame_found = EINA_FALSE, is_change_orientation = EINA_FALSE;
  181. const Eina_List *m, *l;
  182. Evas_3D_Mesh *mesh;
  183. int frame, count, size, i, j;
  184. Evas_3D_Mesh_Frame *f;
  185. float minx, miny, minz, maxx, maxy, maxz, vxmin, vymin, vzmin, vxmax, vymax, vzmax;
  186. float *minmaxdata;
  187. Evas_Vec4 orientation = {0};
  188. Evas_Box3 box3;
  189. eo_do(node,
  190. transform_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_TRANSFORM),
  191. mesh_geom_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_GEOMETRY),
  192. mesh_frame_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MESH_FRAME),
  193. member_dirty = evas_3d_object_dirty_get(EVAS_3D_STATE_NODE_MEMBER));
  194. if (transform_dirty ||
  195. mesh_geom_dirty ||
  196. mesh_frame_dirty ||
  197. member_dirty)
  198. {
  199. if (pd->type == EVAS_3D_NODE_TYPE_MESH)
  200. {
  201. if (pd->orientation.x || pd->orientation.y || pd->orientation.z)
  202. {
  203. evas_vec4_set(&orientation, pd->orientation.x, pd->orientation.y, pd->orientation.z, pd->orientation.w);
  204. is_change_orientation = EINA_TRUE;
  205. }
  206. eo_do (node, m = (Eina_List *)evas_3d_node_mesh_list_get());
  207. EINA_LIST_FOREACH(m, l, mesh)
  208. {
  209. eo_do(node, frame = evas_3d_node_mesh_frame_get(mesh));
  210. Evas_3D_Mesh_Data *mpd = eo_data_scope_get(mesh, EVAS_3D_MESH_CLASS);
  211. f = evas_3d_mesh_frame_find(mpd, frame);
  212. if (f)
  213. {
  214. i = 0, j = 0;
  215. evas_box3_empty_set(&box3);
  216. count = f->vertices[EVAS_3D_VERTEX_POSITION].element_count;
  217. size = f->vertices[EVAS_3D_VERTEX_POSITION].size;
  218. if (!size) size = count * sizeof(float) * mpd->vertex_count;
  219. minmaxdata = (float *)malloc(size);
  220. if (!minmaxdata)
  221. {
  222. ERR("Not enough memory.");
  223. return EINA_FALSE;
  224. }
  225. memcpy(minmaxdata, f->vertices[EVAS_3D_VERTEX_POSITION].data, size);
  226. /*get current coordinates, set orientation and find min/max*/
  227. if (is_change_orientation)
  228. {
  229. Evas_Vec3 rotate;
  230. evas_vec3_set(&rotate, minmaxdata[0], minmaxdata[1], minmaxdata[2]);
  231. evas_vec3_quaternion_rotate(&rotate, &rotate, &orientation);
  232. vxmax = vxmin = minmaxdata[0] = rotate.x;
  233. vymax = vymin = minmaxdata[1] = rotate.y;
  234. vzmax = vzmin = minmaxdata[2] = rotate.z;
  235. }
  236. else
  237. {
  238. vxmax = vxmin = minmaxdata[0];
  239. vymax = vymin = minmaxdata[1];
  240. vzmax = vzmin = minmaxdata[2];
  241. }
  242. j += count;
  243. if (is_change_orientation)
  244. {
  245. for (i = 1; i < mpd->vertex_count; ++i)
  246. {
  247. Evas_Vec3 rotate;
  248. evas_vec3_set(&rotate, minmaxdata[j], minmaxdata[j + 1], minmaxdata[j + 2]);
  249. evas_vec3_quaternion_rotate(&rotate, &rotate, &orientation);
  250. minmaxdata[j] = rotate.x;
  251. minmaxdata[j + 1] = rotate.y;
  252. minmaxdata[j + 2] = rotate.z;
  253. vxmin > minmaxdata[j] ? vxmin = minmaxdata[j] : 0;
  254. vxmax < minmaxdata[j] ? vxmax = minmaxdata[j] : 0;
  255. vymin > minmaxdata[j + 1] ? vymin = minmaxdata[j + 1] : 0;
  256. vymax < minmaxdata[j + 1] ? vymax = minmaxdata[j + 1] : 0;
  257. vzmin > minmaxdata[j + 2] ? vzmin = minmaxdata[j + 2] : 0;
  258. vzmax < minmaxdata[j + 2] ? vzmax = minmaxdata[j + 2] : 0;
  259. j += count;
  260. }
  261. }
  262. else
  263. {
  264. for (i = 1; i < mpd->vertex_count; ++i)
  265. {
  266. vxmin > minmaxdata[j] ? vxmin = minmaxdata[j] : 0;
  267. vxmax < minmaxdata[j] ? vxmax = minmaxdata[j] : 0;
  268. vymin > minmaxdata[j + 1] ? vymin = minmaxdata[j + 1] : 0;
  269. vymax < minmaxdata[j + 1] ? vymax = minmaxdata[j + 1] : 0;
  270. vzmin > minmaxdata[j + 2] ? vzmin = minmaxdata[j + 2] : 0;
  271. vzmax < minmaxdata[j + 2] ? vzmax = minmaxdata[j + 2] : 0;
  272. j += count;
  273. }
  274. }
  275. if (!frame_found)
  276. {
  277. evas_box3_empty_set(&pd->aabb);
  278. evas_box3_empty_set(&pd->obb);
  279. minx = vxmin;
  280. miny = vymin;
  281. minz = vzmin;
  282. maxx = vxmax;
  283. maxy = vymax;
  284. maxz = vzmax;
  285. }
  286. else
  287. {
  288. minx > vxmin ? minx = vxmin : 0;
  289. maxx < vxmax ? maxx = vxmax : 0;
  290. miny > vymin ? miny = vymin : 0;
  291. maxy < vymax ? maxy = vymax : 0;
  292. minz > vzmin ? minz = vzmin : 0;
  293. maxz < vzmax ? maxz = vzmax : 0;
  294. }
  295. frame_found = EINA_TRUE;
  296. free(minmaxdata);
  297. evas_box3_set(&box3, minx, miny, minz, maxx, maxy, maxz);
  298. evas_box3_union(&pd->aabb, &pd->aabb, &box3);
  299. evas_box3_union(&pd->obb, &pd->obb, &f->aabb);
  300. }
  301. }
  302. if (frame_found)
  303. {
  304. if (is_change_orientation)
  305. {
  306. evas_vec3_quaternion_rotate(&pd->obb.p0, &pd->obb.p0, &orientation);
  307. evas_vec3_quaternion_rotate(&pd->obb.p1, &pd->obb.p1, &orientation);
  308. }
  309. if ((pd->scale.x != 1 || pd->scale.y != 1 || pd->scale.z != 1))
  310. {
  311. Evas_Vec3 scale;
  312. evas_vec3_set(&scale, pd->scale.x, pd->scale.y, pd->scale.z);
  313. evas_vec3_multiply(&pd->obb.p0, &scale, &pd->obb.p0);
  314. evas_vec3_multiply(&pd->obb.p1, &scale, &pd->obb.p1);
  315. evas_vec3_multiply(&pd->aabb.p0, &scale, &pd->aabb.p0);
  316. evas_vec3_multiply(&pd->aabb.p1, &scale, &pd->aabb.p1);
  317. }
  318. if ((pd->position.x || pd->position.y || pd->position.z))
  319. {
  320. Evas_Vec3 position;
  321. evas_vec3_set(&position, pd->position.x, pd->position.y, pd->position.z);
  322. evas_vec3_add(&pd->obb.p0, &position, &pd->obb.p0);
  323. evas_vec3_add(&pd->obb.p1, &position, &pd->obb.p1);
  324. evas_vec3_add(&pd->aabb.p0, &position, &pd->aabb.p0);
  325. evas_vec3_add(&pd->aabb.p1, &position, &pd->aabb.p1);
  326. }
  327. }
  328. }
  329. else
  330. {
  331. Eina_List *current;
  332. Evas_3D_Node *datanode;
  333. /* Update AABB and OBB of this node. */
  334. evas_box3_empty_set(&pd->aabb);
  335. evas_box3_empty_set(&pd->obb);
  336. EINA_LIST_FOREACH(pd->members, current, datanode)
  337. {
  338. Evas_3D_Node_Data *datapd = eo_data_scope_get(datanode, EVAS_3D_NODE_CLASS);
  339. evas_box3_union(&pd->obb, &pd->obb, &datapd->obb);
  340. evas_box3_union(&pd->aabb, &pd->aabb, &datapd->aabb);
  341. }
  342. }
  343. }
  344. return EINA_TRUE;
  345. }
  346. static Eina_Bool
  347. _node_update_done(Evas_3D_Node *obj, void *data EINA_UNUSED)
  348. {
  349. //@FIXME
  350. Evas_3D_Object_Data *pdobject = eo_data_scope_get(obj, EVAS_3D_OBJECT_CLASS);
  351. memset(&pdobject->dirty[0], 0x00, sizeof(Eina_Bool) * EVAS_3D_STATE_MAX);
  352. return EINA_TRUE;
  353. }
  354. EOLIAN static void
  355. _evas_3d_node_evas_3d_object_update_notify(Eo *obj, Evas_3D_Node_Data *pd EINA_UNUSED)
  356. {
  357. /* Update transform. */
  358. evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER, EINA_FALSE,
  359. _node_transform_update, NULL);
  360. /* Update AABB. */
  361. evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_POST_ORDER, EINA_FALSE,
  362. _node_aabb_update, NULL);
  363. /* Update node item. */
  364. evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_ANY_ORDER, EINA_FALSE,
  365. _node_item_update, NULL);
  366. /* Mark all nodes in the tree as up-to-date. */
  367. evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_ANY_ORDER, EINA_FALSE,
  368. _node_update_done, NULL);
  369. }
  370. static void
  371. _node_free(Evas_3D_Object *obj)
  372. {
  373. Evas_3D_Node_Data *pd = eo_data_scope_get(obj, MY_CLASS);
  374. if (pd->members)
  375. {
  376. Eina_List *l;
  377. Evas_3D_Node *n;
  378. EINA_LIST_FOREACH(pd->members, l, n)
  379. {
  380. eo_unref(n);
  381. }
  382. eina_list_free(pd->members);
  383. }
  384. if (pd->data.mesh.meshes)
  385. {
  386. Eina_List *l;
  387. Evas_3D_Mesh *m;
  388. EINA_LIST_FOREACH(pd->data.mesh.meshes, l, m)
  389. {
  390. //evas_3d_mesh_node_del(m, node);
  391. eo_unref(m);
  392. }
  393. eina_list_free(pd->data.mesh.meshes);
  394. }
  395. if (pd->data.mesh.node_meshes)
  396. eina_hash_free(pd->data.mesh.node_meshes);
  397. if (pd->scenes_root)
  398. eina_hash_free(pd->scenes_root);
  399. if (pd->scenes_camera)
  400. eina_hash_free(pd->scenes_camera);
  401. //free(node);
  402. }
  403. void
  404. evas_3d_node_scene_root_add(Evas_3D_Node *node, Evas_3D_Scene *scene)
  405. {
  406. int count = 0;
  407. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  408. if (pd->scenes_root == NULL)
  409. {
  410. pd->scenes_root = eina_hash_pointer_new(NULL);
  411. if (pd->scenes_root == NULL)
  412. {
  413. ERR("Failed to create hash table.");
  414. return;
  415. }
  416. }
  417. else
  418. count = (int)(uintptr_t)eina_hash_find(pd->scenes_root, &scene);
  419. eina_hash_set(pd->scenes_root, &scene, (const void *)(uintptr_t)(count + 1));
  420. }
  421. void
  422. evas_3d_node_scene_root_del(Evas_3D_Node *node, Evas_3D_Scene *scene)
  423. {
  424. int count = 0;
  425. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  426. if (pd->scenes_root == NULL)
  427. {
  428. ERR("No scene to delete.");
  429. return;
  430. }
  431. count = (int)(uintptr_t)eina_hash_find(pd->scenes_root, &scene);
  432. if (count == 1)
  433. eina_hash_del(pd->scenes_root, &scene, NULL);
  434. else
  435. eina_hash_set(pd->scenes_root, &scene, (const void *)(uintptr_t)(count - 1));
  436. }
  437. void
  438. evas_3d_node_scene_camera_add(Evas_3D_Node *node, Evas_3D_Scene *scene)
  439. {
  440. int count = 0;
  441. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  442. if (pd->scenes_camera == NULL)
  443. {
  444. pd->scenes_camera = eina_hash_pointer_new(NULL);
  445. if (pd->scenes_camera == NULL)
  446. {
  447. ERR("Failed to create hash table.");
  448. return;
  449. }
  450. }
  451. else
  452. count = (int)(uintptr_t)eina_hash_find(pd->scenes_camera, &scene);
  453. eina_hash_set(pd->scenes_camera, &scene, (const void *)(uintptr_t)(count + 1));
  454. }
  455. void
  456. evas_3d_node_scene_camera_del(Evas_3D_Node *node, Evas_3D_Scene *scene)
  457. {
  458. int count = 0;
  459. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  460. if (pd->scenes_camera == NULL)
  461. {
  462. ERR("No scene to delete.");
  463. return;
  464. }
  465. count = (int)(uintptr_t)eina_hash_find(pd->scenes_camera, &scene);
  466. if (count == 1)
  467. eina_hash_del(pd->scenes_camera, &scene, NULL);
  468. else
  469. eina_hash_set(pd->scenes_camera, &scene, (const void *)(uintptr_t)(count - 1));
  470. }
  471. void
  472. evas_3d_node_traverse(Evas_3D_Node *from, Evas_3D_Node *to, Evas_3D_Node_Traverse_Type type,
  473. Eina_Bool skip, Evas_3D_Node_Func func, void *data)
  474. {
  475. Eina_List *nodes = NULL, *n;
  476. Evas_3D_Node *node = NULL;
  477. if (from == NULL || func == NULL)
  478. goto error;
  479. if (type == EVAS_3D_NODE_TRAVERSE_DOWNWARD)
  480. {
  481. if (to == NULL)
  482. goto error;
  483. node = to;
  484. do {
  485. nodes = eina_list_prepend(nodes, (const void *)node);
  486. if (node == from)
  487. break;
  488. Evas_3D_Node_Data *pdnode = eo_data_scope_get(node, MY_CLASS);
  489. node = pdnode->parent;
  490. if (node == NULL)
  491. goto error;
  492. } while (1);
  493. }
  494. else if (type == EVAS_3D_NODE_TRAVERSE_UPWARD)
  495. {
  496. node = from;
  497. do {
  498. nodes = eina_list_append(nodes, (const void *)node);
  499. if (node == to)
  500. break;
  501. Evas_3D_Node_Data *pdnode = eo_data_scope_get(node, MY_CLASS);
  502. node = pdnode->parent;
  503. if (node == NULL)
  504. {
  505. if (to == NULL)
  506. break;
  507. goto error;
  508. }
  509. } while (1);
  510. }
  511. EINA_LIST_FOREACH(nodes, n, node)
  512. {
  513. if (!func(node, data) && skip)
  514. break;
  515. }
  516. eina_list_free(nodes);
  517. return;
  518. error:
  519. ERR("Node traverse error.");
  520. if (nodes)
  521. eina_list_free(nodes);
  522. }
  523. void
  524. evas_3d_node_tree_traverse(Evas_3D_Node *root, Evas_3D_Tree_Traverse_Type type,
  525. Eina_Bool skip, Evas_3D_Node_Func func, void *data)
  526. {
  527. Eina_List *nodes = NULL, *l;
  528. Evas_3D_Node *node = NULL, *n, *last;
  529. if (root == NULL || func == NULL)
  530. return;
  531. if (type == EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER)
  532. {
  533. /* Put the root node in the queue. */
  534. nodes = eina_list_append(nodes, root);
  535. while (eina_list_count(nodes) > 0)
  536. {
  537. /* Dequeue a node. */
  538. node = eina_list_data_get(nodes);
  539. Evas_3D_Node_Data *pdnode = eo_data_scope_get(node, MY_CLASS);
  540. nodes = eina_list_remove_list(nodes, nodes);
  541. /* Call node function on the node. */
  542. if (func(node, data) || !skip)
  543. {
  544. /* Enqueue member nodes. */
  545. EINA_LIST_FOREACH(pdnode->members, l, n)
  546. {
  547. nodes = eina_list_append(nodes, n);
  548. }
  549. }
  550. }
  551. }
  552. else if (type == EVAS_3D_TREE_TRAVERSE_PRE_ORDER)
  553. {
  554. /* Put the root node in the stack. */
  555. nodes = eina_list_append(nodes, root);
  556. while (eina_list_count(nodes) > 0)
  557. {
  558. /* Pop a node from the stack. */
  559. node = eina_list_data_get(nodes);
  560. Evas_3D_Node_Data *pdnode = eo_data_scope_get(node, MY_CLASS);
  561. nodes = eina_list_remove_list(nodes, nodes);
  562. /* Call node function on the node. */
  563. if (func(node, data) || !skip)
  564. {
  565. /* Push member nodes into the stack. */
  566. EINA_LIST_REVERSE_FOREACH(pdnode->members, l, n)
  567. {
  568. nodes = eina_list_prepend(nodes, n);
  569. }
  570. }
  571. }
  572. }
  573. else if (type == EVAS_3D_TREE_TRAVERSE_POST_ORDER)
  574. {
  575. if (skip)
  576. {
  577. ERR("Using skip with post order traversal has no effect.");
  578. return;
  579. }
  580. /* Put the root node in the stack. */
  581. nodes = eina_list_append(nodes, root);
  582. last = NULL;
  583. while (eina_list_count(nodes) > 0)
  584. {
  585. /* Peek a node from the stack. */
  586. node = eina_list_data_get(nodes);
  587. Evas_3D_Node_Data *pdnode = eo_data_scope_get(node, MY_CLASS);
  588. if (eina_list_count(pdnode->members) == 0)
  589. {
  590. /* The peeked node is a leaf node,
  591. * so visit it and pop from the stack. */
  592. func(node, data);
  593. nodes = eina_list_remove_list(nodes, nodes);
  594. /* Save the last visited node. */
  595. last = node;
  596. }
  597. else
  598. {
  599. /* If the peeked node is not a leaf node,
  600. * there can be only two possible cases.
  601. *
  602. * 1. the parent of the last visited node.
  603. * 2. a sibling of the last visited node.
  604. *
  605. * If the last visited node is a direct child of the peeked node,
  606. * we have no unvisted child nodes for the peeked node, so we have to visit
  607. * the peeked node and pop from the stack.
  608. *
  609. * Otherwise it should be a sibling of the peeked node, so we have to push
  610. * its childs into the stack. */
  611. Evas_3D_Node_Data *pdlast;
  612. if (last )
  613. pdlast= eo_data_scope_get(last, MY_CLASS);
  614. if (last && pdlast->parent == node)
  615. {
  616. /* Visit the node as it doesn't have any unvisited child node. */
  617. func(node, data);
  618. nodes = eina_list_remove_list(nodes, nodes);
  619. /* Save the last visited node. */
  620. last = node;
  621. }
  622. else
  623. {
  624. /* Push child nodes into the stack. */
  625. EINA_LIST_REVERSE_FOREACH(pdnode->members, l, n)
  626. {
  627. nodes = eina_list_prepend(nodes, n);
  628. }
  629. }
  630. }
  631. }
  632. }
  633. if (nodes != NULL)
  634. eina_list_free(nodes);
  635. }
  636. Eina_Bool
  637. _node_is_visible(Evas_3D_Node *node EINA_UNUSED, Evas_3D_Node *camera_node EINA_UNUSED)
  638. {
  639. /* TODO: */
  640. return EINA_TRUE;
  641. }
  642. Eina_Bool
  643. evas_3d_node_mesh_collect(Evas_3D_Node *node, void *data)
  644. {
  645. Evas_3D_Scene_Public_Data *scene_data = (Evas_3D_Scene_Public_Data *)data;
  646. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  647. if (!_node_is_visible(node, scene_data->camera_node))
  648. {
  649. /* Skip entire sub-tree of this node. */
  650. return EINA_FALSE;
  651. }
  652. if (pd->type == EVAS_3D_NODE_TYPE_MESH)
  653. scene_data->mesh_nodes = eina_list_append(scene_data->mesh_nodes, node);
  654. return EINA_TRUE;
  655. }
  656. Eina_Bool
  657. evas_3d_node_light_collect(Evas_3D_Node *node, void *data)
  658. {
  659. Evas_3D_Scene_Public_Data *scene_data = (Evas_3D_Scene_Public_Data *)data;
  660. Evas_3D_Node_Data *pd = eo_data_scope_get(node, MY_CLASS);
  661. if (pd->type == EVAS_3D_NODE_TYPE_LIGHT)
  662. scene_data->light_nodes = eina_list_append(scene_data->light_nodes, node);
  663. return EINA_TRUE;
  664. }
  665. EAPI Evas_3D_Node *
  666. evas_3d_node_add(Evas *e, Evas_3D_Node_Type type)
  667. {
  668. MAGIC_CHECK(e, Evas, MAGIC_EVAS);
  669. return NULL;
  670. MAGIC_CHECK_END();
  671. Evas_Object *eo_obj = eo_add(MY_CLASS, e, evas_3d_node_constructor(type));
  672. return eo_obj;
  673. }
  674. EOLIAN static void
  675. _evas_3d_node_constructor(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Node_Type type)
  676. {
  677. eo_do(obj, evas_3d_object_type_set(EVAS_3D_OBJECT_TYPE_NODE));
  678. evas_vec3_set(&pd->position, 0.0, 0.0, 0.0);
  679. evas_vec4_set(&pd->orientation, 0.0, 0.0, 0.0, 1.0);
  680. evas_vec3_set(&pd->scale, 1.0, 1.0, 1.0);
  681. evas_vec3_set(&pd->position_world, 0.0, 0.0, 0.0);
  682. evas_vec4_set(&pd->orientation_world, 0.0, 0.0, 0.0, 1.0);
  683. evas_vec3_set(&pd->scale_world, 1.0, 1.0, 1.0);
  684. pd->position_inherit = EINA_TRUE;
  685. pd->orientation_inherit = EINA_TRUE;
  686. pd->scale_inherit = EINA_TRUE;
  687. pd->data.mesh.node_meshes = 0;
  688. evas_box3_set(&pd->aabb, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
  689. pd->type = type;
  690. if (type == EVAS_3D_NODE_TYPE_MESH)
  691. {
  692. pd->data.mesh.node_meshes = eina_hash_pointer_new(_node_mesh_free_func);
  693. if (pd->data.mesh.node_meshes == NULL)
  694. {
  695. ERR("Failed to create node mesh table.");
  696. _node_free(obj);
  697. }
  698. }
  699. }
  700. EOLIAN static Evas_3D_Node_Type
  701. _evas_3d_node_type_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  702. {
  703. return pd->type;
  704. }
  705. EOLIAN static void
  706. _evas_3d_node_member_add(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Node *member)
  707. {
  708. if (obj == member)
  709. {
  710. ERR("Failed to add a member node (adding to itself).");
  711. return;
  712. }
  713. Evas_3D_Node_Data *pdmember = eo_data_scope_get(member, MY_CLASS);
  714. if (pdmember->parent == obj)
  715. return;
  716. if (pdmember->parent)
  717. {
  718. /* Detaching from previous parent. */
  719. Evas_3D_Node_Data *pdmemberparent = eo_data_scope_get(pdmember->parent, MY_CLASS);
  720. pdmemberparent->members = eina_list_remove(pdmemberparent->members, member);
  721. /* Mark changed. */
  722. eo_do(pdmember->parent, evas_3d_object_change(EVAS_3D_STATE_NODE_MEMBER, NULL));
  723. }
  724. else
  725. {
  726. /* Should get a new reference. */
  727. eo_ref(member);
  728. }
  729. /* Add the member node. */
  730. pd->members = eina_list_append(pd->members, (const void *)member);
  731. pdmember->parent = obj;
  732. /* Mark changed. */
  733. eo_do(member, evas_3d_object_change(EVAS_3D_STATE_NODE_PARENT, NULL));
  734. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MEMBER, NULL));
  735. }
  736. EOLIAN static void
  737. _evas_3d_node_member_del(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Node *member)
  738. {
  739. Evas_3D_Node_Data *pdmember = eo_data_scope_get(member, MY_CLASS);
  740. if (pdmember->parent != obj)
  741. {
  742. ERR("Failed to delete a member node (not a member of the given node)");
  743. return;
  744. }
  745. /* Delete the member node. */
  746. pd->members = eina_list_remove(pd->members, member);
  747. pdmember->parent = NULL;
  748. /* Mark modified object as changed. */
  749. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MEMBER, NULL));
  750. eo_do(member, evas_3d_object_change(EVAS_3D_STATE_NODE_PARENT, NULL));
  751. /* Decrease reference count. */
  752. eo_unref(member);
  753. }
  754. EOLIAN static Evas_3D_Node *
  755. _evas_3d_node_parent_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  756. {
  757. return pd->parent;
  758. }
  759. EOLIAN static const Eina_List *
  760. _evas_3d_node_member_list_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  761. {
  762. return pd->members;
  763. }
  764. EOLIAN static void
  765. _evas_3d_node_position_set(Eo *obj, Evas_3D_Node_Data *pd, Evas_Real x, Evas_Real y, Evas_Real z)
  766. {
  767. pd->position.x = x;
  768. pd->position.y = y;
  769. pd->position.z = z;
  770. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  771. }
  772. EOLIAN static void
  773. _evas_3d_node_orientation_set(Eo *obj, Evas_3D_Node_Data *pd, Evas_Real x, Evas_Real y, Evas_Real z, Evas_Real w)
  774. {
  775. pd->orientation.x = x;
  776. pd->orientation.y = y;
  777. pd->orientation.z = z;
  778. pd->orientation.w = w;
  779. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  780. }
  781. EOLIAN static void
  782. _evas_3d_node_orientation_angle_axis_set(Eo *obj, Evas_3D_Node_Data *pd,
  783. Evas_Real angle, Evas_Real x, Evas_Real y, Evas_Real z)
  784. {
  785. Evas_Real half_angle = 0.5 * DEGREE_TO_RADIAN(angle);
  786. Evas_Real s = sin(half_angle);
  787. Evas_Vec3 axis;
  788. evas_vec3_set(&axis, x, y, z);
  789. evas_vec3_normalize(&axis, &axis);
  790. pd->orientation.w = cos(half_angle);
  791. pd->orientation.x = s * axis.x;
  792. pd->orientation.y = s * axis.y;
  793. pd->orientation.z = s * axis.z;
  794. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  795. }
  796. EOLIAN static void
  797. _evas_3d_node_scale_set(Eo *obj, Evas_3D_Node_Data *pd, Evas_Real x, Evas_Real y, Evas_Real z)
  798. {
  799. pd->scale.x = x;
  800. pd->scale.y = y;
  801. pd->scale.z = z;
  802. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  803. }
  804. EOLIAN static void
  805. _evas_3d_node_position_get(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Space space,
  806. Evas_Real *x, Evas_Real *y, Evas_Real *z)
  807. {
  808. if (space == EVAS_3D_SPACE_LOCAL)
  809. {
  810. if (x) *x = 0.0;
  811. if (y) *y = 0.0;
  812. if (z) *z = 0.0;
  813. }
  814. else if (space == EVAS_3D_SPACE_PARENT)
  815. {
  816. if (x) *x = pd->position.x;
  817. if (y) *y = pd->position.y;
  818. if (z) *z = pd->position.z;
  819. }
  820. else if (space == EVAS_3D_SPACE_WORLD)
  821. {
  822. eo_do(obj, evas_3d_object_update());
  823. if (x) *x = pd->position_world.x;
  824. if (y) *y = pd->position_world.y;
  825. if (z) *z = pd->position_world.z;
  826. }
  827. }
  828. EOLIAN static void
  829. _evas_3d_node_orientation_get(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Space space,
  830. Evas_Real *x, Evas_Real *y, Evas_Real *z, Evas_Real *w)
  831. {
  832. if (space == EVAS_3D_SPACE_LOCAL)
  833. {
  834. if (x) *x = 0.0;
  835. if (y) *y = 0.0;
  836. if (z) *z = 0.0;
  837. if (w) *w = 0.0;
  838. }
  839. else if (space == EVAS_3D_SPACE_PARENT)
  840. {
  841. if (x) *x = pd->orientation.x;
  842. if (y) *y = pd->orientation.y;
  843. if (z) *z = pd->orientation.z;
  844. if (w) *w = pd->orientation.w;
  845. }
  846. else if (space == EVAS_3D_SPACE_WORLD)
  847. {
  848. eo_do(obj, evas_3d_object_update());
  849. if (x) *x = pd->orientation_world.x;
  850. if (y) *y = pd->orientation_world.y;
  851. if (z) *z = pd->orientation_world.z;
  852. if (w) *w = pd->orientation_world.w;
  853. }
  854. }
  855. EOLIAN static void
  856. _evas_3d_node_scale_get(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Space space,
  857. Evas_Real *x, Evas_Real *y, Evas_Real *z)
  858. {
  859. if (space == EVAS_3D_SPACE_LOCAL)
  860. {
  861. if (x) *x = 0.0;
  862. if (y) *y = 0.0;
  863. if (z) *z = 0.0;
  864. }
  865. else if (space == EVAS_3D_SPACE_PARENT)
  866. {
  867. if (x) *x = pd->scale.x;
  868. if (y) *y = pd->scale.y;
  869. if (z) *z = pd->scale.z;
  870. }
  871. else if (space == EVAS_3D_SPACE_WORLD)
  872. {
  873. eo_do(obj, evas_3d_object_update());
  874. if (x) *x = pd->scale_world.x;
  875. if (y) *y = pd->scale_world.y;
  876. if (z) *z = pd->scale_world.z;
  877. }
  878. }
  879. EOLIAN static void
  880. _evas_3d_node_position_inherit_set(Eo *obj, Evas_3D_Node_Data *pd, Eina_Bool inherit)
  881. {
  882. pd->position_inherit = inherit;
  883. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  884. }
  885. EOLIAN static void
  886. _evas_3d_node_orientation_inherit_set(Eo *obj, Evas_3D_Node_Data *pd, Eina_Bool inherit)
  887. {
  888. pd->orientation_inherit = inherit;
  889. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  890. }
  891. EOLIAN static void
  892. _evas_3d_node_scale_inherit_set(Eo *obj, Evas_3D_Node_Data *pd, Eina_Bool inherit)
  893. {
  894. pd->scale_inherit = inherit;
  895. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  896. }
  897. EOLIAN static Eina_Bool
  898. _evas_3d_node_position_inherit_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  899. {
  900. return pd->position_inherit;
  901. }
  902. EOLIAN static Eina_Bool
  903. _evas_3d_node_orientation_inherit_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  904. {
  905. return pd->orientation_inherit;
  906. }
  907. EOLIAN static Eina_Bool
  908. _evas_3d_node_scale_inherit_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  909. {
  910. return pd->scale_inherit;
  911. }
  912. EOLIAN static void
  913. _evas_3d_node_look_at_set(Eo *obj, Evas_3D_Node_Data *pd,
  914. Evas_3D_Space target_space, Evas_Real tx, Evas_Real ty, Evas_Real tz,
  915. Evas_3D_Space up_space, Evas_Real ux, Evas_Real uy, Evas_Real uz)
  916. {
  917. Evas_Vec3 target;
  918. Evas_Vec3 up;
  919. Evas_Vec3 x, y, z;
  920. /* Target position in parent space. */
  921. if (target_space == EVAS_3D_SPACE_LOCAL)
  922. {
  923. ERR("TODO:");
  924. return;
  925. }
  926. else if (target_space == EVAS_3D_SPACE_PARENT)
  927. {
  928. evas_vec3_set(&target, tx, ty, tz);
  929. }
  930. else if (target_space == EVAS_3D_SPACE_WORLD)
  931. {
  932. ERR("TODO:");
  933. return;
  934. }
  935. else
  936. {
  937. ERR("Invalid coordinate space.");
  938. return;
  939. }
  940. if (up_space == EVAS_3D_SPACE_LOCAL)
  941. {
  942. evas_vec3_set(&up, ux, uy, uz);
  943. //ERR("TODO:");
  944. //return;
  945. }
  946. else if (up_space == EVAS_3D_SPACE_PARENT)
  947. {
  948. evas_vec3_set(&up, ux, uy, uz);
  949. }
  950. else if (up_space == EVAS_3D_SPACE_WORLD)
  951. {
  952. ERR("TODO:");
  953. return;
  954. }
  955. else
  956. {
  957. ERR("Invalid coordinate space.");
  958. return;
  959. }
  960. /* From now on, everything takes place in parent space. */
  961. evas_vec3_subtract(&z, &pd->position, &target);
  962. evas_vec3_normalize(&z, &z);
  963. evas_vec3_cross_product(&x, &up, &z);
  964. evas_vec3_normalize(&x, &x);
  965. evas_vec3_cross_product(&y, &z, &x);
  966. evas_vec3_normalize(&y, &y);
  967. /* Below matrix to quaternion conversion code taken from
  968. * http://fabiensanglard.net/doom3_documentation/37726-293748.pdf
  969. * When any license issue occurs, use ken shoemake's algorithm instead.
  970. */
  971. if (x.x + y.y + z.z > 0.0)
  972. {
  973. Evas_Real t = x.x + y.y + z.z + 1.0;
  974. Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
  975. pd->orientation.w = s * t;
  976. pd->orientation.z = (x.y - y.x) * s;
  977. pd->orientation.y = (z.x - x.z) * s;
  978. pd->orientation.x = (y.z - z.y) * s;
  979. }
  980. else if (x.x > y.y && x.x > z.z)
  981. {
  982. Evas_Real t = x.x - y.y - z.z + 1.0;
  983. Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
  984. pd->orientation.x = s * t;
  985. pd->orientation.y = (x.y + y.x) * s;
  986. pd->orientation.z = (z.x + x.z) * s;
  987. pd->orientation.w = (y.z - z.y) * s;
  988. }
  989. else if (y.y > z.z)
  990. {
  991. Evas_Real t = -x.x + y.y - z.z + 1.0;
  992. Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
  993. pd->orientation.y = s * t;
  994. pd->orientation.x = (x.y + y.x) * s;
  995. pd->orientation.w = (z.x - x.z) * s;
  996. pd->orientation.z = (y.z + z.y) * s;
  997. }
  998. else
  999. {
  1000. Evas_Real t = -x.x - y.y + z.z + 1.0;
  1001. Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
  1002. pd->orientation.z = s * t;
  1003. pd->orientation.w = (x.y - y.x) * s;
  1004. pd->orientation.x = (z.x + x.z) * s;
  1005. pd->orientation.y = (y.z + z.y) * s;
  1006. }
  1007. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM, NULL));
  1008. }
  1009. EOLIAN static void
  1010. _evas_3d_node_camera_set(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Camera *camera)
  1011. {
  1012. if (pd->type != EVAS_3D_NODE_TYPE_CAMERA)
  1013. {
  1014. ERR("Node type mismatch.");
  1015. return;
  1016. }
  1017. if (pd->data.camera.camera == camera)
  1018. return;
  1019. if (pd->data.camera.camera)
  1020. {
  1021. /* Detach previous camera object. */
  1022. evas_3d_camera_node_del(pd->data.camera.camera, obj);
  1023. eo_unref(pd->data.camera.camera);
  1024. }
  1025. pd->data.camera.camera = camera;
  1026. eo_ref(camera);
  1027. /* Register change notification on the camera for this node. */
  1028. evas_3d_camera_node_add(camera, obj);
  1029. /* Mark changed. */
  1030. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_CAMERA, NULL));
  1031. }
  1032. EOLIAN static Evas_3D_Camera *
  1033. _evas_3d_node_camera_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  1034. {
  1035. return pd->data.camera.camera;
  1036. }
  1037. EOLIAN static void
  1038. _evas_3d_node_light_set(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Light *light)
  1039. {
  1040. if (pd->type != EVAS_3D_NODE_TYPE_LIGHT)
  1041. {
  1042. ERR("Node type mismatch.");
  1043. return;
  1044. }
  1045. if (pd->data.light.light == light)
  1046. return;
  1047. if (pd->data.light.light)
  1048. {
  1049. /* Detach previous light object. */
  1050. evas_3d_light_node_del(pd->data.light.light, obj);
  1051. eo_unref(pd->data.light.light);
  1052. }
  1053. pd->data.light.light = light;
  1054. eo_ref(light);
  1055. /* Register change notification on the light for this node. */
  1056. evas_3d_light_node_add(light, obj);
  1057. /* Mark changed. */
  1058. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_LIGHT, NULL));
  1059. }
  1060. EOLIAN static Evas_3D_Light *
  1061. _evas_3d_node_light_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  1062. {
  1063. return pd->data.light.light;
  1064. }
  1065. EOLIAN static void
  1066. _evas_3d_node_mesh_add(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Mesh *mesh)
  1067. {
  1068. Evas_3D_Node_Mesh *nm = NULL;
  1069. if (pd->type != EVAS_3D_NODE_TYPE_MESH)
  1070. {
  1071. ERR("Node type mismatch.");
  1072. return;
  1073. }
  1074. if (eina_hash_find(pd->data.mesh.node_meshes, &mesh) != NULL)
  1075. {
  1076. ERR("The mesh is already added to the node.");
  1077. return;
  1078. }
  1079. if ((nm = _node_mesh_new(obj, mesh)) == NULL)
  1080. {
  1081. ERR("Failed to create node mesh.");
  1082. return;
  1083. }
  1084. /* TODO: Find node mesh and add if it does not exist. */
  1085. if (!eina_hash_add(pd->data.mesh.node_meshes, &mesh, nm))
  1086. {
  1087. ERR("Failed to add a mesh to mesh table.");
  1088. _node_mesh_free(nm);
  1089. return;
  1090. }
  1091. pd->data.mesh.meshes = eina_list_append(pd->data.mesh.meshes, mesh);
  1092. eo_ref(mesh);
  1093. /* Register change notification. */
  1094. evas_3d_mesh_node_add(mesh, obj);
  1095. /* Mark changed. */
  1096. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MESH_GEOMETRY, NULL));
  1097. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MESH_MATERIAL, NULL));
  1098. }
  1099. EOLIAN static void
  1100. _evas_3d_node_mesh_del(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Mesh *mesh)
  1101. {
  1102. if (pd->type != EVAS_3D_NODE_TYPE_MESH)
  1103. {
  1104. ERR("Node type mismatch.");
  1105. return;
  1106. }
  1107. if (!eina_hash_del(pd->data.mesh.node_meshes, &mesh, NULL))
  1108. {
  1109. ERR("The given mesh doesn't belong to this node.");
  1110. return;
  1111. }
  1112. pd->data.mesh.meshes = eina_list_remove(pd->data.mesh.meshes, mesh);
  1113. evas_3d_mesh_node_del(mesh, obj);
  1114. eo_unref(mesh);
  1115. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MESH_GEOMETRY, NULL));
  1116. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MESH_MATERIAL, NULL));
  1117. }
  1118. EOLIAN static const Eina_List *
  1119. _evas_3d_node_mesh_list_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd)
  1120. {
  1121. return pd->data.mesh.meshes;
  1122. }
  1123. EOLIAN static void
  1124. _evas_3d_node_mesh_frame_set(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Mesh *mesh, int frame)
  1125. {
  1126. Evas_3D_Node_Mesh *nm = NULL;
  1127. if (pd->type != EVAS_3D_NODE_TYPE_MESH)
  1128. {
  1129. ERR("Node type mismatch.");
  1130. return;
  1131. }
  1132. if ((nm = eina_hash_find(pd->data.mesh.node_meshes, &mesh)) == NULL)
  1133. {
  1134. ERR("The given mesh doesn't belongs to this node.");
  1135. return;
  1136. }
  1137. nm->frame = frame;
  1138. eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_MESH_FRAME, NULL));
  1139. }
  1140. EOLIAN static int
  1141. _evas_3d_node_mesh_frame_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Evas_3D_Mesh *mesh)
  1142. {
  1143. Evas_3D_Node_Mesh *nm = NULL;
  1144. if (pd->type != EVAS_3D_NODE_TYPE_MESH)
  1145. {
  1146. ERR("Node type mismatch.");
  1147. return 0;
  1148. }
  1149. if ((nm = eina_hash_find(pd->data.mesh.node_meshes, &mesh)) == NULL)
  1150. {
  1151. ERR("The given mesh doesn't belongs to this node.");
  1152. return 0;
  1153. }
  1154. return nm->frame;
  1155. }
  1156. EOLIAN static void
  1157. _evas_3d_node_bounding_box_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Evas_Real *x, Evas_Real *y, Evas_Real *z, Evas_Real *x2, Evas_Real *y2, Evas_Real *z2)
  1158. {
  1159. if (x) *x = pd->aabb.p0.x;
  1160. if (y) *y = pd->aabb.p0.y;
  1161. if (z) *z = pd->aabb.p0.z;
  1162. if (x2) *x2 = pd->aabb.p1.x;
  1163. if (y2) *y2 = pd->aabb.p1.y;
  1164. if (z2) *z2 = pd->aabb.p1.z;
  1165. }
  1166. EOLIAN static int
  1167. _evas_3d_node_obb_frustum_check(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Evas_3D_Node *camera_node)
  1168. {
  1169. Evas_Mat4 matrix_eye = { { 0 } };
  1170. Evas_Mat4 matrix_local_to_world;
  1171. Evas_Mat4 matrix_mv;
  1172. Evas_Mat4 matrix_mvp;
  1173. Evas_Vec4 plane_right, plane_left, plane_bottom, plane_top, plane_far, plane_near, tmp;
  1174. int frustum = 0;
  1175. Evas_3D_Node_Data *camera_pd = eo_data_scope_get(camera_node, EVAS_3D_CAMERA_CLASS);
  1176. Evas_3D_Camera_Data *camera = eo_data_scope_get(camera_pd->data.camera.camera, EVAS_3D_CAMERA_CLASS);
  1177. if (camera_pd->type != EVAS_3D_NODE_TYPE_CAMERA)
  1178. {
  1179. ERR("Nodes type mismatch.");
  1180. return -1;
  1181. }
  1182. #define CHECK_IN_FRUSTUM_MIN(name) \
  1183. (((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)
  1184. #define CHECK_IN_FRUSTUM_MAX(name) \
  1185. (((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)
  1186. #define NORMALIZE(name) \
  1187. evas_vec4_copy(&tmp, &plane_##name); \
  1188. plane_##name.x = plane_##name.x / sqrtf(evas_vec4_length_square_get(&tmp)); \
  1189. plane_##name.y = plane_##name.y / sqrtf(evas_vec4_length_square_get(&tmp)); \
  1190. plane_##name.z = plane_##name.z / sqrtf(evas_vec4_length_square_get(&tmp)); \
  1191. plane_##name.w = plane_##name.w / sqrtf(evas_vec4_length_square_get(&tmp));
  1192. /*get need matrix like multiply view matrix with projection matrix*/
  1193. evas_mat4_inverse_build(&matrix_eye, &camera_pd->position_world, &camera_pd->orientation_world, &camera_pd->scale_world);
  1194. evas_mat4_build(&matrix_local_to_world, &pd->position_world, &pd->orientation_world, &pd->scale_world);
  1195. evas_mat4_multiply(&matrix_mv, &matrix_eye, &matrix_local_to_world);
  1196. evas_mat4_multiply(&matrix_mvp, &camera->projection, &matrix_mv);
  1197. /*get planes and normilize results*/
  1198. evas_vec4_set(&plane_right, matrix_mvp.m[3] - matrix_mvp.m[0],
  1199. matrix_mvp.m[7] - matrix_mvp.m[4],
  1200. matrix_mvp.m[11] - matrix_mvp.m[8],
  1201. matrix_mvp.m[15] - matrix_mvp.m[12]);
  1202. NORMALIZE(right)
  1203. evas_vec4_set(&plane_left, matrix_mvp.m[3] + matrix_mvp.m[0],
  1204. matrix_mvp.m[7] + matrix_mvp.m[4],
  1205. matrix_mvp.m[11] + matrix_mvp.m[8],
  1206. matrix_mvp.m[15] + matrix_mvp.m[12]);
  1207. NORMALIZE(left)
  1208. evas_vec4_set(&plane_bottom, matrix_mvp.m[3] + matrix_mvp.m[1],
  1209. matrix_mvp.m[7] + matrix_mvp.m[5],
  1210. matrix_mvp.m[11] + matrix_mvp.m[9],
  1211. matrix_mvp.m[15] + matrix_mvp.m[13]);
  1212. NORMALIZE(bottom)
  1213. evas_vec4_set(&plane_top, matrix_mvp.m[3] - matrix_mvp.m[1],
  1214. matrix_mvp.m[7] - matrix_mvp.m[5],
  1215. matrix_mvp.m[11] - matrix_mvp.m[9],
  1216. matrix_mvp.m[15] - matrix_mvp.m[13]);
  1217. NORMALIZE(top)
  1218. evas_vec4_set(&plane_far, matrix_mvp.m[3] - matrix_mvp.m[2],
  1219. matrix_mvp.m[7] - matrix_mvp.m[6],
  1220. matrix_mvp.m[11] - matrix_mvp.m[10],
  1221. matrix_mvp.m[15] - matrix_mvp.m[14]);
  1222. NORMALIZE(far)
  1223. evas_vec4_set(&plane_near, matrix_mvp.m[3] + matrix_mvp.m[2],
  1224. matrix_mvp.m[7] + matrix_mvp.m[6],
  1225. matrix_mvp.m[11] + matrix_mvp.m[10],
  1226. matrix_mvp.m[15] + matrix_mvp.m[14]);
  1227. NORMALIZE(near)
  1228. #undef NORMALIZE
  1229. /*check OBB points in frustum (Ax + By + Cz + D >= 0)*/
  1230. if (CHECK_IN_FRUSTUM_MIN(right) && CHECK_IN_FRUSTUM_MIN(left)
  1231. && CHECK_IN_FRUSTUM_MIN(bottom) && CHECK_IN_FRUSTUM_MIN(top)
  1232. && CHECK_IN_FRUSTUM_MIN(far) && CHECK_IN_FRUSTUM_MIN(near))
  1233. frustum |= 1;
  1234. if (CHECK_IN_FRUSTUM_MAX(right) && CHECK_IN_FRUSTUM_MAX(left)
  1235. && CHECK_IN_FRUSTUM_MAX(bottom) && CHECK_IN_FRUSTUM_MAX(top)
  1236. && CHECK_IN_FRUSTUM_MAX(far) && CHECK_IN_FRUSTUM_MAX(near))
  1237. frustum |= 2;
  1238. #undef CHECK_IN_FRUSTUM_MIN
  1239. #undef CHECK_IN_FRUSTUM_MAX
  1240. return frustum;
  1241. }
  1242. #include "canvas/evas_3d_node.eo.c"