34#include <libFreeWRL.h>
36#include "../vrml_parser/Structs.h"
37#include "../opengl/OpenGL_Utils.h"
38#include "../opengl/Frustum.h"
39#include "../main/headers.h"
41#include "LinearAlgebra.h"
42#include "quaternion.h"
44#include "../x3d_parser/Bindable.h"
56static void init_stereodefaults(X3D_Viewer *Viewer)
59 Viewer->shutterGlasses = 0;
61 Viewer->sidebyside = 0;
64 Viewer->eyedist = 0.065;
70 Viewer->screendist = 0.375;
71 Viewer->stereoParameter = 0.01;
72 Viewer->dominantEye = 1;
73 Viewer->eitherDominantEye = 1;
76 Viewer->haveQuadbuffer = 0;
83 int viewer_initialized;
84 X3D_Viewer_Walk viewer_walk;
85 X3D_Viewer_Examine viewer_examine;
86 X3D_Viewer_Fly viewer_fly;
87 X3D_Viewer_Spherical viewer_ypz;
92 int StereoInitializedOnce;
93 GLboolean acMask[3][3];
103void *Viewer_constructor(){
104 void *v = MALLOCV(
sizeof(
struct pViewer));
105 memset(v,0,
sizeof(
struct pViewer));
108void Viewer_init(
struct tViewer *t){
112 t->prv = Viewer_constructor();
114 ppViewer p = (ppViewer)t->prv;
116 p->examineCounter = 5;
118 p->viewer_initialized = FALSE;
124 p->StereoInitializedOnce = 0;
125 p->acMask[0][0] = (GLboolean)1;
127 p->acMask[1][1] = (GLboolean)1;
128 p->acMask[1][2] = (GLboolean)1;
131 loadIdentityMatrix(p->old2new);
132 loadIdentityMatrix(p->identity);
134 p->StereoInitializedOnce = 1;
135 p->keychord = CHORD_XY;
136 p->dragchord = CHORD_YAWZ;
144static void handle_tick_fly(
void);
145static void handle_tick_exfly(
void);
146static void handle_tick_fly2(
double dtime);
150void getCurrentSpeed() {
153 ttglobal tg = gglobal();
156 tg->Mainloop.BrowserSpeed = tg->Mainloop.BrowserFPS * (fabs(
viewer->VPvelocity.x) + fabs(
viewer->VPvelocity.y) + fabs(
viewer->VPvelocity.z));
159void viewer_default0(X3D_Viewer *
viewer,
int vpnodetype) {
161 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
163 viewer->fieldofview = 45.0;
168 viewer->currentPosInModel.x = 0;
viewer->currentPosInModel.y = 0;
viewer->currentPosInModel.z = 10;
171 vrmlrot_to_quaternion (&
viewer->Quat,1.0,0.0,0.0,0.0);
173 viewer->vp2rnSaved = FALSE;
177 memcpy (&
viewer->walk, &p->viewer_walk,sizeof (X3D_Viewer_Walk));
178 memcpy (&
viewer->examine, &p->viewer_examine, sizeof (X3D_Viewer_Examine));
179 memcpy (&
viewer->fly, &p->viewer_fly, sizeof (X3D_Viewer_Fly));
180 memcpy (&
viewer->ypz,&p->viewer_ypz, sizeof (X3D_Viewer_Spherical));
182 if(vpnodetype == NODE_OrthoViewpoint){
184 fwl_set_viewer_type0(
viewer,VIEWER_NONE);
185 viewer->orthoField[0] = -1.0;
186 viewer->orthoField[1] = -1.0;
187 viewer->orthoField[2] = 1.0;
188 viewer->orthoField[3] = 1.0;
190 viewer->farPlane = 210000.0;
194 fwl_set_viewer_type0(
viewer,VIEWER_EXAMINE);
196 viewer->farPlane = 210000.0;
203X3D_Viewer *ViewerByLayerId(
int layerid)
211 bstack = getBindableStacksByLayer(tg,layerid);
214 viewer = MALLOCV(
sizeof(X3D_Viewer));
215 memset(
viewer,0,
sizeof(X3D_Viewer));
216 vpnodetype = bstack->nodetype == NODE_LayoutLayer ? NODE_OrthoViewpoint : NODE_Viewpoint;
218 viewer_default0(
viewer,vpnodetype);
219 init_stereodefaults(
viewer);
222 return bstack->viewer;
228 return ViewerByLayerId(tg->Bindable.activeLayer);
231void viewer_default() {
234 viewer_default0(
viewer,NODE_Viewpoint);
237void resolve_pos2(X3D_Viewer *
viewer);
238void resolve_pos20(X3D_Viewer *
viewer);
239void viewer_init (X3D_Viewer *
viewer,
int type) {
240 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
243 if (!p->viewer_initialized) {
244 p->viewer_initialized = TRUE;
250 viewer->currentPosInModel.x = 0;
viewer->currentPosInModel.y = 0;
viewer->currentPosInModel.z = 10;
253 vrmlrot_to_quaternion (&
viewer->Quat,1.0,0.0,0.0,0.0);
260 memcpy (&
viewer->walk, &p->viewer_walk,sizeof (X3D_Viewer_Walk));
261 memcpy (&
viewer->examine, &p->viewer_examine, sizeof (X3D_Viewer_Examine));
262 memcpy (&
viewer->fly, &p->viewer_fly, sizeof (X3D_Viewer_Fly));
263 memcpy (&
viewer->ypz,&p->viewer_ypz, sizeof (X3D_Viewer_Spherical));
268 viewer->startSLERPtime = 0.0;
269 viewer->transitionType = VIEWER_TRANSITION_LINEAR;
270 viewer->transitionTime = 1.0;
275 viewer->doExamineModeDistanceCalculations = FALSE;
278 viewer->screenOrientation = 0;
280 viewer->nearPlane=DEFAULT_NEARPLANE;
281 viewer->farPlane=DEFAULT_FARPLANE;
282 viewer->backgroundPlane = DEFAULT_BACKGROUNDPLANE;
294void printStatsRoutes()
296 ConsoleMessage(
"%25s %d\n",
"Routes count", getCRouteCount());
299void printStatsBindingStacks();
300void printStatsResources();
301void printStatsEvents();
302void printStatsNodes();
306 printStatsResources();
310 printStatsBindingStacks();
313char* fwl_currentBoundVPname();
322 quaternion_to_vrmlrot(&(
viewer->Quat), &(ori.x),&(ori.y),&(ori.z), &(ori.a));
323 ConsoleMessage(
"Viewpoint local{\n");
324 ConsoleMessage(
"\tPosition[%.4f, %.4f, %.4f]\n", (
viewer->Pos).x, (
viewer->Pos).y, (
viewer->Pos).z);
325 ConsoleMessage(
"\tQuaternion[%.4f, %.4f, %.4f, %.4f]\n", (
viewer->Quat).w, (
viewer->Quat).x, (
viewer->Quat).y, (
viewer->Quat).z);
326 ConsoleMessage(
"\tOrientation[%.4f, %.4f, %.4f, %.4f]\n", ori.x, ori.y, ori.z, ori.a);
327 ConsoleMessage(
"}\n");
328 ConsoleMessage(
"vp description %s\n", fwl_currentBoundVPname());
330 getCurrentPosInModelB();
331 ConsoleMessage(
"World Coordinates of Avatar [%.4f, %.4f %.4f]\n",
viewer->currentPosInModel.x,
viewer->currentPosInModel.y,
viewer->currentPosInModel.z);
335int fwl_get_headlight() {
336 return(Viewer()->headlight);
339void fwl_toggle_headlight() {
343 if (
viewer->headlight == TRUE) {
344 viewer->headlight = FALSE;
351void setNoCollision() {
357 return fwl_getCollision();
359void toggle_collision() {
365int fwl_getCollision(){
372void fwl_setCollision(
int state) {
375 viewer->collision = state;
378void fwl_init_StereoDefaults()
381 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
383 if(!p->StereoInitializedOnce)
384 init_stereodefaults(
viewer);
385 p->StereoInitializedOnce = 1;
389void set_eyehalf(
const double eyehalf,
const double eyehalfangle) {
393 viewer->eyehalf = eyehalf;
394 viewer->eyehalfangle = eyehalfangle;
397void fwl_set_viewer_type0(X3D_Viewer *
viewer,
const int type) {
398 ttglobal tg = gglobal();
401 tg->Mainloop.CTRL = FALSE;
422 case VIEWER_TURNTABLE:
429 case VIEWER_SPHERICAL:
433 if(tg->Mainloop.CTRL){
434 tg->Mainloop.CTRL = FALSE;
436 tg->Mainloop.CTRL = TRUE;
448 if(tg->Mainloop.CTRL){
449 tg->Mainloop.CTRL = FALSE;
452 tg->Mainloop.CTRL = TRUE;
474 ConsoleMessage (
"Viewer type %d is not supported. See Viewer.h.\n", type);
475 viewer->type = VIEWER_NONE;
484 if (vectorSize(getActiveBindableStacks(tg)->navigation) >0)
485 if (
viewer->oktypes[type]==FALSE) {
490 if(1) viewer_init(
viewer,type);
492void fwl_set_viewer_type(
const int type) {
495 fwl_set_viewer_type0(
viewer, type);
501#define VIEWER_STRING(type) ( \
502 type == VIEWER_NONE ? "NONE" : ( \
503 type == VIEWER_EXAMINE ? "EXAMINE" : ( \
504 type == VIEWER_WALK ? "WALK" : ( \
505 type == VIEWER_EXFLY ? "EXFLY" : ( \
506 type == VIEWER_SPHERICAL ? "SPHERICAL" : (\
507 type == VIEWER_TURNTABLE ? "TURNTABLE" : (\
508 type == VIEWER_FLY ? "FLY" : "UNKNOWN"))))))
512#define strcasecmp _stricmp
519 {
"NONE",VIEWER_NONE},
520 {
"WALK",VIEWER_WALK},
522 {
"EXAMINE",VIEWER_EXAMINE},
523 {
"SPHERICAL",VIEWER_SPHERICAL},
524 {
"TURNTABLE",VIEWER_TURNTABLE},
525 {
"EXPLORE",VIEWER_EXPLORE},
526 {
"LOOKAT",VIEWER_LOOKAT},
527 {
"YAWZ",VIEWER_YAWZ},
529 {
"YAWPITCH",VIEWER_YAWPITCH},
530 {
"ROLL",VIEWER_ROLL},
531 {
"DIST",VIEWER_DIST},
533 {
"ZOOM",VIEWER_ZOOM},
536char * lookup_navmodestring(
int navmode){
549 }
while(navmodes[i].
key);
550 if(!retval) retval =
"NONE";
553int lookup_navmode(
char *cmode){
561 if(!strcasecmp(nm->key,cmode)){
566 }
while(navmodes[i].
key);
569char* fwl_getNavModeStr()
573 return lookup_navmodestring(
viewer->type);
581int fwl_setNavMode(
char *mode){
582 int imode = lookup_navmode(mode);
583 fwl_set_viewer_type(imode);
589void resolve_pos20(X3D_Viewer *
viewer) {
591 struct point_XYZ rot, z_axis = { .x=0, .y=0, .z=1 };
594 X3D_Viewer_Examine *examine = &
viewer->examine;
596 quaternion_inverse(&q_inv, &(
viewer->Quat));
597 quaternion_rotation(&rot, &q_inv, &z_axis);
599 (examine->Origin).x = (
viewer->Pos).x -
viewer->Dist * rot.x;
600 (examine->Origin).y = (
viewer->Pos).y -
viewer->Dist * rot.y;
601 (examine->Origin).z = (
viewer->Pos).z -
viewer->Dist * rot.z;
603void resolve_pos2(X3D_Viewer *
viewer) {
610 double cosine, sine, ulen, vlen, scale, dot, angle;
614 ulen = sqrt(vecdot(V1,V1));
615 vlen = sqrt(vecdot(V2,V2));
617 if( APPROX(scale, 0.0) )
619 rotaxis->y = rotaxis->z = 0.0;
625 veccross(&cross,*V1,*V2);
626 sine = sqrt(vecdot(&cross,&cross))/scale;
628 angle = atan2(sine,cosine);
629 vecnormal(rotaxis,&cross);
632double vecangle2d(
double* v1,
double* v2,
double* rotaxis) {
634 double2pointxyz(&V1,v1);
635 double2pointxyz(&V2,v2);
636 double angle = vecangle2(&V1,&V2,&rotax);
637 pointxyz2double(rotaxis,&rotax);
640void avatar2BoundViewpointVerticalAvatar(GLDOUBLE *matA2BVVA, GLDOUBLE *matBVVA2A)
651 viewer_fetch_user_offsets0(
viewer);
652 pointxyz2double(pp,&
viewer->Up);
653 vecscaled(pp,pp,-1.0);
654 double2pointxyz(&downvec,pp);
656 quaternion_rotation(&tilted, &
viewer->Quat, &downvec);
658 matrotate2v(matA2BVVA,downvec,tilted);
659 matrotate2v(matBVVA2A,tilted,downvec);
665void viewer_level_to_bound()
717 viewer_fetch_user_offsets0(
viewer);
718 pointxyz2double(pp,&
viewer->Up);
719 vecscaled(pp,pp,-1.0);
720 double2pointxyz(&downvec,pp);
724 quaternion_rotation(&tilted, &
Quat, &downvec);
726 angle = vecangle2(&downvec,&tilted,&rotaxis);
727 if( APPROX(angle,0.0) )
return;
728 vrmlrot_to_quaternion(&q, rotaxis.x, rotaxis.y, rotaxis.z, -angle );
729 quaternion_normalize(&q);
730 quaternion_multiply(&(
viewer->Quat), &q, &
Quat);
731 quaternion_normalize(&(
viewer->Quat));
733 viewer_update_user_offsets0(
viewer);
736void viewer_togl(
double fieldofview)
768 set_stereo_offset0();
774 quaternion_togl(&
viewer->Quat);
787void getCurrentPosInModelB(){
789 double mod[16], modi[16], pp[3];
792 vecsetd(pp,0.0,0.0,0.0);
793 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
794 matinverseAFFINE(modi,mod);
795 transformAFFINEd(pp,pp,modi);
796 double2pointxyz(&
viewer->currentPosInModel,pp);
799double quadratic(
double x,
double a,
double b,
double c)
802 return x*x*a + x*b + c;
804double xsign_quadratic(
double x,
double a,
double b,
double c)
809 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
811 return xSign*quadratic(x,a,b,c);
813double cubic(
double x,
double a,
double b,
double c,
double d){
814 return x*x*x*a + x*x*b + x*c + d;
816double xsign_cubic(
double x,
double a,
double b,
double c,
double d)
821 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
823 return xSign*cubic(x,a,b,c,d);
825double quartic(
double x,
double a,
double b,
double c,
double d,
double e){
826 return x*x*x*x*a + x*x*x*b + x*x*c + x*d +e;
828double xsign_quartic(
double x,
double a,
double b,
double c,
double d,
double e)
834 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
836 return xSign*quartic(x,a,b,c,d,e);
838double quintic(
double x,
double a,
double b,
double c,
double d,
double e,
double f){
839 return x*x*x*x*x*a + x*x*x*x*b + x*x*x*c + x*x*d +x*e + f;
841double xsign_quintic(
double x,
double a,
double b,
double c,
double d,
double e,
double f)
847 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
849 return xSign*quintic(x,a,b,c,d,e,f);
851static void handle_walk(
const int mev,
const unsigned int button,
const float x,
const float y) {
861 X3D_Viewer_Walk *walk;
869 if (mev == ButtonPress ) {
872 }
else if (mev == MotionNotify) {
883 walk->ZD = -xsign_quadratic(y - walk->SY,.05,5.0,0.0)*
viewer->speed;
884 walk->RD = xsign_quadratic(x - walk->SX,0.1,0.5,0.0);
887 }
else if (button == 3) {
888 walk->XD = xsign_quadratic(x - walk->SX,5.0,10.0,0.0)*
viewer->speed;
889 walk->YD = xsign_quadratic(y - walk->SY,5.0,10.0,0.0)*
viewer->speed;
893 }
else if (mev == ButtonRelease) {
897 }
else if (button == 3) {
906 norm(
const Quaternion *quat)
917void handle_examine(
const int mev,
const unsigned int button,
float x,
float y) {
918 Quaternion q, q_i, arc;
923 X3D_Viewer_Examine *examine;
926 examine = &
viewer->examine;
929 if (mev == ButtonPress) {
940 xy2qua(&(examine->SQuat), x, y);
941 quaternion_set(&(examine->OQuat), &(
viewer->Quat));
956 }
else if (mev == MotionNotify) {
959 squat_norm = norm(&(examine->SQuat));
961 if (APPROX(squat_norm, 0)) {
962 fprintf(stderr,
"Viewer handle_examine: mouse event DRAG - missed press\n");
964 xy2qua(&(examine->SQuat), x, y);
966 quaternion_set(&(examine->OQuat), &(
viewer->Quat));
971 quaternion_inverse(&q_i, &(examine->SQuat));
972 quaternion_multiply(&arc, &q, &q_i);
976 quaternion_multiply(&(
viewer->Quat), &arc, &(examine->OQuat));
989 quaternion_inverse(&q_i, &(
viewer->Quat));
990 quaternion_rotation(&(
viewer->Pos), &q_i, &pp);
994 viewer->Pos.x += (examine->Origin).x;
995 viewer->Pos.y += (examine->Origin).y;
996 viewer->Pos.z += (examine->Origin).z;
1004double get_viewer_dist(){
1005 return Viewer()->Dist;
1008void handle_dist(
const int mev,
const unsigned int button,
float x,
float y) {
1018 X3D_Viewer_Examine *examine;
1021 examine = &
viewer->examine;
1027 if (mev == ButtonPress) {
1031 examine->ODist = max(0.1,
viewer->Dist);
1033 }
else if (mev == MotionNotify) {
1037 viewer->Dist = examine->ODist * exp(4.0 * (examine->SY - yy));
1039 viewer->Dist = (0 != yy) ? examine->ODist * examine->SY / yy : 0;
1045 quaternion_inverse(&q_i, &(
viewer->Quat));
1046 quaternion_rotation(&(
viewer->Pos), &q_i, &pp);
1050 viewer->Pos.x += (examine->Origin).x;
1051 viewer->Pos.y += (examine->Origin).y;
1052 viewer->Pos.z += (examine->Origin).z;
1058double display_screenRatio();
1059double dclamp(
double fval,
double fstart,
double fend) {
1061 fret = fval > fend? fend : fval;
1062 fret = fret < fstart ? fstart : fret;
1065void handle_turntable(
const int mev,
const unsigned int button,
float x,
float y) {
1070 double frameRateAdjustment;
1071 X3D_Viewer_Spherical *ypz;
1073 ttglobal tg = gglobal();
1077 if(APPROX(
viewer->Dist,0.0)){
1082 if( tg->Mainloop.BrowserFPS > 0)
1083 frameRateAdjustment = 20.0 / tg->Mainloop.BrowserFPS;
1085 frameRateAdjustment = 1.0;
1088 if (mev == ButtonPress) {
1089 if (button == 1 || button == 3) {
1094 else if (mev == MotionNotify)
1096 Quaternion qyaw, qpitch;
1097 double dyaw, dpitch;
1103 if (button == 1 || button == 3){
1108 dd.x = dd.y = 0.0; dd.z =
viewer->Dist;
1109 xx.y = xx.z = 0.0; xx.x = 1.0;
1111 quaternion_inverse(&quat,&quat);
1112 quaternion_rotation(&ddr, &quat, &dd);
1113 quaternion_rotation(&xxr, &quat, &xx);
1118 vecnormal(&pp, &pp);
1119 pitch = -(acos(dclamp(vecdot(&pp, &yaxis),-1.0,1.0)) - PI*.5);
1122 if(fabs(pitch) > PI*.25){
1124 vecnormal(&xxr,&xxr);
1125 yaw = atan2(xxr.z,xxr.x);
1132 dist = veclength(pp2);
1133 if(dist > 0.0 && fabs(pitch) < (PI *.5 - .001)){
1134 vecnormal(&pp2,&pp2);
1135 yaw = -atan2(pp2.x, pp2.z);
1141 dyaw = -(ypz->x - x) *
viewer->fieldofview*PI / 180.0*
viewer->fovZoom * display_screenRatio();
1142 dpitch = (ypz->y - y) *
viewer->fieldofview*PI / 180.0*
viewer->fovZoom;
1145 }
else if (button == 3) {
1149 ypz->ypz[1] = -xsign_quadratic(y - ypz->y,100.0,10.0,0.0)*
viewer->speed * frameRateAdjustment *.15;
1152 if (button == 1 || button == 3)
1155 vrmlrot_to_quaternion(&qyaw, 0.0, 1.0, 0.0, yaw);
1156 vrmlrot_to_quaternion(&qpitch, 1.0, 0.0, 0.0, pitch);
1157 quaternion_multiply(&quat, &qpitch, &qyaw);
1158 quaternion_normalize(&quat);
1160 quaternion_set(&(
viewer->Quat), &quat);
1162 quaternion_inverse(&quat, &quat);
1166 quaternion_rotation(&(
viewer->Pos), &quat, &pp);
1174 }
else if(mev == ButtonRelease) {
1182void handle_spherical(
const int mev,
const unsigned int button,
float x,
float y) {
1185 Quaternion qyaw, qpitch;
1188 X3D_Viewer_Spherical *ypz;
1189 ttglobal tg = gglobal();
1193 if(ibutton == 1 && tg->Mainloop.CTRL) ibutton = 3;
1195 if (mev == ButtonPress) {
1196 if (ibutton == 1 || ibutton == 3) {
1200 }
else if (mev == MotionNotify) {
1209 dd.x = dd.y = 0.0; dd.z = 1.0;
1211 quaternion_inverse(&quat,&quat);
1212 quaternion_rotation(&ddr, &quat, &dd);
1213 yaw = -atan2(ddr.x,ddr.z);
1214 pitch = -(acos(vecdot(&ddr, &yaxis)) - PI*.5);
1217 dyaw = (ypz->x - x) *
viewer->fieldofview*PI/180.0*
viewer->fovZoom * display_screenRatio();
1218 dpitch = -(ypz->y - y) *
viewer->fieldofview*PI/180.0*
viewer->fovZoom;
1223 vrmlrot_to_quaternion(&qyaw, 0.0, 1.0, 0.0, yaw);
1224 vrmlrot_to_quaternion(&qpitch, 1.0, 0.0, 0.0, pitch);
1225 quaternion_multiply(&quat, &qpitch, &qyaw);
1226 quaternion_normalize(&quat);
1228 quaternion_set(&(
viewer->Quat), &quat);
1230 }
else if (ibutton == 3) {
1232 d = -(y - ypz->y)*.5;
1236 if(ibutton == 1 || ibutton == 3){
1252void viewer_lastQ_set(Quaternion *lastQ);
1253void handle_fly2(
const int mev,
const unsigned int button,
float x,
float y) {
1258 X3D_Viewer_InPlane *inplane;
1260 inplane = &
viewer->inplane;
1262 if (mev == ButtonPress) {
1268 }
else if (mev == MotionNotify) {
1271 }
else if (mev == ButtonRelease ) {
1303void show_pin_point(
double *pin_point){
1304 struct X3D_Node *boundvp = (
struct X3D_Node*)getActiveLayerBoundViewpoint();
1306 switch(boundvp->_nodeType){
1307 case NODE_Viewpoint: {
1309 veccopyd(vp->_pin_point.c,pin_point);
1310 vp->_show_pin_point = TRUE; }
1312 case NODE_OrthoViewpoint: {
1314 veccopyd(vp->_pin_point.c,pin_point);
1315 vp->_show_pin_point = TRUE; }
1317 case NODE_GeoViewpoint: {
1319 veccopyd(vp->_pin_point.c,pin_point);
1320 vp->_show_pin_point = TRUE; }
1326void unshow_pin_point(){
1327 struct X3D_Node *boundvp = (
struct X3D_Node*)getActiveLayerBoundViewpoint();
1329 switch(boundvp->_nodeType){
1330 case NODE_Viewpoint: {
1332 vp->_show_pin_point = FALSE; }
1334 case NODE_OrthoViewpoint: {
1336 vp->_show_pin_point = FALSE; }
1338 case NODE_GeoViewpoint: {
1340 vp->_show_pin_point = FALSE; }
1346double * get_touch_pin_point();
1347double get_touch_hitPointDist();
1348double * get_touch_ray();
1350void quaternion_split_tilt_yaw(Quaternion *Qyaw, Quaternion *Qtilt, Quaternion *Qfull,
double *up){
1356 double down[3], tilted[3], rotaxis[3],angle;
1357 Quaternion Qtilt_inverse, Qfull_inverse, Qyaw_inverse;
1358 vecscaled(down,up,-1.0);
1360 quaternion_inverse(&Qfull_inverse,Qfull);
1361 quaternion_rotationd(tilted, &Qfull_inverse, down);
1363 angle = vecangle2d(down,tilted,rotaxis);
1365 vrmlrot_to_quaternion(Qtilt, rotaxis[0], rotaxis[1], rotaxis[2], angle );
1366 quaternion_normalize(Qtilt);
1367 quaternion_inverse(&Qtilt_inverse,Qtilt);
1368 quaternion_multiply(Qyaw,&Qtilt_inverse,Qfull);
1370 quaternion_multiply(&Qtest,Qtilt,Qyaw);
1375void handle_pan(
const int mev,
const unsigned int button,
float x,
float y) {
1387 ttglobal tg = gglobal();
1390 double *pin_point, *ray, d3[3], pp[3], angle, Dpos[3];
1391 struct point_XYZ downvec, tilted, rotaxis;
1392 Quaternion Qfull, Qfull_inverse, Qtilt, Qyaw;
1395 viewer_fetch_user_offsets0(
viewer);
1399 quaternion_inverse(&Qfull_inverse,&Qfull);
1401 quaternion_split_tilt_yaw(&Qyaw,&Qtilt,&Qfull,pointxyz2double(dtemp,&
viewer->Up));
1402 pointxyz2double(Dpos,&
viewer->Pos);
1404 X3D_Viewer_Spherical *ypz;
1411 pin_point = get_touch_pin_point();
1412 ray = get_touch_ray();
1413 if(get_touch_hitPointDist() > 0.0 && pin_point && ray) {
1415 double v[3], N[3], dd, trackpoint[3];
1416 quaternion_rotationd(ray,&Qfull_inverse,ray);
1417 quaternion_rotationd(&ray[3],&Qfull_inverse,&ray[3]);
1418 vecaddd(ray,ray,Dpos);
1419 vecaddd(&ray[3],&ray[3],Dpos);
1420 vecdifd(v,&ray[3],ray);
1422 vecsetd(N,0.0,1.0,0.0);
1424 dd = -vecdotd(N,&ray[3]);
1425 if (!line_intersect_planed_3d(ray, v, N, dd, trackpoint, NULL))
1427 veccopyd(
viewer->pan.pin_point_planed,trackpoint);
1431 show_pin_point(trackpoint);
1439 pin_point = get_touch_pin_point();
1440 ray = get_touch_ray();
1443 if(get_touch_hitPointDist() > 0.0 && pin_point && ray) {
1445 double v[3], N[3], dd, delta[3], trackpoint[3];
1447 double ddelta[3],dpos[3];
1448 quaternion_rotationd(ray,&Qfull_inverse,ray);
1449 quaternion_rotationd(&ray[3],&Qfull_inverse,&ray[3]);
1450 vecaddd(ray,ray,Dpos);
1451 vecaddd(&ray[3],&ray[3],Dpos);
1453 vecdifd(v,&ray[3],ray);
1455 vecsetd(N,0.0,1.0,0.0);
1456 dd = -vecdotd(N,
viewer->pan.pin_point_planed);
1457 if (!line_intersect_planed_3d(ray, v, N, dd, trackpoint, NULL))
1459 vecdifd(delta,
viewer->pan.pin_point_planed,trackpoint);
1461 vecaddd(dpos,Dpos,delta);
1462 double2pointxyz(&
viewer->Pos,dpos);
1465 }
else if(button == 4 || button == 5){
1467 ray = get_touch_ray();
1468 if(get_touch_hitPointDist() > 0.0 && ray) {
1469 double ddelta[3],dpos[3],vv[3];
1470 vecdifd(vv,&ray[3],ray);
1472 vecscaled(ddelta,vv, -.2);
1474 vecscaled(ddelta,vv, .25);
1475 pointxyz2double(dpos,&
viewer->Pos);
1476 quaternion_rotationd(ddelta,&Qfull_inverse,ddelta);
1477 vecaddd(dpos,dpos,ddelta);
1478 double2pointxyz(&
viewer->Pos,dpos);
1480 }
else if(button == 2){
1494 if(get_touch_hitPointDist() > 0.0 && pin_point ) {
1495 Quaternion qyaw, qpitch, qttable;
1496 double dyaw, dpitch, v[3], v2[3], pin[3],dpos[3], xaxis[3], yaxis[3], ddr[3], xx[3],pp[3],pp2[3],delta[3],vlength;
1498 dyaw = dpitch = 0.0;
1501 pointxyz2double(yaxis,&
viewer->Up);
1502 ray = get_touch_ray();
1503 pointxyz2double(dpos,&
viewer->Pos);
1505 veccopyd(pin,
viewer->pan.pin_point_planed);
1507 vecdifd(v,pin,dpos);
1508 vlength = veclengthd(v);
1510 vecsetd(xaxis,1.0,0.0,0.0);
1511 quaternion_rotationd(xaxis,&Qfull_inverse,xaxis);
1516 dyaw = -(ypz->x - x) * .5 * PI;
1517 dpitch = (ypz->y - y) * .5 * PI;
1519 vrmlrot_to_quaternion(&qyaw, 0.0, 1.0, 0.0, dyaw);
1520 vrmlrot_to_quaternion(&qpitch, xaxis[0],xaxis[1],xaxis[2], dpitch);
1521 quaternion_multiply(&qttable, &qpitch, &qyaw);
1522 quaternion_normalize(&qttable);
1524 quaternion_multiply(&
viewer->Quat,&
viewer->Quat,&qttable);
1527 quaternion_rotationd(v2,&qttable,v);
1531 vecdifd(delta,v2,v);
1533 vecaddd(dpos,dpos,delta);
1535 double2pointxyz(&
viewer->Pos,dpos);
1546 viewer_update_user_offsets0(
viewer);
1552void handle_zoom(
const int mev,
const unsigned int button,
float x,
float y) {
1557void handle_geo_turntable(
const int mev,
const unsigned int button,
float x,
float y) {
1558printf(
"geo_ttable ");
1561void increment_pos0(
struct point_XYZ *vec);
1562void handle_tick_fly2(
double dtime) {
1564 X3D_Viewer_InPlane *inplane;
1565 double frameRateAdjustment, xx, yy, yyy, zz, rot, a,b,c;
1571 inplane = &
viewer->inplane;
1573 frameRateAdjustment = dtime * 20.0;
1576 xx = inplane->xx - inplane->x;
1577 yy = inplane->yy - inplane->y;
1584 zz = -xsign_cubic(yyy,a,b,c,0.0)*
viewer->speed * dtime;
1598 rot = xsign_quadratic(xx,2.0,10.0,0.0)*dtime;
1600 memcpy(&q,&
viewer->Quat,
sizeof(Quaternion));
1601 vrmlrot_to_quaternion (&nq,0.0,1.0,0.0,0.4*rot);
1602 viewer_lastQ_set(&nq);
1603 quaternion_multiply(&(
viewer->Quat), &nq, &q);
1605 increment_pos0(&xyz);
1610void handle_lookat(
const int mev,
const unsigned int button,
float x,
float y) {
1627 if(
viewer->type == VIEWER_LOOKAT)
1628 fwl_set_viewer_type(VIEWER_LOOKAT);
1629 if(
viewer->type == VIEWER_EXPLORE)
1630 fwl_set_viewer_type(VIEWER_EXPLORE);
1637void handle_tick_lookat() {
1641 switch(
viewer->LookatMode){
1651void handle_explore(
const int mev,
const unsigned int button,
float x,
float y) {
1658 ttglobal tg = gglobal();
1660 ctrl = tg->Mainloop.CTRL;
1665 handle_lookat(mev,button,x,y);
1668 if(APPROX(
viewer->Dist,0.0)){
1670 handle_spherical(mev,button,x,y);
1673 handle_turntable(mev, button, x, y);
1676void handle_tplane(
const int mev,
const unsigned int button,
float x,
float y) {
1683 X3D_Viewer_InPlane *inplane;
1685 inplane = &
viewer->inplane;
1688 if (mev == ButtonPress) {
1692 }
else if (mev == MotionNotify) {
1695 }
else if(mev == ButtonRelease){
1701void handle_tick_tplane(
double dtime){
1703 X3D_Viewer_InPlane *inplane;
1707 inplane = &
viewer->inplane;
1709 double xxx,yyy,a,b,c,d,e;
1710 xxx = (inplane->xx - inplane->x)*1.0;
1711 yyy = (inplane->yy - inplane->y)*1.0;
1716 pp.x = xsign_cubic(xxx,a,b,c,0.0) * dtime *
viewer->speed;
1717 pp.y = xsign_cubic(yyy,a,b,c,0.0) * dtime *
viewer->speed;
1730 increment_pos0(&pp);
1734void handle_rtplane(
const int mev,
const unsigned int button,
float x,
float y) {
1741 X3D_Viewer_InPlane *inplane;
1743 double xx,yy, frameRateAdjustment;
1744 ttglobal tg = gglobal();
1746 inplane = &
viewer->inplane;
1748 if( tg->Mainloop.BrowserFPS > 0)
1749 frameRateAdjustment = 20.0 / tg->Mainloop.BrowserFPS;
1751 frameRateAdjustment = 1.0;
1753 if (mev == ButtonPress) {
1756 }
else if (mev == MotionNotify) {
1758 inplane->xx = xsign_quadratic(x - inplane->x,0.1,0.5,0.0)*frameRateAdjustment;
1759 inplane->yy = xsign_quadratic(y - inplane->y,0.1,0.5,0.0)*frameRateAdjustment;
1761 }
else if (mev == ButtonRelease) {
1769void handle_tick_rplane(
double dtime){
1771 X3D_Viewer_InPlane *inplane;
1776 inplane = &
viewer->inplane;
1778 roll = xsign_quadratic(inplane->xx - inplane->x,2.0,2.0,0.0)*dtime;
1779 vrmlrot_to_quaternion (&quatr,0.0,0.0,1.0,roll);
1780 quaternion_multiply(&(
viewer->Quat), &quatr, &(
viewer->Quat));
1781 quaternion_normalize(&(
viewer->Quat));
1785void handle_tick_tilt(
double dtime) {
1787 X3D_Viewer_InPlane *inplane;
1792 inplane = &
viewer->inplane;
1794 yaw = xsign_quadratic(inplane->xx - inplane->x,2.0,2.0,0.0)*dtime;
1795 vrmlrot_to_quaternion (&quatt,0.0,1.0,0.0,yaw);
1796 quaternion_multiply(&(
viewer->Quat), &quatt, &(
viewer->Quat));
1797 pitch = -xsign_quadratic(inplane->yy - inplane->y,2.0,2.0,0.0)*dtime;
1798 vrmlrot_to_quaternion (&quatt,1.0,0.0,0.0,pitch);
1799 quaternion_multiply(&(
viewer->Quat), &quatt, &(
viewer->Quat));
1800 quaternion_normalize(&(
viewer->Quat));
1807void handle0(
const int mev,
const unsigned int button,
const float x,
const float yup)
1815 case VIEWER_SPHERICAL:
1816 case VIEWER_TURNTABLE:
1817 case VIEWER_EXAMINE:
1821 viewer_fetch_user_offsets0(
viewer);
break;
1823 viewer_fetch_LCS(
viewer);
break;
1834 case VIEWER_EXAMINE:
1835 handle_examine(mev, button, ((
float) x), ((
float) yup));
1838 handle_walk(mev, button, ((
float) x), ((
float) yup));
1843 handle_fly2(mev, button, ((
float) x), ((
float) yup));
1856 case VIEWER_SPHERICAL:
1857 handle_spherical(mev,button,((
float) x),((
float)yup));
1859 case VIEWER_TURNTABLE:
1860 handle_turntable(mev, button, ((
float)x), ((
float)yup));
1863 handle_lookat(mev, button, ((
float)x), ((
float)yup));
1865 case VIEWER_EXPLORE:
1866 handle_explore(mev, button, ((
float)x), ((
float)yup));
1869 handle_dist(mev,button,(
float)x,(
float)yup);
1872 handle_pan(mev,button,(
float)x,(
float)yup);
1875 handle_zoom(mev,button,(
float)x,(
float)yup);
1883 case VIEWER_SPHERICAL:
1884 case VIEWER_TURNTABLE:
1885 case VIEWER_EXAMINE:
1889 viewer_update_user_offsets0(
viewer);
break;
1891 viewer_update_LCS(
viewer);
break;
1896#define FLYREMAP {{'a',NUM0},{'z',NUMDEC},{'j',LEFT_KEY},{'l',RIGHT_KEY},{'p',UP_KEY},{';',DOWN_KEY},{'8',NUM8},{'k',NUM2},{'u',NUM4},{'o',NUM6 },{'7',NUM7},{'9',NUM9}}
1902Key FLYREMAP2 [] = {{
'a',NUM0},{
'z',NUMDEC},{
'j',LEFT_KEY},{
'l',RIGHT_KEY},{
'p',UP_KEY},{
';',DOWN_KEY},{
'8',NUM8},{
'k',NUM2},{
'u',NUM4},{
'o',NUM6 },{
'7',NUM7},{
'9',NUM9}};
1903int FLYREMAP2SIZE = 12;
1904Key FLYCHORDREMAP [] = {
1905{
'j',LEFT_KEY},{
'l',RIGHT_KEY},{
'p',UP_KEY},{
';',DOWN_KEY}
1907int arrowkeys [] = {LEFT_KEY,RIGHT_KEY,UP_KEY,DOWN_KEY};
1915int indexArrowkey(
int key){
1919 if(
key == arrowkeys[i]) iret = i;
1935 FLY_ROLL_COUNTERCLOCKWISE,
1938Key fly_normalkeys [] = {
1943 {
'a',FLY_Z_FORWARD},
1944 {
'z',FLY_Z_REVERSE},
1946 {
'8',FLY_PITCH_DOWN},
1948 {
'o',FLY_YAW_RIGHT},
1949 {
'7',FLY_ROLL_COUNTERCLOCKWISE},
1950 {
'9',FLY_ROLL_CLOCKWISE},
1954char *chordnames [] = {
"YAWZ",
"YAWPITCH",
"ROLL",
"XY"};
1961 {CHORD_YAWZ, {{FLY_YAW_LEFT,LEFT_KEY},{FLY_YAW_RIGHT,RIGHT_KEY},{FLY_Z_FORWARD,UP_KEY},{FLY_Z_REVERSE,DOWN_KEY}}},
1962 {CHORD_YAWPITCH,{{FLY_YAW_LEFT,LEFT_KEY},{FLY_YAW_RIGHT,RIGHT_KEY},{FLY_PITCH_UP,UP_KEY},{FLY_PITCH_DOWN,DOWN_KEY}}},
1963 {CHORD_ROLL, {{FLY_ROLL_COUNTERCLOCKWISE,LEFT_KEY},{FLY_ROLL_CLOCKWISE,RIGHT_KEY},{FLY_ROLL_COUNTERCLOCKWISE,UP_KEY},{FLY_ROLL_CLOCKWISE,DOWN_KEY}}},
1964 {CHORD_XY, {{FLY_X_LEFT,LEFT_KEY},{FLY_X_RIGHT,RIGHT_KEY},{FLY_Y_UP,UP_KEY},{FLY_Y_DOWN,DOWN_KEY}}},
1967int viewer_getKeyChord(){
1968 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
1971void viewer_setKeyChord(
int chord){
1973 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
1975 if(chord1 > 3) chord1 = 0;
1976 if(chord1 < 0) chord1 = 3;
1977 p->keychord = chord1;
1979char *fwl_getKeyChord(){
1980 return chordnames[viewer_getKeyChord()];
1983int fwl_setKeyChord(
char *chordname){
1987 if(!strcasecmp(chordname,chordnames[i])){
1988 viewer_setKeyChord(i);
1995int viewer_getDragChord(){
1996 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
1997 return p->dragchord;
1999void viewer_setDragChord(
int chord){
2000 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2001 p->dragchord = chord;
2003void viewer_setNextDragChord(){
2004 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2005 p->dragchord = p->dragchord == CHORD_XY ? CHORD_YAWZ : p->dragchord + 1;
2007char *fwl_getDragChord(){
2008 return chordnames[viewer_getDragChord()];
2010int fwl_setDragChord(
char *chordname){
2014 if(!strcasecmp(chordname,chordnames[i])){
2015 viewer_setDragChord(i);
2025int lookup_fly_arrow(
int key){
2028 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2029 int idxarrow, idxnormal;
2031 idxarrow = indexArrowkey(
key);
2034 idxnormal = FLYCHORDREMAP2[p->keychord].arrows[idxarrow].key;
2036 iret = fly_normalkeys[idxnormal].key;
2041char lookup_fly_extended(
int key){
2044 Key ps[KEYS_HANDLED] = FLYREMAP;
2045 for(i=0;i<KEYS_HANDLED;i++){
2053char lookup_fly_key(
int key){
2056 kp = lookup_fly_arrow(
key);
2058 kp = lookup_fly_extended(
key);
2061static struct flykey_lookup_type {
2067} flykey_lookup [] = {
2068 {
'j', 0, 0, -1, FLY_X_LEFT},
2069 {
'l', 0, 0, 1, FLY_X_RIGHT},
2070 {
';', 0, 1, -1, FLY_Y_DOWN},
2071 {
'p', 0, 1, 1, FLY_Y_UP,},
2072 {
'a', 0, 2, -1, FLY_Z_FORWARD},
2073 {
'z', 0, 2, 1, FLY_Z_REVERSE},
2075 {
'k', 1, 0, -1, FLY_YAW_LEFT},
2076 {
'8', 1, 0, 1, FLY_YAW_RIGHT},
2077 {
'u', 1, 1, -1, FLY_PITCH_UP},
2078 {
'o', 1, 1, 1, FLY_PITCH_DOWN},
2079 {
'7', 1, 2, -1, FLY_ROLL_COUNTERCLOCKWISE},
2080 {
'9', 1, 2, 1, FLY_ROLL_CLOCKWISE}
2084struct flykey_lookup_type *getFlyIndex(
char key){
2085 struct flykey_lookup_type *flykey;
2088 for(index=0;index<KEYS_HANDLED;index++){
2089 if(
key == flykey_lookup[index].
key )
break;
2092 flykey = &flykey_lookup[index];
2095int isFlyKey(
char key){
2097 index = indexArrowkey(
key);
2099 for(i=0;i<KEYS_HANDLED;i++)
2100 if(
key == flykey_lookup[i].
key ){
2104 return index > -1 ? 1 : 0;
2106void handle_key(
const char key,
double keytime)
2110 X3D_Viewer_Fly *fly;
2111 struct flykey_lookup_type *flykey;
2116 _key = (char) tolower((
int)
key);
2117 if(!isFlyKey(_key)){
2122 flykey = getFlyIndex(_key);
2124 if(flykey->motion > -1 && flykey->motion < 2 && flykey->axis > -1 && flykey->axis < 3){
2125 fly->down[flykey->motion][flykey->axis].direction = flykey->sign;
2126 fly->down[flykey->motion][flykey->axis].epoch = keytime;
2127 fly->down[flykey->motion][flykey->axis].era = keytime;
2128 fly->down[flykey->motion][flykey->axis].once = 1;
2134void handle_keyrelease(
const char key,
double keytime)
2138 X3D_Viewer_Fly *fly;
2139 struct flykey_lookup_type *flykey;
2146 _key = (char) tolower((
int)
key);
2147 if(!isFlyKey(_key))
return;
2148 flykey = getFlyIndex(_key);
2150 if(flykey->motion > -1 && flykey->motion < 2 && flykey->axis > -1 && flykey->axis < 3){
2151 int *ndown = &fly->ndown[flykey->motion][flykey->axis];
2154 fly->wasDown[flykey->motion][flykey->axis][*ndown].direction = fly->down[flykey->motion][flykey->axis].direction;
2155 fly->wasDown[flykey->motion][flykey->axis][*ndown].epoch = keytime - fly->down[flykey->motion][flykey->axis].epoch;
2156 fly->wasDown[flykey->motion][flykey->axis][*ndown].era = keytime - fly->down[flykey->motion][flykey->axis].era;
2157 fly->wasDown[flykey->motion][flykey->axis][*ndown].once = fly->down[flykey->motion][flykey->axis].once;
2160 fly->down[flykey->motion][flykey->axis].direction = 0;
2172void viewer_lastP_clear()
2174 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2176 p->viewer_lastP.x = p->viewer_lastP.y = p->viewer_lastP.z = 0.0;
2178void viewer_lastQ_set(Quaternion *lastQ)
2180 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2181 quaternion_rotation(&p->viewer_lastP,lastQ,&p->viewer_lastP);
2183void viewer_lastP_add(
struct point_XYZ *vec)
2185 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2188 VECADD(p->viewer_lastP,*vec);
2191 viewer_lastP_clear();
2197 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2199 struct point_XYZ nv = p->viewer_lastP;
2200 vecscale(&nv,&nv,-1.0);
2221static void handle_tick_walk()
2224 X3D_Viewer_Walk *walk;
2225 double frame_rate_adjustment;
2236 frame_rate_adjustment = 10.0 * (TickTime() - lastTime());
2239 pp.x = frame_rate_adjustment * walk->XD;
2240 pp.y = frame_rate_adjustment * walk->YD;
2241 pp.z = frame_rate_adjustment * walk->ZD;
2297 vrmlrot_to_quaternion (&nq,0.0,1.0,0.0,0.4*walk->RD * 2.0 * frame_rate_adjustment);
2298 viewer_lastQ_set(&nq);
2303 quaternion_multiply(&(
viewer->Quat), &q, &nq);
2304 quaternion_normalize(&(
viewer->Quat));
2309 Quaternion qlevel,qplanar;
2313 pointxyz2double(dd,&
viewer->Up);
2314 double2pointxyz(&rotaxis,dd);
2315 vecscaled(dd,dd,-1.0);
2316 double2pointxyz(&down,dd);
2319 quaternion_rotation(&tilted,&q,&down);
2320 angle = vecangle2(&down,&tilted, &rotaxis);
2321 vrmlrot_to_quaternion (&qlevel,rotaxis.x,rotaxis.y,rotaxis.z,-angle);
2323 quaternion_multiply(&qplanar,&qlevel,&q);
2334 viewer_lastP_add(&vec);
2337 quaternion_inverse(&q_i, &qplanar);
2338 quaternion_rotation(&nv, &q_i, &vec);
2341 viewer->VPvelocity.x = nv.x;
viewer->VPvelocity.y = nv.y;
viewer->VPvelocity.z = nv.z;
2359static int negate_pos = TRUE;
2360void viewer_setpose(
double *quat4,
double *vec3){
2368 viewer_fetch_user_offsets0(
viewer);
2370 if(negate_pos) vecnegated(vec,vec);
2371 double2pointxyz(&
viewer->Pos,vec);
2372 double2quat(&
viewer->Quat,quat4);
2373 viewer_update_user_offsets0(
viewer);
2375void viewer_getpose(
double *quat4,
double *vec3){
2383 viewer_fetch_user_offsets0(
viewer);
2384 pointxyz2double(vec3,&
viewer->Pos);
2386 vecnegated(vec3,vec3);
2387 quat2double(quat4,&
viewer->Quat);
2389void viewer_fetch_bindtime_pose0(X3D_Viewer *
viewer, Quaternion *
Quat,
struct point_XYZ *Pos);
2390void viewer_getbindpose(
double *quat4,
double *vec3){
2401 viewer_fetch_bindtime_pose0(
viewer,&quat,&pos);
2402 quat2double(quat4,&quat);
2403 pointxyz2double(vec3,&pos);
2407void viewer_getview(
double *viewMatrix){
2411 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, viewMatrix);
2414void viewer_setview(
double *viewMatrix){
2415 FW_GL_SETDOUBLEV(GL_MODELVIEW_MATRIX, viewMatrix);
2431static void handle_tick_exfly()
2435 char string[STRING_SIZE];
2436 float px,py,pz,q1,q2,q3,q4;
2438 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2443 memset(
string, 0, STRING_SIZE *
sizeof(
char));
2445 if ((p->exfly_in_file = fopen(IN_FILE,
"r")) == NULL) {
2447 "Viewer handle_tick_exfly: could not open %s for read, returning to EXAMINE mode.\nSee the FreeWRL man page for further details on the usage of Fly - External Sensor input mode.\n",
2451 viewer->type = VIEWER_EXAMINE;
2455 rv = fread(
string,
sizeof(
char), IN_FILE_BYTES, p->exfly_in_file);
2456 if (ferror(p->exfly_in_file)) {
2458 "Viewer handle_tick_exfly: error reading from file %s.",
2460 fclose(p->exfly_in_file);
2463 fclose(p->exfly_in_file);
2466 if ((len = strlen(
string)) > 0) {
2467 if(p->exflyMethod == 0)
2470 len = sscanf (
string,
"%f %f %f %f %f %f %f",&px,&py,&pz,
2474 if (len != 7)
return;
2484 }
else if(p->exflyMethod == 1){
2486 static int lastbut = 0;
2488 len = sscanf (
string,
"%d %f %f ",&but,&px,&py);
2489 if (len != 3)
return;
2490 mev = ButtonRelease;
2491 if(but) mev = MotionNotify;
2494 mev = (but==1 || but==4)? ButtonPress : ButtonRelease;
2499 handle_walk(mev,but,px,py);
2520static void handle_tick_fly()
2523 X3D_Viewer_Fly *fly;
2524 Quaternion q_v, nq = { 1, 0, 0, 0 };
2526 double changed = 0.0, time_diff = -1.0;
2533 if (fly->lasttime < 0) {
2534 fly->lasttime = TickTime();
2537 double dtime = TickTime();
2538 time_diff = dtime - fly->lasttime;
2539 if (APPROX(time_diff, 0)) {
2542 fly->lasttime = dtime;
2543 if(time_diff < 0.0)
return;
2550 for (i = 0; i < 3; i++) {
2552 if(!fly->down[0][i].direction){
2553 double dtime = fly->lasttime - fly->down[0][i].epoch;
2555 fly->Velocity[0][i] *= pow(0.04, time_diff);
2558 if(fabs(fly->Velocity[0][i]) < .001){
2559 fly->Velocity[0][i] = 0.0;
2562 if(fly->down[0][i].direction){
2564 fly->Velocity[0][i] += (fly->ndown[0][i]+fly->down[0][i].once)*fly->down[0][i].direction *
viewer->speed * .1 * max(
viewer->Dist,1.0);
2565 fly->down[0][i].once = 0;
2566 fly->ndown[0][i] = 0;
2569 changed += fly->Velocity[0][i];
2582 for (i = 0; i < 3; i++) {
2583 static double radians_per_second = .6;
2584 fly->Velocity[1][i] = 0.0;
2585 if(!fly->down[1][i].direction){
2586 fly->Velocity[1][i] *= pow(0.04, time_diff);
2589 double rps = radians_per_second;
2592 double era = fly->lasttime - fly->down[1][i].era;
2593 fly->Velocity[1][i] += era * fly->down[1][i].direction * rps;
2594 fly->down[1][i].era += era;
2597 if(fly->ndown[1][i]){
2600 double rps = radians_per_second * .33;
2601 for(k=0; k<fly->ndown[1][i]; k++){
2602 double era = fly->wasDown[1][i][k].era;
2603 double pressedEra = fly->wasDown[1][i][k].epoch;
2605 if(pressedEra <= .1)
2608 fly->Velocity[1][i] += era * fly->wasDown[1][i][k].direction * rps;
2610 fly->ndown[1][i] = 0;
2612 if (fabs(fly->Velocity[1][i]) > 0.8) {
2613 fly->Velocity[1][i] /= (fabs(fly->Velocity[1][i]) / 0.8);
2615 changed += fly->Velocity[1][i];
2620 if (APPROX(changed,0.0))
return;
2621 v.x = fly->Velocity[0][0] * time_diff;
2622 v.y = fly->Velocity[0][1] * time_diff;
2623 v.z = fly->Velocity[0][2] * time_diff;
2626 nq.x = fly->Velocity[1][0];
2627 nq.y = fly->Velocity[1][1];
2628 nq.z = fly->Velocity[1][2];
2629 quaternion_normalize(&nq);
2631 quaternion_set(&q_v, &(
viewer->Quat));
2632 quaternion_multiply(&(
viewer->Quat), &nq, &q_v);
2633 quaternion_normalize(&(
viewer->Quat));
2642 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2647 case VIEWER_SPHERICAL:
2648 case VIEWER_TURNTABLE:
2649 viewer_fetch_user_offsets0(
viewer);
break;
2651 viewer_fetch_LCS(
viewer);
break;
2653 dtime = TickTime() - lastTime();
2658 case VIEWER_EXAMINE:
2664 handle_tick_exfly();
2667 switch(p->dragchord){
2668 case CHORD_YAWPITCH:
2669 handle_tick_tilt(dtime);
2672 handle_tick_rplane(dtime);
2675 handle_tick_tplane(dtime);
2679 handle_tick_fly2(dtime);
2697 handle_tick_lookat();
2699 case VIEWER_EXPLORE:
2701 case VIEWER_SPHERICAL:
2704 case VIEWER_TURNTABLE:
2714 case VIEWER_SPHERICAL:
2715 case VIEWER_TURNTABLE:
2716 viewer_update_user_offsets0(
viewer);
break;
2718 viewer_update_LCS(
viewer);
break;
2720 if(
viewer->type != VIEWER_NONE){
2721 viewer_fetch_user_offsets0(
viewer);
2723 viewer_update_user_offsets0(
viewer);
2725 if(0)
if (
viewer->doExamineModeDistanceCalculations) {
2729 CALCULATE_EXAMINE_DISTANCE
2730 p->examineCounter --;
2732 if (p->examineCounter < 0) {
2733 viewer->doExamineModeDistanceCalculations = FALSE;
2734 p->examineCounter = 5;
2753xy2qua(Quaternion *ret,
const double x,
const double y)
2755 double _x = x - 0.5, _y = y - 0.5, _z, dist;
2759 dist = sqrt((_x * _x) + (_y * _y));
2772 quaternion_normalize(ret);
2778void setmask(GLboolean *mask,
int r,
int g,
int b)
2780 mask[0] = (GLboolean)r;
2781 mask[1] = (GLboolean)g;
2782 mask[2] = (GLboolean)b;
2784void Viewer_anaglyph_setSide(
int iside)
2786 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2790 glColorMask(p->acMask[iside][0],p->acMask[iside][1],p->acMask[iside][2],t);
2792void Viewer_anaglyph_clearSides()
2794 glColorMask(1,1,1,1);
2797static char * RGBACM =
"RGBACM";
2798static int indexRGBACM(
int a)
2800 return (
int) (strchr(RGBACM,a)-RGBACM);
2802int getAnaglyphPrimarySide(
int primary,
int iside){
2805 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2806 return (
int)p->acMask[iside][primary];
2809void setAnaglyphPrimarySide(
int primary,
int iside){
2821 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2824 p->acMask[i][primary] = (GLboolean)1;
2826 p->acMask[i][primary] = (GLboolean)0;
2828void setAnaglyphSideColor(
char val,
int iside)
2831 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
2833 viewer->iprog[iside] = indexRGBACM(val);
2834 if(
viewer->iprog[iside] == -1 )
2836 printf (
"warning, command line anaglyph parameter incorrect - was %c need something like RG\n",val);
2837 viewer->iprog[iside] = iside;
2840 switch (
viewer->iprog[iside]) {
2842 setmask(p->acMask[iside],1,0,0);
2845 setmask(p->acMask[iside],0,1,0);
2848 setmask(p->acMask[iside],0,0,1);
2851 setmask(p->acMask[iside],1,1,0);
2854 setmask(p->acMask[iside],0,1,1);
2857 setmask(p->acMask[iside],1,0,1);
2861void fwl_set_AnaglyphParameter(
const char *optArg) {
2866 const char* glasses;
2871 len = (int) strlen(optArg);
2872 if(len !=2 && len != 3)
2874 printf (
"warning, command line anaglyph parameter incorrect - was %s need something like RC or LRN\n",optArg);
2875 glasses =
"RC"; len = 2;
2878 setAnaglyphSideColor(glasses[0],0);
2879 setAnaglyphSideColor(glasses[1],1);
2884 case 'L': iside = 0;
break;
2885 case 'R': iside = 1;
break;
2886 case 'N': iside = 2;
break;
2890 setAnaglyphPrimarySide(i,iside);
2894 viewer->shutterGlasses = 0;
2898 setStereoBufferStyle(1);
2902void fwl_init_Shutter (
void)
2909 ttglobal tg = gglobal();
2912 tg->display.shutterGlasses = 2;
2913 viewer->shutterGlasses = 2;
2914 setStereoBufferStyle(1);
2915 if(
viewer->haveQuadbuffer)
2917 tg->display.shutterGlasses = 1;
2918 viewer->shutterGlasses = 1;
2919 setStereoBufferStyle(0);
2925void fwl_init_SideBySide()
2930 setStereoBufferStyle(1);
2934 viewer->stereoParameter = min(
viewer->stereoParameter,.01);
2936void fwl_init_UpDown()
2941 setStereoBufferStyle(1);
2945 viewer->stereoParameter = min(
viewer->stereoParameter,.01);
2948void clear_shader_table();
2957 clear_shader_table();
2958 setStereoBufferStyle(1);
2963 ttglobal tg = gglobal();
2969 glColorMask(1,1,1,1);
2970 clear_shader_table();
2975 viewer->shutterGlasses = 0;
2978 tg->display.shutterGlasses = 0;
2981void fwl_init_quadrant(){
2983 ttglobal tg = gglobal();
2989void fwl_init_cardboard(){
2991 ttglobal tg = gglobal();
3005static void setStereo(
int type)
3009 gglobal()->Viewer.stereotype = type;
3013 case VIEWER_STEREO_OFF: {;
break;}
3014 case VIEWER_STEREO_SHUTTERGLASSES: {fwl_init_Shutter();
break;}
3015 case VIEWER_STEREO_SIDEBYSIDE: {fwl_init_SideBySide();
break;}
3016 case VIEWER_STEREO_ANAGLYPH: {setAnaglyph();
break;}
3017 case VIEWER_STEREO_UPDOWN: {fwl_init_UpDown();
break;}
3018 case VIEWER_STEREO_CARDBOARD: {fwl_init_cardboard();
break;}
3019 case VIEWER_STEREO_QUADRANT: {fwl_init_quadrant();
break;}
3023void toggleOrSetStereo(
int type)
3031 shut =
viewer->shutterGlasses ? 1 : 0;
3033 if(type != curtype) {
3037 gglobal()->Viewer.stereotype = 0;
3041void fwl_setPickraySide(
int ipreferredSide,
int either){
3044 viewer->dominantEye = ipreferredSide;
3045 viewer->eitherDominantEye = either;
3048void fwl_getPickraySide(
int *ipreferredSide,
int *either){
3051 *ipreferredSide =
viewer->dominantEye ;
3052 *either =
viewer->eitherDominantEye;
3058 if(
viewer->screendist != 0.0)
3080 set_eyehalf(
viewer->eyedist/2.0,atan(
viewer->stereoParameter)*180.0/3.1415926);
3084void viewer_postGLinit_init(
void)
3090 ttglobal tg = gglobal();
3092 rdr_caps = tg->display.rdr_caps;
3095 viewer->haveQuadbuffer = (rdr_caps->quadBuffer== GL_TRUE);
3101 type = VIEWER_STEREO_OFF;
3102 if(
viewer->shutterGlasses ) type = VIEWER_STEREO_SHUTTERGLASSES;
3103 if(
viewer->sidebyside ) type = VIEWER_STEREO_SIDEBYSIDE;
3104 if(
viewer->updown ) type = VIEWER_STEREO_UPDOWN;
3105 if(
viewer->anaglyph ==1 ) type = VIEWER_STEREO_ANAGLYPH;
3106 if(
viewer->cardboard ==1 ) type = VIEWER_STEREO_CARDBOARD;
3107 if(
viewer->quadrant == 1 ) type = VIEWER_STEREO_QUADRANT;
3108 if(type==VIEWER_STEREO_SHUTTERGLASSES)
3112 if (!
viewer->haveQuadbuffer ) {
3113 ConsoleMessage(
"Unable to get quadbuffer stereo visual, switching to flutter mode\n");
3122void fwl_set_StereoParameter (
const char *optArg) {
3128 i = sscanf(optArg,
"%lf",&
viewer->stereoParameter);
3129 if (i==0) printf (
"warning, command line stereo parameter incorrect - was %s\n",optArg);
3130 else updateEyehalf();
3133void fwl_set_EyeDist (
const char *optArg) {
3138 i= sscanf(optArg,
"%lf",&
viewer->eyedist);
3139 if (i==0) printf (
"warning, command line eyedist parameter incorrect - was %s\n",optArg);
3140 else updateEyehalf();
3143void fwl_set_ScreenDist (
const char *optArg) {
3148 i= sscanf(optArg,
"%lf",&
viewer->screendist);
3149 if (i==0) printf (
"warning, command line screendist parameter incorrect - was %s\n",optArg);
3150 else updateEyehalf();
3154void set_stereo_offset0()
3156 double x = 0.0, angle = 0.0;
3160 if (
viewer->iside == 0) {
3163 angle =
viewer->eyehalfangle;
3164 }
else if (
viewer->iside == 1) {
3167 angle = -
viewer->eyehalfangle;
3169 FW_GL_TRANSLATE_D(x, 0.0, 0.0);
3170 FW_GL_ROTATE_D(angle, 0.0, 1.0, 0.0);
3175void viewer_update_user_offsets0(X3D_Viewer *
viewer){
3183 boundvp = getActiveLayerBoundViewpoint();
3185 switch(boundvp->_nodeType){
3186 case NODE_OrthoViewpoint:
3191 quaternion_to_vrmlrot(&
viewer->Quat,&oo[0],&oo[1],&oo[2],&oo[3]);
3193 double2float(vp->orientation.c,oo,4);
3196 case NODE_Viewpoint:
3201 quaternion_to_vrmlrot(&
viewer->Quat,&oo[0],&oo[1],&oo[2],&oo[3]);
3203 double2float(vp->orientation.c,oo,4);
3207 case NODE_GeoViewpoint:
3209 double pos[3],pos0[3],quat[4],quat0[4];
3211 pointxyz2double(pos,&
viewer->Pos);
3212 pointxyz2double(pos0,&
viewer->Pos0);
3213 quat2double(quat,&
viewer->Quat);
3214 quat2double(quat0,&
viewer->Quat0);
3215 if(veclengthd(vecdifd(pos,pos,pos0)) > .002 || veclength4d(vecdif4d(quat,quat,quat0)) > .00002)
3216 geoviewpoint_update_TCS(vp,&
viewer->Quat,&
viewer->Pos);
3224void viewer_fetch_user_offsets0(X3D_Viewer *
viewer){
3228 boundvp = getActiveLayerBoundViewpoint();
3230 switch(boundvp->_nodeType){
3231 case NODE_OrthoViewpoint:
3234 double oo[4], pp[3];
3235 float2double(pp,vp->position.c,3);
3236 double2pointxyz(&
viewer->Pos,pp);
3238 float2double(oo,vp->orientation.c,4);
3239 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
3242 case NODE_Viewpoint:
3246 double oo[4], pp[3];
3247 float2double(pp,vp->position.c,3);
3248 double2pointxyz(&
viewer->Pos,pp);
3249 float2double(oo,vp->orientation.c,4);
3250 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
3253 case NODE_GeoViewpoint:
3271void viewer_fetch_LCS(X3D_Viewer *
viewer){
3277 boundvp = getActiveLayerBoundViewpoint();
3279 switch(boundvp->_nodeType){
3280 case NODE_OrthoViewpoint:
3281 case NODE_Viewpoint:
3282 viewer_fetch_user_offsets0(
viewer);
3284 case NODE_GeoViewpoint:
3299void viewer_update_LCS(X3D_Viewer *
viewer){
3301 boundvp = getActiveLayerBoundViewpoint();
3303 switch(boundvp->_nodeType){
3304 case NODE_OrthoViewpoint:
3305 case NODE_Viewpoint:
3306 viewer_update_user_offsets0(
viewer);
3308 case NODE_GeoViewpoint:
3310 double pos[3],pos0[3],quat[4],quat0[4];
3312 pointxyz2double(pos,&
viewer->Pos);
3313 pointxyz2double(pos0,&
viewer->Pos0);
3314 quat2double(quat,&
viewer->Quat);
3315 quat2double(quat0,&
viewer->Quat0);
3316 if(veclengthd(vecdifd(pos,pos,pos0)) > .002 || veclength4d(vecdif4d(quat,quat,quat0)) > .00002)
3317 geoviewpoint_update_LCS(vp,&
viewer->Quat,&
viewer->Pos);
3327void viewer_fetch_bindtime_pose0(X3D_Viewer *
viewer, Quaternion *
Quat,
struct point_XYZ *Pos){
3331 boundvp = getActiveLayerBoundViewpoint();
3333 switch(boundvp->_nodeType){
3334 case NODE_OrthoViewpoint:
3337 double oo[4], pp[3];
3338 float2double(pp,vp->_position.c,3);
3339 double2pointxyz(&
viewer->Pos,pp);
3341 float2double(oo,vp->_orientation.c,4);
3342 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
3345 case NODE_Viewpoint:
3349 double oo[4], pp[3];
3350 float2double(pp,vp->_position.c,3);
3351 double2pointxyz(&
viewer->Pos,pp);
3352 float2double(oo,vp->_orientation.c,4);
3353 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
3356 case NODE_GeoViewpoint:
3360 float2double(oo,vp->_orientation.c,4);
3361 vrmlrot_to_quaternion(
Quat,oo[0],oo[1],oo[2], -oo[3]);
3362 double2pointxyz(Pos,vp->_position.c);
3373void increment_pos0(
struct point_XYZ *vec) {
3378 viewer_lastP_add(vec);
3381 quaternion_inverse(&q_i, &(
viewer->Quat));
3382 quaternion_rotation(&nv, &q_i, vec);
3385 viewer->VPvelocity.x = nv.x;
viewer->VPvelocity.y = nv.y;
viewer->VPvelocity.z = nv.z;
3396void increment_pos(
struct point_XYZ *vec) {
3399 viewer_fetch_user_offsets0(
viewer);
3400 increment_pos0(vec);
3401 viewer_update_user_offsets0(
viewer);
3409 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
3410 viewer = ViewerByLayerId(vp->_layerId);
3414 if (!(vp->isBound))
return;
3415 if(!vp->_initializedOnce) {
3417 veccopy3f(vp->_position.c,vp->position.c);
3418 veccopy4f(vp->_orientation.c,vp->orientation.c);
3419 vp->_initializedOnce = TRUE;
3422 if(!vp->retainUserOffsets){
3423 veccopy3f(vp->position.c,vp->_position.c);
3424 veccopy4f(vp->orientation.c,vp->_orientation.c);
3426 viewer = ViewerByLayerId(vp->_layerId);
3430 if (
viewer->transitionType != VIEWER_TRANSITION_TELEPORT &&
viewer->wasBound) {
3432 viewer->vp2rnSaved = TRUE;
3437 matcopy(
viewer->slerp_viewmatrix,bstack->viewtransformmatrix);
3438 matcopy(
viewer->slerp_posorimatrix,bstack->posorimatrix);
3442 viewer->SLERPing = FALSE;
3443 viewer->startSLERPtime = TickTime();
3445 viewer->SLERPing2 = TRUE;
3446 viewer->SLERPing2justStarted = TRUE;
3450 viewer->SLERPing = FALSE;
3451 viewer->SLERPing2 = FALSE;
3460 if (vp->fieldOfView.n == 4) {
3463 viewer->orthoField[0] = (double) vp->fieldOfView.p[0];
3464 viewer->orthoField[1] = (double) vp->fieldOfView.p[1];
3465 viewer->orthoField[2] = (double) vp->fieldOfView.p[2];
3466 viewer->orthoField[3] = (double) vp->fieldOfView.p[3];
3468 ERROR_MSG(
"OrthoViewpoint - fieldOfView must have 4 parameters");
3469 viewer->orthoField[0] = -1.0;
3470 viewer->orthoField[1] = -1.0;
3471 viewer->orthoField[2] = 1.0;
3472 viewer->orthoField[3] = 1.0;
3478 INITIATE_ROTATION_ORIGIN
3507 viewer_lastP_clear();
3508 setMenuStatusVP (vp->description->strptr);
3513int slerp_viewpoint2()
3518 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
3522 if(
viewer->SLERPing2 &&
viewer->vp2rnSaved && itype==2) {
3523 double mat_to[16],mat_from[16];
3525 ttglobal tg = gglobal();
3526 bstack = getActiveBindableStacks(tg);
3528 matmultiplyAFFINE(mat_to,bstack->viewtransformmatrix,bstack->posorimatrix);
3529 matmultiplyAFFINE(mat_from,
viewer->slerp_viewmatrix,
viewer->slerp_posorimatrix);
3543 if(
viewer->SLERPing2justStarted)
3545 viewer->SLERPing2justStarted = FALSE;
3549 double matnow[16],matdif[16], matid[16], mat_toi[16], matview[16], matnew[16];;
3550 tickFrac = (TickTime() -
viewer->startSLERPtime)/
viewer->transitionTime;
3551 tickFrac = DOUBLE_MIN(tickFrac,1.0);
3552 tickFrac = DOUBLE_MAX(tickFrac,0.0);
3554 loadIdentityMatrix(matid);
3555 matinverseAFFINE(mat_toi,mat_to);
3556 matmultiplyAFFINE(matdif,mat_from,mat_toi);
3557 general_slerp(matnow,matdif,matid,16,tickFrac);
3558 matmultiplyAFFINE(matnew,matnow,bstack->viewtransformmatrix);
3559 matcopy(bstack->viewtransformmatrix, matnew);
3563 viewer->SLERPing2 = FALSE;
3570 if(
viewer->SLERPing2justStarted)
3575 double vpn2rn[16],rn2vpn[16];
3578 matcopy(vpo2rn,mat_from);
3582 matcopy(vpn2rn,mat_to);
3585 matinverseAFFINE(rn2vpn,vpn2rn);
3590 matmultiplyAFFINE(diffrn,vpo2rn,rn2vpn);
3596 matrix_to_quaternion(&p->sq,diffrn);
3597 quaternion_normalize(&p->sq);
3598 p->sp[0] = diffrn[12];
3599 p->sp[1] = diffrn[13];
3600 p->sp[2] = diffrn[14];
3601 viewer->SLERPing2justStarted = FALSE;
3608 Quaternion qdif,qzero;
3609 double vzero[3], vshift[3], matdif[16], matnew[16];
3611 tickFrac = (TickTime() -
viewer->startSLERPtime)/
viewer->transitionTime;
3612 tickFrac = DOUBLE_MIN(tickFrac,1.0);
3613 tickFrac = DOUBLE_MAX(tickFrac,0.0);
3615 vzero[0] = vzero[1] = vzero[2] = 0.0;
3616 vrmlrot_to_quaternion(&qzero, 0.0,1.0,0.0,0.0);
3617 quaternion_slerp(&qdif,&p->sq,&qzero,tickFrac);
3618 general_slerp(vshift,p->sp,vzero,3,tickFrac);
3619 FW_GL_PUSH_MATRIX();
3620 FW_GL_LOAD_IDENTITY();
3621 FW_GL_TRANSLATE_D(vshift[0],vshift[1],vshift[2]);
3622 quaternion_togl(&qdif);
3623 fw_glGetDoublev(GL_MODELVIEW_MATRIX, matdif);
3625 matmultiplyAFFINE(matnew,matdif,bstack->viewtransformmatrix);
3626 matcopy(bstack->viewtransformmatrix, matnew);
3629 viewer->SLERPing2 = FALSE;
3636int slerp_viewpoint3()
3642 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
3646 if(
viewer->SLERPing3 && itype==3){
3650 tickFrac = (TickTime() -
viewer->startSLERPtime)/
viewer->transitionTime;
3651 tickFrac = min(1.0,tickFrac);
3653 viewer_fetch_LCS(
viewer);
3654 quaternion_slerp(&
viewer->Quat,&
viewer->startSLERPQuat,&
viewer->endSLERPQuat,tickFrac);
3657 viewer_update_LCS(
viewer);
3658 general_slerp(&
viewer->Dist,&
viewer->startSLERPDist,&
viewer->endSLERPDist,1,tickFrac);
3659 if(tickFrac >= 1.0) {
3669void setup_viewpoint_slerp3(
double* center,
double pivot_radius,
double vp_radius){
3679 Quaternion qyaw, qpitch, qtmp;
3684 double pos[3] = {0.0,0.0,0.0};
3688 veccopyd(pos,center);
3690 vecnormald(pos,pos);
3691 vecscaled(pos,pos,vp_radius);
3702 viewer_fetch_LCS(
viewer);
3706 viewer->startSLERPtime = TickTime();
3721 viewer->endSLERPDist = vp_radius;
3725 quaternion_normalize(&
viewer->startSLERPQuat);
3726 quaternion_inverse( &q_i,&
viewer->startSLERPQuat);
3727 vecdifd(pos,center,pos);
3728 double2pointxyz(&pp,pos);
3729 quaternion_rotation(&qq, &q_i, &pp);
3730 vecadd(&
viewer->endSLERPPos,&
viewer->startSLERPPos,&qq);
3738 if( APPROX( vecnormald(C,C), 0.0) )
3742 vecscaled(C,C,-1.0);
3743 yaw = -atan2(C[0],C[2]);
3745 vrmlrot_to_quaternion(&qyaw, 0.0,1.0,0.0,yaw);
3746 double2pointxyz(&PC,C);
3747 quaternion_rotation(&PC,&qyaw,&PC);
3749 pitch = atan2(PC.y,PC.z);
3750 vrmlrot_to_quaternion(&qpitch,1.0,0.0,0.0,pitch);
3752 quaternion_multiply(&qtmp,&qyaw,&qpitch);
3753 quaternion_multiply(&
viewer->endSLERPQuat,&qtmp,&
viewer->startSLERPQuat);
3758void viewer_viewall(){
3759 double dcenter[3], pivot_radius, vp_radius;
3765 float scene_diameter, vpradius;
3767 float vpf[3], center[3], vpoffset[3];
3768 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, MM);
3770 extent6f_copy(extent6,rn->_extent);
3772 extent6f_mattransform4d(extent6,extent6,MM);
3773 if(Viewer()->ortho){
3776 struct X3D_Node *boundvp = getActiveLayerBoundViewpoint();
3777 if(boundvp->_nodeType == NODE_OrthoViewpoint){
3779 vp->fieldOfView.p[0] = extent6[1];
3780 vp->fieldOfView.p[1] = extent6[3];
3781 vp->fieldOfView.p[2] = extent6[0];
3782 vp->fieldOfView.p[3] = extent6[2];
3792 vecset3f(vpf,0.0f,0.0f,0.0f);
3793 extent6f_get_center3f(extent6,center);
3794 float2double(dcenter,center,3);
3795 pivot_radius = extent6f_get_maxradius(extent6);
3797 vecdif3f(vpoffset,center,vpf);
3798 vp_radius = vpradius = veclength3f(vpoffset) * 1.5;
3808 vp_radius = pivot_radius /sin(Viewer()->fieldofview *.5 * M_PI / 180.0);
3811 Viewer()->Dist = vp_radius;
3813 setup_viewpoint_slerp3(dcenter,pivot_radius, vp_radius);
3823 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
3826 if (!(vp->isBound))
return;
3827 if(!vp->_initializedOnce) {
3828 veccopy3f(vp->_position.c,vp->position.c);
3829 veccopy4f(vp->_orientation.c,vp->orientation.c);
3830 vp->_initializedOnce = TRUE;
3979 if(!vp->retainUserOffsets){
3980 veccopy3f(vp->position.c,vp->_position.c);
3981 veccopy4f(vp->orientation.c,vp->_orientation.c);
3983 viewer = ViewerByLayerId(vp->_layerId);
3987 if (
viewer->transitionType != VIEWER_TRANSITION_TELEPORT &&
viewer->wasBound) {
3989 viewer->vp2rnSaved = TRUE;
3994 matcopy(
viewer->slerp_viewmatrix,bstack->viewtransformmatrix);
3995 matcopy(
viewer->slerp_posorimatrix,bstack->posorimatrix);
3999 viewer->SLERPing = FALSE;
4000 viewer->startSLERPtime = TickTime();
4002 viewer->SLERPing2 = TRUE;
4003 viewer->SLERPing2justStarted = TRUE;
4005 viewer->SLERPing = FALSE;
4006 viewer->SLERPing2 = FALSE;
4020 INITIATE_ROTATION_ORIGIN
4050 viewer_lastP_clear();
4051 setMenuStatusVP (vp->description->strptr);
4055int fwl_getAnaglyphSide(
int whichSide) {
4056 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
4059 if ((whichSide<0) || (whichSide>1)) {
4074 return (p->acMask[whichSide][0] << 2) | (p->acMask[whichSide][1] << 1) | (p->acMask[whichSide][2]);
4081void Android_reset_viewer_to_defaults() {
4085 ppViewer p = (ppViewer)gglobal()->Viewer.prv;
4087 p->viewer_initialized = FALSE;
4090 viewer->SLERPing2 = FALSE;
4091 viewer->SLERPing = FALSE;
4095 return Viewer()->iside;