Tachyon (current)  Current Main Branch
spaceball.c
Go to the documentation of this file.
1 /*
2  * spaceball.c - code to perform camera fly-throughs using a spaceball
3  *
4  * (C) Copyright 1994-2022 John E. Stone
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * $Id: spaceball.c,v 1.8 2022/02/18 18:18:36 johns Exp $
8  *
9  */
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <string.h>
15 #if !defined(_MSC_VER)
16 #include <unistd.h>
17 #endif
18 
19 #include "trackball.h" /* quaternion code */
20 #include "tachyon.h" /* main ray tracer api headers */
21 #include "spaceball.h" /* protos for this file */
22 #include "glwin.h" /* windowing system spaceball events */
23 
24 #if defined(USESPACEBALL)
25 #include "sball.h" /* spaceball code */
26 #endif
27 
28 void * tachyon_init_spaceball(SceneHandle scene, void *glwin, char * serialport) {
29  sbHandle * bh;
30 
31  bh = (sbHandle *) malloc(sizeof(sbHandle));
32  if (bh == NULL) {
33  return NULL;
34  }
35 
36  memset(bh, 0, sizeof(sbHandle));
37  bh->glwin = glwin; /* windowing system handle */
38 #if defined(USESPACEBALL)
39  if (port != NULL) {
40  bh->sball = sball_open(serialport);
41  if (bh->sball == NULL) {
42  free(bh);
43  return NULL;
44  }
45  }
46 #endif
47 
49 
50  bh->camcent = bh->orig_camcent;
51  bh->camviewvec = bh->orig_camviewvec;
52  bh->camupvec = bh->orig_camupvec;
53  trackball(bh->curquat, 0.0, 0.0, 0.0, 0.0);
54  trackball(bh->lastquat, 0.0, 0.0, 0.0, 0.0);
55 
56  return bh;
57 }
58 
59 
61  int tx, ty, tz, rx, ry, rz, buttons, buttonchanged;
62  int win_event = 0;
63  int direct_event = 0;
64 
65  float qq[4]={0.0, 0.0, 0.0, 1.0};
66  float xx[3]={1.0, 0.0, 0.0};
67  float yy[3]={0.0, 1.0, 0.0};
68  float zz[3]={0.0, 0.0, 1.0};
69 
70  float m[4][4];
71  float t[3];
72 
73  static float transdivisor = 5000.0;
74  static float angdivisor = 20000.0;
75 
76  /* explicitly initialize event state variables */
77  rx=ry=rz=tx=ty=tz=buttons=0;
78 
79  if (glwin_get_spaceball(bh->glwin, &rx, &ry, &rz, &tx, &ty, &tz, &buttons)) {
80  win_event = 1;
81  }
82 
83 #if defined(USESPACEBALL)
84  if (bh->sball != NULL) {
85  int rx2, ry2, rz2, tx2, ty2, tz2, buttons2;
86  if (sball_getstatus(bh->sball, &tx2, &ty2, &tz2, &rx2, &ry2, &rz2, &buttons2) {
87  direct_event = 1;
88  rx += rx2;
89  ry += ry2;
90  rz += rz2;
91  tx += tx2;
92  ty += ty2;
93  tz += tz2;
94  buttons |= buttons2;
95  }
96  }
97 #endif
98 
99  if (!win_event && !direct_event) {
100  /* usleep(5); */ /* if no movement then sleep for a tiny bit.. */
101  return 0; // no events to report
102  }
103 
104  /* find which buttons changed state */
105  buttonchanged = buttons ^ bh->buttondown;
106 
107  /* negate rotations given by spaceball */
108  rx = -rx;
109  ry = -ry;
110  rz = -rz;
111 
112 #if defined(USESPACEBALL)
113  if ((buttonchanged & SBALL_BUTTON_PICK) && (buttons & SBALL_BUTTON_PICK)) ||
114  (buttonchanged & SBALL_BUTTON_1) && (buttons & SBALL_BUTTON_1)) ||
115  (buttonchanged & SBALL_BUTTON_LEFT) && (buttons & SBALL_BUTTON_LEFT)) ) {
116 
117 #else
118  if ((buttonchanged & 1) && (buttons & 1)) {
119 #endif
120  bh->curtrans[0] = 0.0;
121  bh->curtrans[1] = 0.0;
122  bh->curtrans[2] = 0.0;
123  trackball(bh->curquat, 0.0, 0.0, 0.0, 0.0);
124  trackball(bh->lastquat, 0.0, 0.0, 0.0, 0.0);
125  transdivisor = 5000.0;
126  angdivisor = 20000.0;
127 
128  bh->camviewvec = bh->orig_camviewvec;
129  bh->camupvec = bh->orig_camupvec;
130  bh->camcent = bh->orig_camcent;
131  }
132 
133 
134 #if defined(USESPACEBALL)
135  if (buttons & SBALL_BUTTON_1) {
136  transdivisor /= 1.2;
137  angdivisor /= 1.2;
138  }
139  else if (buttons & SBALL_BUTTON_2) {
140  transdivisor *= 1.2;
141  angdivisor *= 1.2;
142  }
143 
144  if (buttons & SBALL_BUTTON_3)
145  transdivisor /= 1.2;
146  else if (buttons & SBALL_BUTTON_4)
147  transdivisor *= 1.2;
148 
149  if (buttons & SBALL_BUTTON_5)
150  angdivisor *= 1.2;
151  else if (buttons & SBALL_BUTTON_6)
152  angdivisor /= 1.2;
153 
154  if (buttons & SBALL_BUTTON_7) {
155  return 1; /* quit the fly through */
156  }
157 #endif
158 
159  t[0] = tx / transdivisor;
160  t[1] = ty / transdivisor;
161  t[2] = tz / transdivisor;
162 
163  /*
164  * convert rotations and translations from the
165  * spaceball's coordinate frame into the camera's frame.
166  */
167  bh->newtrans[0] =
168  t[0] * bh->orig_camrightvec.x +
169  t[1] * bh->orig_camupvec.x +
170  t[2] * bh->orig_camviewvec.x;
171 
172  bh->newtrans[1] =
173  t[0] * bh->orig_camrightvec.y +
174  t[1] * bh->orig_camupvec.y +
175  t[2] * bh->orig_camviewvec.y;
176 
177  bh->newtrans[2] =
178  t[0] * bh->orig_camrightvec.z +
179  t[1] * bh->orig_camupvec.z +
180  t[2] * bh->orig_camviewvec.z;
181 
182  /*
183  * rotate around camera's coordinate frame
184  */
185  xx[0] = bh->orig_camrightvec.x;
186  xx[1] = bh->orig_camrightvec.y;
187  xx[2] = bh->orig_camrightvec.z;
188 
189  yy[0] = bh->orig_camupvec.x;
190  yy[1] = bh->orig_camupvec.y;
191  yy[2] = bh->orig_camupvec.z;
192 
193  zz[0] = bh->orig_camviewvec.x;
194  zz[1] = bh->orig_camviewvec.y;
195  zz[2] = bh->orig_camviewvec.z;
196 
197  /* do rotations */
198  axis_to_quat(xx, rx / angdivisor, bh->lastquat);
199 
200  axis_to_quat(yy, ry / angdivisor, qq);
201  add_quats(qq, bh->lastquat, bh->lastquat);
202 
203  axis_to_quat(zz, rz / angdivisor, qq);
204  add_quats(qq, bh->lastquat, bh->lastquat);
205 
206  add_quats(bh->lastquat, bh->curquat, bh->curquat);
207 
208  build_rotmatrix(m, bh->curquat);
209 
210  /*
211  * translate along the new axes
212  */
213  t[0] = m[0][0] * bh->newtrans[0] + m[0][1] * bh->newtrans[1] + m[0][2] * bh->newtrans[2];
214  t[1] = m[1][0] * bh->newtrans[0] + m[1][1] * bh->newtrans[1] + m[1][2] * bh->newtrans[2];
215  t[2] = m[2][0] * bh->newtrans[0] + m[2][1] * bh->newtrans[1] + m[2][2] * bh->newtrans[2];
216 
217  bh->camcent.x += t[0];
218  bh->camcent.y += t[1];
219  bh->camcent.z += t[2];
220 
221 
222  /*
223  * rotate view system with spaceball
224  */
225  bh->camviewvec.x = m[0][0] * bh->orig_camviewvec.x + m[0][1] * bh->orig_camviewvec.y + m[0][2] * bh->orig_camviewvec.z;
226  bh->camviewvec.y = m[1][0] * bh->orig_camviewvec.x + m[1][1] * bh->orig_camviewvec.y + m[1][2] * bh->orig_camviewvec.z;
227  bh->camviewvec.z = m[2][0] * bh->orig_camviewvec.x + m[2][1] * bh->orig_camviewvec.y + m[2][2] * bh->orig_camviewvec.z;
228 
229  bh->camupvec.x = m[0][0] * bh->orig_camupvec.x + m[0][1] * bh->orig_camupvec.y + m[0][2] * bh->orig_camupvec.z;
230  bh->camupvec.y = m[1][0] * bh->orig_camupvec.x + m[1][1] * bh->orig_camupvec.y + m[1][2] * bh->orig_camupvec.z;
231  bh->camupvec.z = m[2][0] * bh->orig_camupvec.x + m[2][1] * bh->orig_camupvec.y + m[2][2] * bh->orig_camupvec.z;
232 
233  /*
234  * update camera parameters before we render again
235  */
236  rt_camera_position(scene, bh->camcent, bh->camviewvec, bh->camupvec);
237 
238 #if defined(RT_ACCUMULATE_ON)
240 #endif
241 
242  return 0;
243 }
244 
245 
int tachyon_spaceball_update(sbHandle *bh, SceneHandle scene)
Definition: spaceball.c:60
void rt_get_camera_position(SceneHandle voidscene, apivector *camcent, apivector *viewvec, apivector *upvec, apivector *rightvec)
Get camera position and orientation.
Definition: api.c:273
apivector orig_camupvec
Definition: spaceball.h:29
void rt_accumulation_mode(SceneHandle voidscene, int mode)
Request Tachyon to use (or disuse) an internal floating point accumulation buffer, combining the newest frame with previously accumulated frames, normalizing the pixel values using an internal subframe counter.
Definition: api.c:457
float curtrans[3]
Definition: spaceball.h:32
int glwin_get_spaceball(void *voidhandle, int *rx, int *ry, int *rz, int *tx, int *ty, int *tz, int *buttons)
Definition: glwin.c:3408
void axis_to_quat(float a[3], float phi, float q[4])
Definition: trackball.c:206
apivector orig_camviewvec
Definition: spaceball.h:28
apivector camcent
Definition: spaceball.h:23
void * tachyon_init_spaceball(SceneHandle scene, void *glwin, char *serialport)
Definition: spaceball.c:28
apivector orig_camcent
Definition: spaceball.h:27
flt x
X coordinate or direction component.
Definition: tachyon.h:54
#define RT_ACCUMULATE_CLEAR
accum.
Definition: tachyon.h:350
flt y
Y coordinate or direction component.
Definition: tachyon.h:55
float curquat[4]
Definition: spaceball.h:34
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
Definition: trackball.c:160
float lastquat[4]
Definition: spaceball.h:35
void * glwin
Definition: spaceball.h:17
void * SceneHandle
Definition: tachyon.h:51
apivector camviewvec
Definition: spaceball.h:24
void add_quats(float q1[4], float q2[4], float dest[4])
Definition: trackball.c:247
apivector camupvec
Definition: spaceball.h:25
void build_rotmatrix(float m[4][4], float q[4])
Definition: trackball.c:302
int buttondown
Definition: spaceball.h:21
void rt_camera_position(SceneHandle voidscene, apivector camcent, apivector viewvec, apivector upvec)
Set camera position and orientation.
Definition: api.c:256
float newtrans[3]
Definition: spaceball.h:33
Tachyon public API function prototypes and declarations used to drive the ray tracing engine...
apivector orig_camrightvec
Definition: spaceball.h:30
flt z
Z coordinate or direction component.
Definition: tachyon.h:56