35#include <libFreeWRL.h>
37#include "../vrml_parser/Structs.h"
38#include "../main/headers.h"
40#include "../x3d_parser/Bindable.h"
41#include "LinearAlgebra.h"
43#include "quaternion.h"
45#include "../opengl/Frustum.h"
47#include "../opengl/OpenGL_Utils.h"
48#include "../opengl/Frustum.h"
49#include "../scenegraph/RenderFuncs.h"
50#include "../ui/common.h"
53struct X3D_Node *getActiveLayerBoundViewpoint();
54struct X3D_Node* getSelectedViewpoint();
59 if (!renderstate()->render_vp)
return;
66 node->_reachablethispass = TRUE;
68 if ((
struct X3D_Node*)node == getSelectedViewpoint() && !node->_donethispass) {
69 node->_donethispass = 1;
76 vrmlrot_to_quaternion(&q3,node->orientation.c[0],node->orientation.c[1],node->orientation.c[2],-node->orientation.c[3]);
79 FW_GL_TRANSLATE_D(-node->position.c[0],-node->position.c[1],-node->position.c[2]);
82 FW_GL_GETINTEGERV(GL_VIEWPORT, viewPort);
83 if(viewPort[2] > viewPort[3]) {
85 viewer->fieldofview = node->fieldOfView/3.1415926536*180;
87 a1 = node->fieldOfView;
88 a1 = atan2(sin(a1),viewPort[2]/((
float)viewPort[3]) * cos(a1));
89 viewer->fieldofview = a1/3.1415926536*180;
94void draw_viewpoint(
int type,
float *fov,
float aspect);
96 float center[3],size[3];
97 if(node->_show_pin_point || fwl_getShowViewpoints())
98 draw_bbox(double2float(center,node->_pin_point.c,3),vecset3f(size,.4f,.4f,.4f));
99 if(fwl_getShowViewpoints()){
101 FW_GL_TRANSLATE_D(node->_position.c[0],node->_position.c[1],node->_position.c[2]);
102 FW_GL_ROTATE_RADIANS( node->_orientation.c[3],node->_orientation.c[0],node->_orientation.c[1],
103 node->_orientation.c[2]);
105 draw_viewpoint(node->_nodeType,&node->fieldOfView,node->aspectRatio);
110 float center[3],size[3];
111 if(node->_show_pin_point || fwl_getShowViewpoints())
112 draw_bbox(double2float(center,node->_pin_point.c,3),vecset3f(size,.4f,.4f,.4f));
113 if(fwl_getShowViewpoints()){
115 FW_GL_TRANSLATE_D(node->_position.c[0],node->_position.c[1],node->_position.c[2]);
116 FW_GL_ROTATE_RADIANS( node->_orientation.c[3],node->_orientation.c[0],node->_orientation.c[1],
117 node->_orientation.c[2]);
119 draw_viewpoint(node->_nodeType,node->fieldOfView.p,1.0f);
127 if (!renderstate()->render_vp)
return;
133 node->_reachablethispass = TRUE;
135 if((
struct X3D_Node*)node == getSelectedViewpoint() && !node->_donethispass){
136 node->_donethispass = 1;
140 FW_GL_ROTATE_RADIANS(-node->orientation.c[3],node->orientation.c[0],node->orientation.c[1],
141 node->orientation.c[2]);
142 FW_GL_TRANSLATE_D(-node->position.c[0],-node->position.c[1],-node->position.c[2]);
145 if (node->fieldOfView.n == 4) {
146 for (ind=0; ind<4; ind++) {
147 Viewer()->orthoField[ind] = (double) node->fieldOfView.p[ind];
162 double mod[16], modi[16], matr[16], axis[3];
165 push_transform_local_identity();
170 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
171 float2double(axis,node->axisOfRotation.c,3);
172 align = (APPROX(veclengthd(axis),0.0f));
176 double modb[16], modbi[16];
177 matrixAFFINE2RotationMatrix(modb,mod);
178 matinverseAFFINE(matr,modb);
179 FW_GL_TRANSFORM_D(matr);
188 double vpos[3], zvec[3], perpa[3], perpb[3];
190 vecsetd(vpos,0.0,0.0,0.0);
191 matinverseAFFINE(modi,mod);
192 transformAFFINEd(vpos,vpos,modi);
193 vecnormald(vpos,vpos);
195 vecsetd(zvec,0.0,0.0,1.0);
197 veccrossd(perpa,axis,vpos);
198 veccrossd(perpb,axis,zvec);
200 matrotate2vd(matr,perpa,perpb);
201 FW_GL_TRANSFORM_D(matr);
203 reset_transform_local(matr);
208 struct point_XYZ vpos, ax, cp, cp2, arcp;
209 static const struct point_XYZ orig = {.x=0.0, .y=0.0, .z=0.0};
210 static const struct point_XYZ zvec = {.x=0.0, .y=0.0, .z=1.0};
215 double len, len2, angle;
218 ax.x = node->axisOfRotation.c[0];
219 ax.y = node->axisOfRotation.c[1];
220 ax.z = node->axisOfRotation.c[2];
221 align = (APPROX(VECSQ(ax),0));
223 viewer_fetch_LCS(Viewer());
224 quaternion_to_vrmlrot(&(Viewer()->
Quat),
225 &(viewer_orient.x), &(viewer_orient.y),
226 &(viewer_orient.z), &(viewer_orient.a));
230 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
232 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
233 FW_GLU_UNPROJECT(orig.x, orig.y, orig.z, mod, proj, viewport, &vpos.x, &vpos.y, &vpos.z);
238 matinverseAFFINE(modi,mod);
239 transform(&vpos,&orig,modi);
242 if (APPROX(len, 0)) {
return; }
243 VECSCALE(vpos, 1/sqrt(len));
246 ax.x = viewer_orient.x;
247 ax.y = viewer_orient.y;
248 ax.z = viewer_orient.z;
251 VECCP(ax, zvec, arcp);
253 if (APPROX(len, 0)) {
return; }
256 if (APPROX(len, 0)) {
return; }
257 VECSCALE(ax, 1/sqrt(len));
260 len = sqrt(VECSQ(cp));
261 if (APPROX(len, 0)) {
262 FW_GL_ROTATE_RADIANS(-viewer_orient.a, ax.x, ax.y, ax.z);
268 VECCP(cp, zvec, cp2);
270 len2 = VECPT(cp, zvec);
271 len = sqrt(VECSQ(cp2));
274 if (VECPT(cp, arcp) > 0)
280 angle = atan2(len2, sign*len);
282 FW_GL_ROTATE_RADIANS(angle, ax.x, ax.y, ax.z);
288 pop_transform_local();
295 int nc = node->children.n;
301 prep_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
303 prep_BBox((
struct BBoxFields*)&node->bboxCenter);
304 normalChildren(node->children);
306 fin_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
336 int nc = node->children.n;
340 if(renderstate()->render_collision) {
342 if((node->collide) && (node->enabled) && !(node->proxy)) {
345 OldCollisionInfo = *ci;
346 for(i=0; i<nc; i++) {
347 void *p = ((node->children).p[i]);
349 printf(
"RENDER COLLISION %d CHILD %d\n",node, p);
353 if((!APPROX(ci->Offset.x,
354 OldCollisionInfo.Offset.x)) ||
355 (!APPROX(ci->Offset.y,
356 OldCollisionInfo.Offset.y)) ||
357 (!APPROX(ci->Offset.z,
358 OldCollisionInfo.Offset.z))) {
365 node->__hit = (node->__hit & 1) ? 1 : 3;
367 node->__hit = (node->__hit & 1) ? 2 : 0;
371 POSSIBLE_PROTO_EXPANSION(
struct X3D_Node *, node->proxy,tmpN)
378 prep_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
380 prep_BBox((
struct BBoxFields*)&node->bboxCenter);
381 normalChildren(node->children);
384 fin_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
389void child_LOD (
struct X3D_LOD *node) {
409 prep_BBox((
struct BBoxFields*)&node->bboxCenter);
410 render_node(node->_selected);
417void proximity_LOD (
struct X3D_LOD *node) {
425 int nran = (node->range).n;
430 int spec = X3D_PROTO(node->_executionContext)->__specversion;
431 if (spec < 300 || node->level.n) {
436 pp = node->children.p;
437 n = node->children.n;
443 node->_selected = pp[0];
445 node->_selected = NULL;
450 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
454 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
455 FW_GLU_UNPROJECT(0,0,0,mod,proj,viewport, &vec.x,&vec.y,&vec.z);
462 struct point_XYZ orig = {.x=0.0,.y=0.0,.z=0.0};
463 matinverseAFFINE(modi,mod);
464 transform(&vec,&orig,modi);
468 vec.x -= (node->center).c[0];
469 vec.y -= (node->center).c[1];
470 vec.z -= (node->center).c[2];
472 dist = sqrt(VECSQ(vec));
476 if(dist < ((node->range).p[i])) {
break; }
482 if (i >= n) i = n - 1;
483 if (node->_lastMethod > 0) {
484 if (Viewer()->SLERPing || Viewer()->SLERPing2 || Viewer()->SLERPing3)
485 node->_lastMethod = 1;
487 node->_lastMethod = 0;
490 node->_selected = pp[i];
493 else { node->_selected = NULL; }
495 if(i != node->level_changed){
496 node->level_changed = i;
497 MARK_EVENT(X3D_NODE(node),offsetof(
struct X3D_LOD,level_changed));
508 void add_node_to_broto_context(
struct X3D_Proto *currentContext,
struct X3D_Node *node);
514 if (node->__proxNode == NULL) {
517 if(node->_executionContext)
518 add_node_to_broto_context(X3D_PROTO(node->_executionContext),X3D_NODE(pn));
521 node->__proxNode = (
void *)pn;
524 ADD_PARENT(X3D_NODE(pn),X3D_NODE(node));
528 pn = X3D_PROXIMITYSENSOR(node->__proxNode);
531 memcpy (&pn->center, &node->center, sizeof (
float)*3);
532 memcpy (&pn->size, &node->size, sizeof (
float)*3);
554 if (renderstate()->render_proximity) {
555 if (node->__proxNode != NULL) {
557 render_node(X3D_NODE(node->__proxNode));
564 if (!renderstate()->render_vp)
return;
567 for(i=0; i<node->children.n; i++) {
568 struct X3D_Node *p = X3D_NODE(node->children.p[i]);
576#define strcasecmp stricmp
578void draw_frustum(
float *corners);
579static double screespace_allowed_error = 5.0;
580void compile_Tile(
struct X3D_Tile *node){
583void prep_Tile(
struct X3D_Tile *node){
585static int tile_view_frozen = FALSE;
586int getTileViewFrozen(){
587 return tile_view_frozen;
589void toggleTileViewFrozen(){
591 tile_view_frozen = 1 - tile_view_frozen;
592 if(tile_view_frozen) printf(
"FREEZING tile view\n");
593 else printf(
"UN-FREEZING tile view\n");
596 TILE_REFINE_DEFAULT = 0,
597 TILE_REFINE_REPLACE = 1,
601 BOUNDING_VOLUME_NONE = 0,
602 BOUNDING_VOLUME_BBOX = 1,
603 BOUNDING_VOLUME_SPHERE = 2,
604 BOUNDING_VOLUME_REGION = 3,
606void child_Tile(
struct X3D_Tile *node){
611 double screenspace_error = 1.e+06;
612 static double mod[16], proj[16], mvproj[16];
613 static struct Planed frustum_planes[6];
614 static float frustum_corners[24];
615 static int have_frustum_corners;
616 static int have_mod = FALSE;
617 static int child_tile = FALSE;
618 static int once = FALSE;
619 int root_tile = FALSE;
620 if(!child_tile) root_tile = TRUE;
623 printf(
"Press '=' key to FREEZE / UNFREEZE Tile computational Viewpoint\n");
627 if( (!getTileViewFrozen() || !have_mod) && root_tile){
631 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
633 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
635 matmultiplyFULL(mvproj,mod,proj);
636 setFrustumPlanes(mvproj,frustum_planes);
637 have_frustum_corners = frustum_generate_corner_points(frustum_planes, frustum_corners);
640 if(have_frustum_corners && root_tile){
641 draw_frustum(frustum_corners);
643 int refine, cbvtype, bvtype;
644 refine = TILE_REFINE_DEFAULT;
645 if(!strcasecmp(node->refine->strptr,
"REPLACE")) refine = TILE_REFINE_REPLACE;
646 else if(!strcasecmp(node->refine->strptr,
"ADD")) refine = TILE_REFINE_ADD;
650 cbvtype = BOUNDING_VOLUME_NONE;
651 if(!strcasecmp(node->contentVolumeType->strptr,
"BBOX")) cbvtype = BOUNDING_VOLUME_BBOX;
652 else if(!strcasecmp(node->contentVolumeType->strptr,
"SPHERE")) cbvtype = BOUNDING_VOLUME_SPHERE;
653 else if(!strcasecmp(node->contentVolumeType->strptr,
"REGION")) cbvtype = BOUNDING_VOLUME_REGION;
654 if(node->contentVolume.n == 0) cbvtype = BOUNDING_VOLUME_NONE;
655 bvtype = BOUNDING_VOLUME_NONE;
656 if(!strcasecmp(node->boundingVolumeType->strptr,
"BBOX")) bvtype = BOUNDING_VOLUME_BBOX;
657 else if(!strcasecmp(node->boundingVolumeType->strptr,
"SPHERE")) bvtype = BOUNDING_VOLUME_SPHERE;
658 else if(!strcasecmp(node->boundingVolumeType->strptr,
"REGION")) bvtype = BOUNDING_VOLUME_REGION;
659 if(node->boundingVolume.n == 0) bvtype = BOUNDING_VOLUME_NONE;
661 int inview_content, inview_tile;
662 inview_content = inview_tile = TRUE;
665 double modi[16], orig[3], origb[3], vec[3],vecb[3],
vec4[4], range, viewspace_error, nearplane_error;
677 if(bvtype == BOUNDING_VOLUME_BBOX && node->boundingVolume.n == 12){
679 float2double(orig,node->boundingVolume.p,3);
680 transformAFFINEd(vec,orig,mod);
681 range = veclengthd(vec);
682 }
else if(bvtype == BOUNDING_VOLUME_SPHERE && node->boundingVolume.n == 4){
683 float2double(orig,node->boundingVolume.p,3);
684 transformAFFINEd(vec,orig,mod);
685 range = veclengthd(vec);
686 }
else if(bvtype == BOUNDING_VOLUME_REGION && node->boundingVolume.n == 6){
689 vecsetd(
vec4,node->geometricError,0.0,-range);
694 vecsetd(
vec4,0.0,0.0,-range);
700 vecdifd(vec,orig,origb);
701 nearplane_error = veclengthd(vec);
702 FW_GL_GETINTEGERV(GL_VIEWPORT, viewPort);
703 screenspace_error = (nearplane_error / 2.0) * (
double) viewPort[2];
709 if(cbvtype == BOUNDING_VOLUME_BBOX && node->contentVolume.n == 12)
711 float p3fn24[24], extent6[6], overlap[6];
712 orientedBBox2vec3fn(p3fn24, node->contentVolume.p);
714 inview_content = FALSE;
719 float ff[3], cuboid[6];
721 extent6f_constructor(cuboid,-1.0f,1.0f,-1.0f,1.0f,-1.0f,1.0f);
723 for(
int i=0;i<8;i++){
724 float2double(dd,&p3fn24[3*i],3);
726 transformFULL4d(dd,dd,mvproj);
727 vecscaled(dd,dd,1.0/dd[3]);
728 double2float(ff,dd,3);
729 inside = inside || extent6f_point_inside(cuboid,ff);
731 float2double(dd,node->contentVolume.p,3);
733 transformFULL4d(dd,dd,mvproj);
734 vecscaled(dd,dd,1.0/dd[3]);
735 double2float(ff,dd,3);
736 inside = inside || extent6f_point_inside(cuboid,ff);
738 inview_content = inside;
745 int inpoint, inside = FALSE;
746 for(
int i=0;i<8;i++){
747 float2double(dd,&p3fn24[3*i],3);
749 inpoint = frustum_point_inside(frustum_planes,dd);
750 inside = inside || inpoint;
753 float2double(dd,node->contentVolume.p,3);
754 inpoint = frustum_point_inside(frustum_planes,dd);
755 inside = inside || inpoint;
758 inview_content = inside;
763 inview_content = frustum_box_inside(frustum_planes,p3fn24,8);
766 if(bvtype == BOUNDING_VOLUME_BBOX && node->boundingVolume.n == 12)
768 float p3fn24[24], extent6[6], overlap[6];
770 matmultiplyFULL(mvproj,proj,mod);
771 orientedBBox2vec3fn(p3fn24, node->boundingVolume.p);
777 float ff[3], cuboid[6];
778 extent6f_constructor(cuboid,-1.0f,1.0f,-1.0f,1.0f,-1.0f,1.0f);
780 for(
int i=0;i<8;i++){
781 float2double(dd,&p3fn24[3*i],3);
783 transformFULL4d(dd,dd,mvproj);
784 vecscaled(dd,dd,1.0/dd[3]);
785 double2float(ff,dd,3);
786 inside = inside || extent6f_point_inside(cuboid,ff);
788 float2double(dd,node->boundingVolume.p,3);
790 transformFULL4d(dd,dd,mvproj);
791 vecscaled(dd,dd,1.0/dd[3]);
792 double2float(ff,dd,3);
793 inside = inside || extent6f_point_inside(cuboid,ff);
795 inview_tile = inside;
802 int inpoint, inside = FALSE;
803 for(
int i=0;i<8;i++){
804 float2double(dd,&p3fn24[3*i],3);
805 inpoint = frustum_point_inside(frustum_planes,dd);
806 inside = inside || inpoint;
812 float2double(dd,node->boundingVolume.p,3);
813 inpoint = frustum_point_inside(frustum_planes,dd);
814 inside = inside || inpoint;
817 inview_tile = inside;
822 inview_tile = frustum_box_inside(frustum_planes,p3fn24,8);
827 if(root_tile) child_tile = TRUE;
828 int no_sse_cull = FALSE;
829 int no_bv_cull = FALSE;
830 prep_BBox((
struct BBoxFields*)&node->bboxCenter);
831 if(cbvtype == BOUNDING_VOLUME_NONE || cbvtype == BOUNDING_VOLUME_BBOX && inview_content || no_bv_cull)
832 if(screenspace_error <= screespace_allowed_error || node->children.n == 0 || refine == TILE_REFINE_ADD || no_sse_cull){
833 render_node(node->content);
835 if(node->showContent == FALSE){
836 node->showContent = TRUE;
837 MARK_EVENT (X3D_NODE(node),offsetof (
struct X3D_Tile, showContent));
840 if(node->showContent == TRUE){
841 node->showContent = FALSE;
842 MARK_EVENT (X3D_NODE(node),offsetof (
struct X3D_Tile, showContent));
845 if(bvtype == BOUNDING_VOLUME_NONE || bvtype == BOUNDING_VOLUME_BBOX && inview_tile || no_bv_cull)
846 if(screenspace_error > screespace_allowed_error && node->children.n > 0 || no_sse_cull){
848 prep_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
850 normalChildren(node->children);
852 fin_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
855 if(root_tile) child_tile = FALSE;
859void proximity_Tile(
struct X3D_Tile *node){