37#include <libFreeWRL.h>
40#include "../vrml_parser/Structs.h"
41#include "../input/InputFunctions.h"
42#include "../opengl/LoadTextures.h"
45#include "../main/headers.h"
46#include "../opengl/OpenGL_Utils.h"
47#include "../scenegraph/RenderFuncs.h"
49#include "../x3d_parser/Bindable.h"
50#include "../scenegraph/LinearAlgebra.h"
51#include "../scenegraph/Collision.h"
52#include "../scenegraph/quaternion.h"
53#include "../scenegraph/sounds.h"
54#include "../vrml_parser/CRoutes.h"
55#include "../opengl/OpenGL_Utils.h"
56#include "../opengl/Textures.h"
58#include "SensInterps.h"
67void *SensInterps_constructor(){
72void SensInterps_init(
struct tSensInterps *t)
76 t->prv = SensInterps_constructor();
88void do_active_inactive (
112 double ticktime = TickTime();
116 printf (
"is active tick %f startt %f stopt %f\n",
117 TickTime(), *startt, *stopt);
120 if (ticktime > *stopt) {
121 if (*startt >= *stopt) {
129 if (! APPROX(speed, 0)) {
131 if (elapsedTime >= fabs(myDuration/speed) ) {
133 printf (
"stopping case x\n");
134 printf (
"TickTime() %f\n",ticktime);
135 printf (
"startt %f\n",*startt);
136 printf (
"myDuration %f\n",myDuration);
137 printf (
"speed %f\n",speed);
147 printf (
"stopping case z\n");
160 if (ticktime >= *startt) {
163 if (ticktime >= *stopt) {
168 if (*startt >= *stopt) {
172 if (!(*startt > 0)) *startt = ticktime;
175 }
else if (*startt >= *stopt) {
176 if (*startt > *inittime) {
191 if (!(*startt > 0)) *startt = ticktime;
200int find_key (
int kin,
float frac,
float *keys) {
203 for (counter=1; counter <= kin; counter++) {
204 if (frac <keys[counter]) {
213void do_OintScalar (
void *node) {
223 kvin = px->keyValue.n;
224 kVs = px->keyValue.p;
229 if ((kvin == 0) || (kin == 0)) {
230 px->value_changed = (float) 0.0;
233 if (kin>kvin) kin=kvin;
236 printf (
"ScalarInterpolator, kin %d kvin %d, vc %f\n",kin,kvin,px->value_changed);
240 if (px->set_fraction <= px->key.p[0]) {
241 px->value_changed = kVs[0];
242 }
else if (px->set_fraction >= px->key.p[kin-1]) {
243 px->value_changed = kVs[kvin-1];
246 counter=find_key(kin,(
float)(px->set_fraction),px->key.p);
248 (px->set_fraction - px->key.p[counter-1]) /
249 (px->key.p[counter] - px->key.p[counter-1]) *
250 (kVs[counter] - kVs[counter-1]) +
256void do_OintNormal(
void *node) {
262 int thisone, prevone;
275 printf (
"debugging OintCoord keys %d kv %d vc %d\n",px->keyValue.n, px->key.n,px->value_changed.n);
281 kvin = px->keyValue.n;
282 kVs = px->keyValue.p;
286 if (kpkv != px->value_changed.n) {
288 printf (
"refactor valuechanged array. n %d sizeof p %d\n",
289 kpkv,
sizeof (
struct SFColor) * kpkv);
291 if (px->value_changed.n != 0) {
292 FREE_IF_NZ (px->value_changed.p);
294 px->value_changed.n = kpkv;
295 px->value_changed.p = MALLOC (
struct SFVec3f*,
sizeof (
struct SFVec3f) * kpkv);
299 valchanged = px->value_changed.p;
303 if ((kvin == 0) || (kin == 0)) {
305 printf (
"no keys or keyValues yet\n");
308 for (indx = 0; indx < kpkv; indx++) {
309 valchanged[indx].c[0] = (float) 0.0;
310 valchanged[indx].c[1] = (float) 0.0;
311 valchanged[indx].c[2] = (float) 0.0;
315 if (kin>kvin) kin=kvin;
319 printf (
"debugging, kpkv %d, px->value_changed.n %d\n", kpkv, px->value_changed.n);
320 printf (
"NormalInterpolator, kpkv %d\n",kpkv);
325 if (px->set_fraction <= px->key.p[0]) {
327 printf (
"COINT out1\n");
330 for (indx = 0; indx < kpkv; indx++) {
331 memcpy ((
void *)&valchanged[indx],
332 (
void *)&kVs[indx],
sizeof (
struct SFColor));
335 printf (
"COINT out1 copied\n");
337 }
else if (px->set_fraction >= px->key.p[kin-1]) {
339 printf (
"COINT out2\n");
342 for (indx = 0; indx < kpkv; indx++) {
343 memcpy ((
void *)&valchanged[indx],
344 (
void *)&kVs[kvin-kpkv+indx],
348 printf (
"COINT out2 finished\n");
352 printf (
"COINT out3\n");
357 printf (
"indx=0, kin %d frac %f\n",kin,px->set_fraction);
360 myKey=find_key(kin,(
float)(px->set_fraction),px->key.p);
362 printf (
"working on key %d\n",myKey);
366 interval = (px->set_fraction - px->key.p[myKey-1]) /
367 (px->key.p[myKey] - px->key.p[myKey-1]);
369 for (indx = 0; indx < kpkv; indx++) {
370 thisone = myKey * kpkv + indx;
371 prevone = (myKey-1) * kpkv + indx;
374 if (thisone >= kvin) {
375 printf (
"CoordinateInterpolator error: thisone %d prevone %d indx %d kpkv %d kin %d kvin %d\n",thisone,prevone,
380 for (tmp=0; tmp<3; tmp++) {
381 valchanged[indx].c[tmp] = kVs[prevone].c[tmp] +
382 interval * (kVs[thisone].c[tmp] -
383 kVs[prevone].c[tmp]);
386 printf (
" 1 %d interval %f prev %f this %f final %f\n",1,interval,kVs[prevone].c[1],kVs[thisone].c[1],valchanged[indx].c[1]);
390 printf (
"COINT out3 finished\n");
396 for (indx = 0; indx < kpkv; indx++) {
397 normalval.x = valchanged[indx].c[0];
398 normalval.y = valchanged[indx].c[1];
399 normalval.z = valchanged[indx].c[2];
400 normalize_vector(&normalval);
401 valchanged[indx].c[0] = (float) normalval.x;
402 valchanged[indx].c[1] = (float) normalval.y;
403 valchanged[indx].c[2] = (float) normalval.z;
406 printf (
"Done CoordinateInterpolator\n");
411void do_OintCoord(
void *node) {
417 int thisone, prevone;
428 printf (
"do_OintCoord, frac %f toGPU %d toCPU %d\n",px->set_fraction,px->_GPU_Routes_out, px->_CPU_Routes_out);
429 printf (
"debugging OintCoord keys %d kv %d vc %d\n",px->keyValue.n, px->key.n,px->value_changed.n);
435 if (px->_GPU_Routes_out > 0) {
436 if (px->_keyVBO==0) {
437 glGenBuffers(1,(GLuint *)&px->_keyValueVBO);
438 glGenBuffers(1,(GLuint *)&px->_keyVBO);
439 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,px->_keyValueVBO);
440 printf (
"genning buffer data for %d keyValues, total floats %d\n",px->keyValue.n, px->keyValue.n*3);
441 glBufferData(GL_ARRAY_BUFFER,px->keyValue.n *
sizeof(
float)*3,px->keyValue.p, GL_STATIC_DRAW);
443 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,px->_keyVBO);
444 glBufferData(GL_ARRAY_BUFFER,px->key.n *
sizeof(
float),px->key.p, GL_STATIC_DRAW);
445 printf (
"created VBOs for the CoordinateInterpolator, they are %d and %d\n",
446 px->_keyValueVBO, px->_keyVBO);
452 if (px->_CPU_Routes_out == 0) {
454 printf (
"do_OintCoord, no CPU routes out, no need to do this work\n");
463 kvin = px->keyValue.n;
464 kVs = px->keyValue.p;
468 if (kpkv != px->value_changed.n) {
470 printf (
"refactor valuechanged array. n %d sizeof p %d\n",
471 kpkv,
sizeof (
struct SFVec3f) * kpkv);
473 if (px->value_changed.n != 0) {
474 FREE_IF_NZ (px->value_changed.p);
476 px->value_changed.n = kpkv;
477 px->value_changed.p = MALLOC (
struct SFVec3f*,
sizeof (
struct SFVec3f) * kpkv);
481 valchanged = px->value_changed.p;
485 if ((kvin == 0) || (kin == 0)) {
487 printf (
"no keys or keyValues yet\n");
490 for (indx = 0; indx < kpkv; indx++) {
491 valchanged[indx].c[0] = (float) 0.0;
492 valchanged[indx].c[1] = (float) 0.0;
493 valchanged[indx].c[2] = (float) 0.0;
497 if (kin>kvin) kin=kvin;
501 printf (
"debugging, kpkv %d, px->value_changed.n %d\n", kpkv, px->value_changed.n);
502 printf (
"CoordinateInterpolator, kpkv %d\n",kpkv);
507 if (px->set_fraction <= px->key.p[0]) {
509 printf (
"COINT out1\n");
512 for (indx = 0; indx < kpkv; indx++) {
513 memcpy ((
void *)&valchanged[indx],
514 (
void *)&kVs[indx],
sizeof (
struct SFVec3f));
520 printf (
"COINT out1 copied\n");
522 }
else if (px->set_fraction >= px->key.p[kin-1]) {
524 printf (
"COINT out2\n");
527 for (indx = 0; indx < kpkv; indx++) {
528 memcpy ((
void *)&valchanged[indx],
529 (
void *)&kVs[kvin-kpkv+indx],
533 printf (
"COINT out2 finished\n");
537 printf (
"COINT out3\n");
542 printf (
"indx=0, kin %d frac %f\n",kin,px->set_fraction);
545 myKey=find_key(kin,(
float)(px->set_fraction),px->key.p);
547 printf (
"working on key %d\n",myKey);
551 interval = (px->set_fraction - px->key.p[myKey-1]) /
552 (px->key.p[myKey] - px->key.p[myKey-1]);
554 for (indx = 0; indx < kpkv; indx++) {
555 thisone = myKey * kpkv + indx;
556 prevone = (myKey-1) * kpkv + indx;
559 if (thisone >= kvin) {
560 printf (
"CoordinateInterpolator error: thisone %d prevone %d indx %d kpkv %d kin %d kvin %d\n",thisone,prevone,
565 for (tmp=0; tmp<3; tmp++) {
566 valchanged[indx].c[tmp] = kVs[prevone].c[tmp] +
567 interval * (kVs[thisone].c[tmp] -
568 kVs[prevone].c[tmp]);
571 printf (
" 1 %d interval %f prev %f this %f final %f\n",1,interval,kVs[prevone].c[1],kVs[thisone].c[1],valchanged[indx].c[1]);
575 printf (
"COINT out3 finished\n");
581 printf (
"Done CoordinateInterpolator\n");
585void do_OintCoord2D(
void *node) {
591 int thisone, prevone;
603 printf (
"debugging OintCoord keys %d kv %d vc %d\n",px->keyValue.n, px->key.n,px->value_changed.n);
609 kvin = px->keyValue.n;
610 kVs = px->keyValue.p;
614 if (kpkv != px->value_changed.n) {
616 printf (
"refactor valuechanged array. n %d sizeof p %d\n",
617 kpkv,
sizeof (
struct SFVec2f) * kpkv);
619 if (px->value_changed.n != 0) {
620 FREE_IF_NZ (px->value_changed.p);
622 px->value_changed.n = kpkv;
623 px->value_changed.p = MALLOC (
struct SFVec2f*,
sizeof (
struct SFVec2f) * kpkv);
627 valchanged = px->value_changed.p;
631 if ((kvin == 0) || (kin == 0)) {
633 printf (
"no keys or keyValues yet\n");
636 for (indx = 0; indx < kpkv; indx++) {
637 valchanged[indx].c[0] = (float) 0.0;
638 valchanged[indx].c[1] = (float) 0.0;
642 if (kin>kvin) kin=kvin;
646 printf (
"debugging, kpkv %d, px->value_changed.n %d\n", kpkv, px->value_changed.n);
647 printf (
"CoordinateInterpolator2D, kpkv %d\n",kpkv);
652 if (px->set_fraction <= px->key.p[0]) {
654 printf (
"COINT out1\n");
657 for (indx = 0; indx < kpkv; indx++) {
658 memcpy ((
void *)&valchanged[indx],
659 (
void *)&kVs[indx],
sizeof (
struct SFVec2f));
664 printf (
"COINT out1 copied\n");
666 }
else if (px->set_fraction >= px->key.p[kin-1]) {
668 printf (
"COINT out2\n");
671 for (indx = 0; indx < kpkv; indx++) {
672 memcpy ((
void *)&valchanged[indx],
673 (
void *)&kVs[kvin-kpkv+indx],
677 printf (
"COINT out2 finished\n");
681 printf (
"COINT out3\n");
686 printf (
"indx=0, kin %d frac %f\n",kin,px->set_fraction);
689 myKey=find_key(kin,(
float)(px->set_fraction),px->key.p);
691 printf (
"working on key %d\n",myKey);
695 interval = (px->set_fraction - px->key.p[myKey-1]) /
696 (px->key.p[myKey] - px->key.p[myKey-1]);
698 for (indx = 0; indx < kpkv; indx++) {
699 thisone = myKey * kpkv + indx;
700 prevone = (myKey-1) * kpkv + indx;
703 if (thisone >= kvin) {
704 printf (
"CoordinateInterpolator2D error: thisone %d prevone %d indx %d kpkv %d kin %d kvin %d\n",thisone,prevone,
709 for (tmp=0; tmp<2; tmp++) {
710 valchanged[indx].c[tmp] = kVs[prevone].c[tmp] +
711 interval * (kVs[thisone].c[tmp] -
712 kVs[prevone].c[tmp]);
716 printf (
"COINT out3 finished\n");
722 printf (
"Done CoordinateInterpolator2D\n");
726void do_OintPos2D(
void *node) {
733 int kin, kvin, counter, tmp;
742 kvin = px->keyValue.n;
743 kVs = px->keyValue.p;
746 printf(
"do_Oint2: Position interp2D, node %u kin %d kvin %d set_fraction %f\n",
747 node, kin, kvin, px->set_fraction);
751 if ((kvin == 0) || (kin == 0)) {
752 px->value_changed.c[0] = (float) 0.0;
753 px->value_changed.c[1] = (float) 0.0;
756 if (kin>kvin) kin=kvin;
760 if (px->set_fraction <= ((px->key).p[0])) {
761 memcpy ((
void *)&px->value_changed,
762 (
void *)&kVs[0], sizeof (
struct SFVec2f));
763 }
else if (px->set_fraction >= px->key.p[kin-1]) {
764 memcpy ((
void *)&px->value_changed,
765 (
void *)&kVs[kvin-1], sizeof (
struct SFVec2f));
768 counter = find_key(kin,((
float)(px->set_fraction)),px->key.p);
769 for (tmp=0; tmp<2; tmp++) {
770 px->value_changed.c[tmp] =
771 (px->set_fraction - px->key.p[counter-1]) /
772 (px->key.p[counter] - px->key.p[counter-1]) *
773 (kVs[counter].c[tmp] -
774 kVs[counter-1].c[tmp]) +
775 kVs[counter-1].c[tmp];
779 printf (
"Pos/Col, new value (%f %f)\n",
780 px->value_changed.c[0],px->value_changed.c[1]);
792void do_ColorInterpolator (
void *node) {
794 int kin, kvin, counter, tmp;
800 kvin = px->keyValue.n;
801 kVs = px->keyValue.p;
807 printf(
"do_ColorInt: Position/Color interp, node %u kin %d kvin %d set_fraction %f\n",
808 node, kin, kvin, px->set_fraction);
812 if ((kvin == 0) || (kin == 0)) {
813 px->value_changed.c[0] = (float) 0.0;
814 px->value_changed.c[1] = (float) 0.0;
815 px->value_changed.c[2] = (float) 0.0;
819 if (kin>kvin) kin=kvin;
822 if (px->set_fraction <= ((px->key).p[0])) {
823 memcpy ((
void *)&px->value_changed, (
void *)&kVs[0], sizeof (
struct SFColor));
824 }
else if (px->set_fraction >= px->key.p[kin-1]) {
825 memcpy ((
void *)&px->value_changed, (
void *)&kVs[kvin-1], sizeof (
struct SFColor));
828 counter = find_key(kin,((
float)(px->set_fraction)),px->key.p);
829 for (tmp=0; tmp<3; tmp++) {
830 px->value_changed.c[tmp] =
831 (px->set_fraction - px->key.p[counter-1]) /
832 (px->key.p[counter] - px->key.p[counter-1]) *
833 (kVs[counter].c[tmp] - kVs[counter-1].c[tmp]) + kVs[counter-1].c[tmp];
837 printf (
"Pos/Col, new value (%f %f %f)\n",
838 px->value_changed.c[0],px->value_changed.c[1],px->value_changed.c[2]);
843void do_PositionInterpolator (
void *node) {
845 int kin, kvin, counter, tmp;
851 kvin = px->keyValue.n;
852 kVs = px->keyValue.p;
858 printf(
"do_PositionInt: Position/Vec3f interp, node %u kin %d kvin %d set_fraction %f\n",
859 node, kin, kvin, px->set_fraction);
863 if ((kvin == 0) || (kin == 0)) {
864 px->value_changed.c[0] = (float) 0.0;
865 px->value_changed.c[1] = (float) 0.0;
866 px->value_changed.c[2] = (float) 0.0;
870 if (kin>kvin) kin=kvin;
873 if (px->set_fraction <= ((px->key).p[0])) {
874 memcpy ((
void *)&px->value_changed, (
void *)&kVs[0], sizeof (
struct SFVec3f));
875 }
else if (px->set_fraction >= px->key.p[kin-1]) {
876 memcpy ((
void *)&px->value_changed, (
void *)&kVs[kvin-1], sizeof (
struct SFVec3f));
879 counter = find_key(kin,((
float)(px->set_fraction)),px->key.p);
880 for (tmp=0; tmp<3; tmp++) {
881 px->value_changed.c[tmp] =
882 (px->set_fraction - px->key.p[counter-1]) /
883 (px->key.p[counter] - px->key.p[counter-1]) *
884 (kVs[counter].c[tmp] - kVs[counter-1].c[tmp]) + kVs[counter-1].c[tmp];
888 printf (
"Pos/Col, new value (%f %f %f)\n",
889 px->value_changed.c[0],px->value_changed.c[1],px->value_changed.c[2]);
898void do_Oint4 (
void *node) {
913 kvin = ((px->keyValue).n);
914 kVs = ((px->keyValue).p);
917 printf (
"starting do_Oint4; keyValue count %d and key count %d\n",
925 if ((kvin == 0) || (kin == 0)) {
926 px->value_changed.c[0] = (float) 0.0;
927 px->value_changed.c[1] = (float) 0.0;
928 px->value_changed.c[2] = (float) 0.0;
929 px->value_changed.c[3] = (float) 0.0;
932 if (kin>kvin) kin=kvin;
936 if (px->set_fraction <= ((px->key).p[0])) {
937 memcpy ((
void *)&px->value_changed,
939 }
else if (px->set_fraction >= ((px->key).p[kin-1])) {
940 memcpy ((
void *)&px->value_changed,
941 (
void *)&kVs[kvin-1], sizeof (
struct SFRotation));
943 counter = find_key(kin,(
float)(px->set_fraction),px->key.p);
944 interval = (px->set_fraction - px->key.p[counter-1]) /
945 (px->key.p[counter] - px->key.p[counter-1]);
952 printf (
"counter %d interval %f\n",counter,interval);
953 printf (
"angles %f %f %f %f, %f %f %f %f\n",
963 vrmlrot_to_quaternion (&st, kVs[counter-1].c[0],
964 kVs[counter-1].c[1], kVs[counter-1].c[2], kVs[counter-1].c[3]);
965 vrmlrot_to_quaternion (&fin,kVs[counter].c[0],
966 kVs[counter].c[1], kVs[counter].c[2], kVs[counter].c[3]);
968 quaternion_slerp(&
final, &st, &fin, (
double)interval);
969 quaternion_to_vrmlrot(&
final,&x, &y, &z, &a);
970 px->value_changed.c[0] = (float) x;
971 px->value_changed.c[1] = (float) y;
972 px->value_changed.c[2] = (float) z;
973 px->value_changed.c[3] = (float) a;
976 printf (
"Oint, new angle %f %f %f %f\n",px->value_changed.c[0],
977 px->value_changed.c[1],px->value_changed.c[2], px->value_changed.c[3]);
984void do_CollisionTick(
void *ptr) {
986 if (cx->__hit == 3) {
988 cx->collideTime = TickTime();
989 MARK_EVENT (ptr, offsetof(
struct X3D_Collision, collideTime));
996void do_AudioTick(
void *ptr) {
999 double pitch, duration;
1004 if(node->__inittime == 0.0)
1005 node->__inittime = TickTime();
1007 if(TickTime() < node->startTime) {
1011 oldstatus = node->isActive;
1012 pitch = node->pitch;
1014 if(node->__sourceNumber < 0)
return;
1028 duration = return_Duration(node);
1029 do_active_inactive (
1030 &node->isActive, &node->__inittime, &node->startTime,
1031 &node->stopTime,node->loop,duration,
1032 pitch,node->elapsedTime);
1034 if (oldstatus != node->isActive) {
1036 if (node->isActive == 1) {
1039 node->__lasttime = TickTime();
1040 node->elapsedTime = 0.0;
1042 MARK_EVENT (X3D_NODE(node), offsetof(
struct X3D_AudioClip, isActive));
1046 if(node->pauseTime > node->startTime){
1047 if( node->resumeTime < node->pauseTime && !node->isPaused){
1048 node->isPaused = TRUE;
1049 MARK_EVENT (X3D_NODE(node), offsetof(
struct X3D_AudioClip, isPaused));
1050 }
else if(node->resumeTime > node->pauseTime && node->isPaused){
1051 node->isPaused = FALSE;
1052 node->__lasttime = TickTime();
1053 MARK_EVENT (X3D_NODE(node), offsetof(
struct X3D_AudioClip, isPaused));
1057 if(node->isActive == 1 && node->isPaused == FALSE) {
1058 double dtime = TickTime();
1059 node->elapsedTime += dtime - node->__lasttime;
1060 node->__lasttime = dtime;
1062 MARK_EVENT (ptr, offsetof(
struct X3D_AudioClip, elapsedTime));
1070#define LOAD_STABLE 10
1071unsigned char *movietexture_get_frame_by_fraction(
struct X3D_Node* node,
float fraction,
int *width,
int *height,
int *nchan);
1072void do_MovieTextureTick(
void *ptr) {
1089 if(node->__inittime == 0.0)
1090 node->__inittime = TickTime();
1092 if(TickTime() < node->startTime) {
1099 duration = node->duration_changed;
1100 speed = node->speed;
1102 oldstatus = node->isActive;
1103 do_active_inactive (
1104 &node->isActive, &node->__inittime, &node->startTime,
1105 &node->stopTime,node->loop,duration,
1106 speed,node->elapsedTime);
1108 if (oldstatus != node->isActive) {
1109 if (node->isActive == 1) {
1112 node->__lasttime = TickTime();
1113 node->elapsedTime = 0.0;
1119 if(node->pauseTime > node->startTime){
1120 if( node->resumeTime < node->pauseTime && !node->isPaused){
1121 node->isPaused = TRUE;
1123 }
else if(node->resumeTime > node->pauseTime && node->isPaused){
1124 node->isPaused = FALSE;
1125 node->__lasttime = TickTime();
1130 if(node->isActive && node->isPaused == FALSE) {
1131 double dtime = TickTime();
1132 node->elapsedTime += dtime - node->__lasttime;
1133 node->__lasttime = dtime;
1143 myFrac = node->elapsedTime / duration;
1145 tmpTrunc = (int) myFrac;
1146 frac = (float)myFrac - (
float)tmpTrunc;
1151 }
else if (APPROX(speed, 0.0f)) {
1154 node->__frac = frac;
1156 if(node->loop == FALSE && tmpTrunc > 0)
1157 node->__frac = 1.0f;
1163 if(node->__loadstatus == LOAD_STABLE){
1166 unsigned char* texdata;
1167 int width,height,nchan;
1169 texdata = movietexture_get_frame_by_fraction(X3D_NODE(node), node->__frac, &width, &height, &nchan);
1171 int thisTexture = node->__textureTableIndex;
1172 tti = getTableIndex(thisTexture);
1174 static int once = 0;
1178 tti->channels = nchan;
1182 tti->texdata = malloc(tti->x*tti->y*tti->channels);
1183 memcpy(tti->texdata,texdata,tti->x*tti->y*tti->channels);
1184 tti->status = TEX_NEEDSBINDING;
1187 tti->status = TEX_LOADED;
1188 glBindTexture(GL_TEXTURE_2D,tti->OpenGLTexture);
1190 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1191 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1196 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,texdata);
1198 glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,texdata);
1199 glBindTexture(GL_TEXTURE_2D,0);
1215float fclamp(
float fval,
float fstart,
float fend) {
1217 fret = fval > fend? fend : fval;
1218 fret = fret < fstart ? fstart : fret;
1221float *vecclamp2f(
float *fval,
float *fstart,
float *fend){
1224 if(fstart[i] <= fend[i])
1225 fval[i] = fclamp(fval[i],fstart[i],fend[i]);
1229float *vecclamp3f(
float *fval,
float *fstart,
float *fend){
1232 if(fstart[i] <= fend[i])
1233 fval[i] = fclamp(fval[i],fstart[i],fend[i]);
1238int approx3f(
float *a,
float *b){
1239 float tol = 0.00000001;
1242 iret = iret && (fabs(a[i] - b[i]) < tol) ? iret : FALSE;
1246int approx4f(
float *a,
float *b){
1247 float tol = 0.00000001;
1250 iret = iret && (fabs(a[i] - b[i]) < tol) ? iret : FALSE;
1254void do_TouchSensor (
void *ptr,
int ev,
int but1,
int over) {
1260 printf (
"%lf: TS ",TickTime());
1261 if (ev==ButtonPress) printf (
"ButtonPress ");
1262 else if (ev==ButtonRelease) printf (
"ButtonRelease ");
1263 else if (ev==KeyPress) printf (
"KeyPress ");
1264 else if (ev==KeyRelease) printf (
"KeyRelease ");
1265 else if (ev==MotionNotify) printf (
"%lf MotionNotify ");
1266 else printf (
"ev %d ",ev);
1268 if (but1) printf (
"but1 TRUE ");
else printf (
"but1 FALSE ");
1269 if (over) printf (
"over TRUE ");
else printf (
"over FALSE ");
1276 if (node->__oldEnabled != node->enabled) {
1277 node->__oldEnabled = node->enabled;
1278 MARK_EVENT(X3D_NODE(node),offsetof (
struct X3D_TouchSensor, enabled));
1280 if (!node->enabled)
return;
1283 if ((ev == overMark) && (over != node->isOver)) {
1285 printf (
"TS %u, isOver changed %d\n",node, over);
1287 node->isOver = over;
1293 if (ev == ButtonPress) {
1294 node->isActive=TRUE;
1297 printf (
"touchSens %u, butPress\n",node);
1300 node->touchTime = TickTime();
1303 }
else if (ev == ButtonRelease) {
1305 printf (
"touchSens %u, butRelease\n",node);
1307 node->isActive=FALSE;
1313 veccopy3f(node->_oldhitPoint.c,tg->RenderFuncs.ray_save_posn);
1316 if(!approx3f(node->_oldhitPoint.c,node->hitPoint_changed.c)){
1317 veccopy3f(node->hitPoint_changed.c,node->_oldhitPoint.c);
1322 veccopy3f(normalval,tg->RenderFuncs.hyp_save_norm);
1323 vecnormalize3f(normalval,normalval);
1324 veccopy3f(node->_oldhitNormal.c,normalval);
1327 if(!approx3f(node->_oldhitNormal.c,node->hitNormal_changed.c)) {
1329 veccopy3f(node->hitNormal_changed.c,node->_oldhitNormal.c);
1330 MARK_EVENT(ptr, offsetof (
struct X3D_TouchSensor, hitNormal_changed));
1339void do_LineSensor(
void *ptr,
int ev,
int but1,
int over) {
1351 float trackpoint[3], translation[3], xxx;
1358 printf(
"%lf: TS ", TickTime());
1359 if (ev == ButtonPress) printf(
"ButtonPress ");
1360 else if (ev == ButtonRelease) printf(
"ButtonRelease ");
1361 else if (ev == KeyPress) printf(
"KeyPress ");
1362 else if (ev == KeyRelease) printf(
"KeyRelease ");
1363 else if (ev == MotionNotify) printf(
"%lf MotionNotify ");
1364 else printf(
"ev %d ", ev);
1366 if (but1) printf(
"but1 TRUE ");
else printf(
"but1 FALSE ");
1367 if (over) printf(
"over TRUE ");
else printf(
"over FALSE ");
1374 if (node->__oldEnabled != node->enabled) {
1375 node->__oldEnabled = node->enabled;
1376 MARK_EVENT(X3D_NODE(node), offsetof(
struct X3D_LineSensor, enabled));
1378 if (!node->enabled)
return;
1389 float origin [] = { 0.0f, 0.0f, 0.0f };
1390 float footpoint2[3], footpoint1[3], v1[3];
1391 vecdif3f(v1, tg->RenderFuncs.hyp_save_norm, tg->RenderFuncs.hyp_save_posn);
1392 vecnormalize3f(v1, v1);
1393 if (!line_intersect_line_3f(tg->RenderFuncs.hyp_save_posn, v1,
1394 origin, node->direction.c, NULL, &tt, footpoint1, footpoint2))
1400 veccopy3f(trackpoint,footpoint2);
1402 if ((ev == ButtonPress) && but1) {
1404#define LINESENSOR_FLOAT_OFFSET 1
1405#ifndef LINESENSOR_FLOAT_OFFSET
1407 veccopy3f(op.c, trackpoint);
1408 memcpy((
void *)&node->_origPoint, (
void *)&op,
sizeof(
struct SFColor));
1411 node->_origPoint.c[0] = xxx;
1413 if (node->autoOffset)
1414 node->_origPoint.c[1] = node->offset;
1416 node->_origPoint.c[1] = 0.0f;
1419 node->isActive = TRUE;
1423 else if ((ev == MotionNotify) && (node->isActive) && but1) {
1424 float xxxoffset, xxxorigin;
1427 veccopy3f(node->_oldtrackPoint.c,trackpoint);
1429 if(!approx3f(node->_oldtrackPoint.c, node->trackPoint_changed.c)) {
1430 veccopy3f(node->trackPoint_changed.c, node->_oldtrackPoint.c);
1431 MARK_EVENT(ptr, offsetof(
struct X3D_LineSensor, trackPoint_changed));
1436#ifdef LINESENSOR_FLOAT_OFFSET
1437 xxxoffset = node->offset;
1438 xxxorigin = node->_origPoint.c[0];
1442 xxxoffset = vecdot3f(node->direction.c,node->offset.c);
1443 xxxorigin = vecdot3f(node->direction.c,node->_origPoint.c);
1448 if (node->maxPosition >= node->minPosition) {
1449 if (xxx < node->minPosition) {
1450 xxx = node->minPosition;
1452 else if (xxx > node->maxPosition) {
1453 xxx = node->maxPosition;
1457 vecscale3f(translation, node->direction.c, xxx);
1459#ifndef LINESENSOR_FLOAT_OFFSET
1462 vecscale3f(diroffset, node->direction.c, xxxoffset);
1464 vecdif3f(nondiroffset, node->offset.c, diroffset);
1466 vecadd3f(translation, translation, nondiroffset);
1469 veccopy3f(node->_oldtranslation.c,translation);
1471 if(!approx3f(node->_oldtranslation.c, node->translation_changed.c)) {
1472 veccopy3f(node->translation_changed.c, node->_oldtranslation.c);
1473 MARK_EVENT(ptr, offsetof(
struct X3D_LineSensor, translation_changed));
1476 node->_origPoint.c[1] = xxx;
1478 else if (ev == ButtonRelease) {
1480 node->isActive = FALSE;
1484 if (node->autoOffset) {
1485#ifdef LINESENSOR_FLOAT_OFFSET
1486 node->offset = node->_origPoint.c[1];
1488 veccopy3f(node->offset.c,node->translation_changed.c);
1497void do_PointSensor(
void *ptr,
int ev,
int but1,
int over) {
1508 float trackpoint[3], translation[3], *posn, *rposn, *norm;
1513 printf(
"%lf: TS ", TickTime());
1514 if (ev == ButtonPress) printf(
"ButtonPress ");
1515 else if (ev == ButtonRelease) printf(
"ButtonRelease ");
1516 else if (ev == KeyPress) printf(
"KeyPress ");
1517 else if (ev == KeyRelease) printf(
"KeyRelease ");
1518 else if (ev == MotionNotify) printf(
"%lf MotionNotify ");
1519 else printf(
"ev %d ", ev);
1521 if (but1) printf(
"but1 TRUE ");
else printf(
"but1 FALSE ");
1522 if (over) printf(
"over TRUE ");
else printf(
"over FALSE ");
1529 if (node->__oldEnabled != node->enabled) {
1530 node->__oldEnabled = node->enabled;
1531 MARK_EVENT(X3D_NODE(node), offsetof(
struct X3D_PointSensor, enabled));
1533 if (!node->enabled)
return;
1538 norm = tg->RenderFuncs.hyp_save_norm;
1539 posn = tg->RenderFuncs.hyp_save_posn;
1540 rposn = tg->RenderFuncs.ray_save_posn;
1542 if ((ev == ButtonPress) && but1) {
1545 float distance = veclength3f(vecdif3f(tt,rposn,norm));
1547 veccopy3f(trackpoint,rposn);
1548 veccopy3f(node->_origPoint.c,trackpoint);
1551 node->isActive = TRUE;
1555 else if ((ev == MotionNotify) && (node->isActive) && but1) {
1567 veccopy3f(trackpoint,rposn);
1569 veccopy3f(node->_oldtrackPoint.c,trackpoint);
1570 if(!approx3f(node->_oldtrackPoint.c, node->trackPoint_changed.c)) {
1571 veccopy3f(node->trackPoint_changed.c, node->_oldtrackPoint.c);
1572 MARK_EVENT(ptr, offsetof(
struct X3D_PointSensor, trackPoint_changed));
1575 vecdif3f(v1, norm, posn);
1576 vecnormalize3f(v1, v1);
1581 if (!line_intersect_plane_3f(posn,v1,tg->RenderFuncs.camera_axis,node->_origPoint.c,translation,NULL))
1584 if (node->autoOffset){
1585 vecadd3f(translation,translation,node->offset.c);
1590 vecclamp3f(translation,node->minPosition.c,node->maxPosition.c);
1592 veccopy3f(node->_oldtranslation.c,translation);
1594 if(!approx3f(node->_oldtranslation.c, node->translation_changed.c)) {
1595 veccopy3f(node->translation_changed.c, node->_oldtranslation.c);
1596 MARK_EVENT(ptr, offsetof(
struct X3D_PointSensor, translation_changed));
1599 else if (ev == ButtonRelease) {
1601 node->isActive = FALSE;
1604 if (node->autoOffset) {
1605 veccopy3f(node->offset.c,node->translation_changed.c);
1613void do_PlaneSensor (
void *ptr,
int ev,
int but1,
int over) {
1615 float mult, nx, ny, trackpoint[3], inverserotation[4], *posn;
1623 ConsoleMessage(
"%lf: TS ",TickTime());
1624 if (ev==ButtonPress) ConsoleMessage(
"ButtonPress ");
1625 else if (ev==ButtonRelease) ConsoleMessage(
"ButtonRelease ");
1626 else if (ev==KeyPress) ConsoleMessage(
"KeyPress ");
1627 else if (ev==KeyRelease) ConsoleMessage(
"KeyRelease ");
1628 else if (ev==MotionNotify) ConsoleMessage(
"MotionNotify ");
1629 else ConsoleMessage(
"ev %d ",ev);
1631 if (but1) ConsoleMessage(
"but1 TRUE ");
else ConsoleMessage(
"but1 FALSE ");
1632 if (over) ConsoleMessage(
"over TRUE ");
else ConsoleMessage(
"over FALSE ");
1633 ConsoleMessage (
"\n");
1639 if (node->__oldEnabled != node->enabled) {
1640 node->__oldEnabled = node->enabled;
1641 MARK_EVENT(X3D_NODE(node),offsetof (
struct X3D_PlaneSensor, enabled));
1643 if (!node->enabled)
return;
1650 float N[3] = { 0.0f, 0.0f, 1.0f };
1655 vecnormalize3f(v, vecdif3f(t1, tg->RenderFuncs.hyp_save_norm, tg->RenderFuncs.hyp_save_posn));
1657 axisangle_rotate3f(NS,N, node->axisRotation.c);
1660 posn = tg->RenderFuncs.hyp_save_posn;
1661 if (!line_intersect_planed_3f(posn, v, NS, 0.0f, trackpoint, NULL))
1665 veccopy4f(inverserotation,node->axisRotation.c);
1666 inverserotation[3] = -inverserotation[3];
1670 if ((ev==ButtonPress) && but1) {
1674 posn = tg->RenderFuncs.hyp_save_posn;
1676 veccopy3f(op.c, trackpoint);
1677 memcpy((
void *)&node->_origPoint, (
void *)&op,
sizeof(
struct SFColor));
1678 veccopy3f(node->_origPoint.c,op.c);
1681 node->isActive=TRUE;
1684 }
else if ((ev==MotionNotify) && (node->isActive) && but1) {
1686 nx = trackpoint[0]; ny = trackpoint[1];
1688 ConsoleMessage (
"now, mult %f nx %f ny %f op %f %f %f\n",mult,nx,ny,
1689 node->_origPoint.c[0],node->_origPoint.c[1],
1690 node->_origPoint.c[2]);
1694 if(!node->sensorLocalOutput){
1695 axisangle_rotate3f(trackpoint,trackpoint, inverserotation);
1698 veccopy3f(node->_oldtrackPoint.c, trackpoint);
1700 if(!approx3f(node->_oldtrackPoint.c,node->trackPoint_changed.c)) {
1701 veccopy3f(node->trackPoint_changed.c, node->_oldtrackPoint.c);
1702 MARK_EVENT(ptr, offsetof (
struct X3D_PlaneSensor, trackPoint_changed));
1707 tr[0] = nx - node->_origPoint.c[0] + node->offset.c[0];
1708 tr[1] = ny - node->_origPoint.c[1] + node->offset.c[1];
1709 tr[2] = node->offset.c[2];
1711 vecclamp2f(tr,node->minPosition.c,node->maxPosition.c);
1712 if(!node->sensorLocalOutput){
1713 axisangle_rotate3f(tr,tr, node->axisRotation.c);
1715 veccopy3f(node->_oldtranslation.c,tr);
1717 if(!approx3f(node->_oldtranslation.c,node->translation_changed.c)) {
1718 veccopy3f(node->translation_changed.c, (
void *) node->_oldtranslation.c);
1719 MARK_EVENT(ptr, offsetof (
struct X3D_PlaneSensor, translation_changed));
1722 }
else if (ev==ButtonRelease) {
1724 node->isActive=FALSE;
1728 if (node->autoOffset) {
1729 veccopy3f(node->offset.c,node->translation_changed.c);
1739void do_Anchor (
void *ptr,
int ev,
int but1,
int over) {
1747 if (ev==ButtonRelease) {
1750 if (node->url.n < 1)
return;
1751 setAnchorsAnchor( node );
1753 OLDCODE FREE_IF_NZ(tg->RenderFuncs.OSX_replace_world_from_console);
1756 tg->RenderFuncs.BrowserAction = TRUE;
1772void do_CylinderSensor (
void *ptr,
int ev,
int but1,
int over) {
1775 double rot, radius, ang, length;
1776 double det, pos, neg, temp;
1777 double acute_angle, disk_angle, height;
1778 float Y[3] = { 0.0f, 1.0f, 0.0f }, ZERO[3] = { 0.0f, 0.0f, 0.0f };
1779 float aBearing[3], bBearing[3], dirBearing[3], posn[3], axisRotation[4];
1781 GLDOUBLE modelMatrix[16];
1788 if (node->__oldEnabled != node->enabled) {
1789 node->__oldEnabled = node->enabled;
1792 if (!node->enabled)
return;
1801 veccopy4f(axisRotation,node->axisRotation.c);
1802 axisRotation[3] = -axisRotation[3];
1805 axisangle_rotate3f(aBearing, tg->RenderFuncs.hyp_save_posn, axisRotation);
1806 axisangle_rotate3f(bBearing, tg->RenderFuncs.hyp_save_norm, axisRotation);
1807 vecnormalize3f(dirBearing, vecdif3f(dirBearing, bBearing, aBearing));
1808 axisangle_rotate3f(posn,tg->RenderFuncs.ray_save_posn, axisRotation);
1810 if (ev==ButtonPress) {
1822 dot = vecdot3f(dirBearing, Y);
1823 dot = fclamp(dot,-1.0f,1.0f);
1824 acute_angle = acos(dot);
1825 ang = min(acute_angle,PI - acute_angle);
1827 veccopy3f(rs, posn);
1832 radius = veclength3f(rs);
1833 vecnormalize3f(rs, rs);
1834 if (ang < node->diskAngle){
1836 node->_usingDisk = TRUE;
1837 disk_angle = -atan2(rs[2], rs[0]);
1838 printf(
"using disk\n");
1841 node->_usingDisk = FALSE;
1843 float travelled, cylpoint[3], axispoint[3], dif[3];
1844 line_intersect_line_3f(aBearing, dirBearing, ZERO, Y, NULL, NULL, cylpoint, axispoint);
1846 travelled = veclength3f(vecdif3f(dif, cylpoint, axispoint));
1850 if (det3f(dirBearing, dif, Y) > 0.0f) travelled = -travelled;
1851 disk_angle = travelled / (2.0f * PI * radius) * (2.0f * PI);
1853 node->_radius = (float)radius;
1858 node->_origPoint.c[0] = disk_angle;
1859 node->_origPoint.c[1] = -height;
1863 node->isActive=TRUE;
1866 }
else if ((ev == MotionNotify) && (node->isActive)) {
1867 float trackpoint[3], rotation4f[4];
1871 veccopy3f(trackpoint,node->_oldtrackPoint.c);
1877 float diskpoint[3], orig_diskangle, height;
1878 height = node->_origPoint.c[1];
1879 radius = node->_radius;
1880 orig_diskangle = node->_origPoint.c[0];
1881 if (node->_usingDisk == TRUE) {
1883 line_intersect_planed_3f(aBearing, dirBearing, Y, height, diskpoint, NULL);
1884 veccopy3f(trackpoint,diskpoint);
1885 vecnormalize3f(diskpoint, diskpoint);
1887 disk_angle = -atan2(diskpoint[2], diskpoint[0]);
1896 float travelled, axispoint[3], dif[3];
1897 line_intersect_line_3f(aBearing, dirBearing, ZERO, Y, NULL, NULL, cylpoint, axispoint);
1901 travelled = veclength3f(vecdif3f(dif, cylpoint, axispoint));
1902 if (det3f(dirBearing, dif, Y) > 0.0f) travelled = -travelled;
1904 disk_angle = travelled / (2.0f * PI * radius) * (2.0f * PI);
1905 if(!line_intersect_cylinder_3f(aBearing,dirBearing,node->_radius,trackpoint))
1906 veccopy3f(trackpoint,cylpoint);
1909 rot = disk_angle - orig_diskangle;
1911 if (node->autoOffset) {
1913 rot = node->offset + rot;
1917 if (node->minAngle < node->maxAngle) {
1918 rot = fclamp(rot,node->minAngle,node->maxAngle);
1922 vecset4f(rotation4f,0.0f,1.0f,0.0f,(
float)rot);
1924 if(!node->sensorLocalOutput){
1926 axisangle_rotate3f(rotation4f,rotation4f,node->axisRotation.c);
1928 veccopy4f(node->_oldrotation.c,rotation4f);
1929 if(!approx4f(node->_oldrotation.c,node->rotation_changed.c)) {
1930 veccopy4f(node->rotation_changed.c, node->_oldrotation.c);
1936 if(!node->sensorLocalOutput)
1937 axisangle_rotate3f(trackpoint, trackpoint, node->axisRotation.c);
1938 veccopy3f(node->_oldtrackPoint.c,trackpoint);
1939 if(!approx3f(node->_oldtrackPoint.c, node->trackPoint_changed.c)) {
1940 veccopy3f(node->trackPoint_changed.c, node->_oldtrackPoint.c);
1944 }
else if (ev==ButtonRelease) {
1946 node->isActive=FALSE;
1949 if (node->autoOffset) {
1950 node->offset = node->rotation_changed.c[3];
1960float fwfdsign(
float x){
return x >= 0.0f ? 1.0f : -1.0f; }
1962void do_CylinderSensor_simple (
void *ptr,
int ev,
int but1,
int over) {
1967 float *cur, *orig, onorm[3];
1974 if (node->__oldEnabled != node->enabled) {
1975 node->__oldEnabled = node->enabled;
1985 cur = tg->RenderFuncs.ray_save_posn;
1986 orig = node->_origPoint.c;
1987 veccopy3f(onorm,orig);
1989 vecnormalize3f(onorm,onorm);
1990 if (ev==ButtonPress) {
1992 float pcur[3], height;
1993 veccopy3f(orig,cur);
1996 veccopy3f(pcur,cur);
1999 node->_radius = veclength3f(pcur);
2000 if (APPROX(node->_radius,0.0)) {
2001 printf (
"warning, RADIUS %lf == 0, can not compute\n",node->_radius);
2009 node->isActive=TRUE;
2011 }
else if (ev==ButtonRelease) {
2013 node->isActive=FALSE;
2016 if (node->autoOffset) {
2017 node->offset = node->rotation_changed.c[3];
2019 }
else if ((ev==MotionNotify) && (node->isActive)) {
2021 float dotProd, sine, angle;
2025 float pcur[3], height;
2029 veccopy3f(pcur,cur);
2031 newRad = veclength3f(pcur);
2033 if (APPROX(newRad,0.0)) {
2034 printf (
"warning, newRad %lf == 0, can not compute\n",newRad);
2040 vecnormalize3f(cnorm,pcur);
2043 veccross3f(newAxis,onorm,cnorm);
2044 sine = veclength3f(newAxis);
2049 dotProd = vecdot3f(onorm,cnorm);
2050 dotProd = fclamp(dotProd,-1.0f,1.0f);
2051 angle = acos(dotProd) * fwfdsign(newAxis[1]);
2058 if(node->autoOffset)
2060 angle += node->offset;
2061 angle = atan2(sin(angle),cos(angle));
2066 vecset3f(node->rotation_changed.c,0.0f,1.0f,0.0f);
2067 node->rotation_changed.c[3] = angle;
2070 vecscale3f(node->trackPoint_changed.c,cnorm, node->_radius);
2071 node->trackPoint_changed.c[1] = height;
2088void do_SphereSensor (
void *ptr,
int ev,
int but1,
int over) {
2091 float *cur, *orig, *onorm;
2098 if (node->__oldEnabled != node->enabled) {
2099 node->__oldEnabled = node->enabled;
2109 cur = tg->RenderFuncs.ray_save_posn;
2110 orig = node->_origPoint.c;
2111 onorm = node->_origNormalizedPoint.c;
2112 if (ev==ButtonPress) {
2114 veccopy3f(orig,cur);
2118 node->_radius = veclength3f(cur);
2119 if (APPROX(node->_radius,0.0)) {
2120 printf (
"warning, RADIUS %lf == 0, can not compute\n",node->_radius);
2125 vecscale3f(onorm,cur,1.0f / node->_radius);
2130 vrmlrot_normalize(node->offset.c);
2133 node->isActive=TRUE;
2135 }
else if (ev==ButtonRelease) {
2137 node->isActive=FALSE;
2140 if (node->autoOffset) {
2141 veccopy4f(node->offset.c,node->rotation_changed.c);
2143 }
else if ((ev==MotionNotify) && (node->isActive)) {
2151 newRad = veclength3f(cur);
2153 if (APPROX(newRad,0.0)) {
2154 printf (
"warning, newRad %lf == 0, can not compute\n",newRad);
2159 vecscale3f(cnorm,cur,1.0f/newRad);
2162 veccross3f(newA,orig,cur);
2163 vecnormalize3f(newA,newA);
2168 dotProd = vecdot3f(onorm,cnorm);
2173 dotProd = acos(dotProd);
2181 if(node->autoOffset)
2188 vrmlrot_to_quaternion(&q1, (
double) newA[0],
2189 (
double) newA[1], (
double) newA[2], (
double) dotProd);
2190 vrmlrot_to_quaternion(&q2, (
double) node->offset.c[0],
2191 (
double) node->offset.c[1], (
double) node->offset.c[2], (
double) node->offset.c[3]);
2193 quaternion_multiply(&qret,&q1,&q2);
2195 quaternion_to_vrmlrot(&qret, &newD[0], &newD[1], &newD[2], &newD[3]);
2196 newA[0] = newD[0]; newA[1] = newD[1], newA[2] = newD[2], newA[3] = newD[3];
2202 veccopy4f(node->rotation_changed.c,newA);
2205 vecscale3f(node->trackPoint_changed.c,cnorm, node->_radius);