1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11 #include "cameraClass.h"
12
13 static Matrix Identity = {
14 {{ 1.0, 0.0, 0.0 },
15 { 0.0, 1.0, 0.0 },
16 { 0.0, 0.0, 1.0 }
17 }
18 };
19
20 /*
21 * Compute the camera matrix from the current parameters
22 */
23
24 #define ZERO(v) (v.x==0 && v.y==0 && v.z==0)
25
26 Camera
_dxfSetCameraProjection(Camera c,float * p)27 _dxfSetCameraProjection(Camera c, float *p)
28 {
29 Matrix t;
30
31 t.A[0][0] = p[ 0]; t.A[0][1] = p[ 1]; t.A[0][3] = p[ 2];
32 t.A[1][0] = p[ 4]; t.A[1][1] = p[ 5]; t.A[1][3] = p[ 6];
33 t.A[2][0] = p[ 8]; t.A[2][1] = p[ 9]; t.A[2][3] = p[10];
34 t.b[0] = p[12]; t.b[1] = p[13]; t.b[2] = p[14];
35
36 c->m = c->rot = t;
37 return c;
38 }
39
40
41 static Camera
matrix(Camera c)42 matrix(Camera c)
43 {
44 Vector xaxis, yaxis, zaxis, v;
45 Matrix t;
46 float xres;
47
48 /* compute resolution */
49 xres = c->resolution; /* yres = c->resolution*c->aspect/c->pix_aspect; */
50
51 /* translate to origin of camera coordinate system */
52 t = DXTranslate(DXNeg(c->from));
53
54 /* camera coordinate system axes */
55 v = DXSub(c->from, c->to);
56 if (ZERO(v))
57 DXErrorReturn(ERROR_BAD_PARAMETER,
58 "camera from and to points are identical");
59 zaxis = DXNormalize(v);
60 v = DXCross(c->up, zaxis);
61 if (ZERO(v))
62 DXErrorReturn(ERROR_BAD_PARAMETER, "degenerate camera up vector");
63 xaxis = DXNormalize(v);
64 yaxis = DXNormalize(DXCross(zaxis, xaxis));
65 t = DXConcatenate(t, DXMat(
66 xaxis.x, yaxis.x, zaxis.x,
67 xaxis.y, yaxis.y, zaxis.y,
68 xaxis.z, yaxis.z, zaxis.z,
69 0, 0, 0
70 ));
71 c->rot = t;
72
73 /*
74 * scaling to resolution
75 * In ortho case, we scale z similarly to x and y so that transformed
76 * objects retain their shape, so that e.g. volume rendering can
77 * look at voxel shape after transformation to determine what algorithm
78 * to use. Is this the best way to do this? XXX - what about
79 * perspective case? XXX - fails if pix_aspect is not 1
80 * XXX - undid this, because it distorts z values for volume
81 * rendering - how to handle this?
82 */
83 #if 1
84 if (c->width==0)
85 DXErrorReturn(ERROR_BAD_PARAMETER, "camera width is zero");
86 t = DXConcatenate(t, DXScale(xres/c->width, xres/c->width/c->pix_aspect, 1));
87 if (c->ortho) {
88 Vector xto;
89 xto = DXApply(c->to, t);
90 t.b[2] -= xto.z;
91 }
92 #else
93 if (c->ortho)
94 t = DXConcatenate(t, DXScale(
95 xres/c->width, xres/c->width/c->pix_aspect, xres/c->width));
96 else
97 t = DXConcatenate(t, DXScale(
98 xres/c->width, xres/c->width/c->pix_aspect, 1));
99 #endif
100 c->m = t;
101 return c;
102 }
103
104
105 /*
106 * Camera object
107 */
108
109 Camera
_NewCamera(struct camera_class * class)110 _NewCamera(struct camera_class *class)
111 {
112 Camera c = (Camera) _dxf_NewObject((struct object_class *)class);
113 if (!c)
114 return NULL;
115
116 c->from = DXPt(0,0,1);
117 c->to = DXPt(0,0,0);
118 c->up = DXVec(0,1,0);
119 c->ortho = 1;
120 c->width = 2; /* XXX - +/- 1 */
121 c->aspect = 3.0/4.0;
122 c->pix_aspect = 1;
123 c->resolution = 640;
124 c->background.r = 0.0;
125 c->background.g = 0.0;
126 c->background.b = 0.0;
127 return matrix(c);
128 }
129
130 Camera
DXNewCamera()131 DXNewCamera()
132 {
133 return _NewCamera(&_dxdcamera_class);
134 }
135
136 int
_dxfCamera_Delete(Camera c)137 _dxfCamera_Delete(Camera c)
138 {
139 return OK;
140 }
141
142
143 Object
_dxfCamera_Copy(Camera old,enum _dxd_copy copy)144 _dxfCamera_Copy(Camera old, enum _dxd_copy copy)
145 {
146 Camera new;
147 new = DXNewCamera();
148 if (!new)
149 return NULL;
150 if (!_dxf_CopyObject((Object)new, (Object)old, copy))
151 return NULL;
152 new->from = old->from;
153 new->to = old->to;
154 new->up = old->up;
155 new->ortho = old->ortho;
156 new->width = old->width;
157 new->aspect = old->aspect;
158 new->pix_aspect = old->pix_aspect;
159 new->resolution = old->resolution;
160 new->m = old->m;
161 new->rot = old->rot;
162 new->background = old->background;
163 return (Object)new;
164 }
165
166
167 Camera
DXSetView(Camera c,Point from,Point to,Vector up)168 DXSetView(Camera c, Point from, Point to, Vector up)
169 {
170 CHECK(c, CLASS_CAMERA);
171
172 c->from = from;
173 c->to = to;
174 c->up = up;
175 return matrix(c);
176 }
177
178 Camera
DXSetPerspective(Camera c,double fov,double aspect)179 DXSetPerspective(Camera c, double fov, double aspect)
180 {
181 CHECK(c, CLASS_CAMERA);
182
183 c->width = fov;
184 c->aspect = aspect;
185 c->ortho = 0;
186 return matrix(c);
187 }
188
189 Camera
DXSetOrthographic(Camera c,double width,double aspect)190 DXSetOrthographic(Camera c, double width, double aspect)
191 {
192 CHECK(c, CLASS_CAMERA);
193
194 c->width = width;
195 c->aspect = aspect;
196 c->ortho = 1;
197 return matrix(c);
198 }
199
200 Camera
DXSetResolution(Camera c,int hres,double pix_aspect)201 DXSetResolution(Camera c, int hres, double pix_aspect)
202 {
203 CHECK(c, CLASS_CAMERA);
204
205 c->resolution = hres;
206 c->pix_aspect = pix_aspect;
207 return matrix(c);
208 }
209
210 /*
211 * Access routines
212 */
213
214 Matrix
DXGetCameraMatrix(Camera c)215 DXGetCameraMatrix(Camera c)
216 {
217 return c? c->m : Identity;
218 }
219
220
221 Matrix
DXGetCameraMatrixWithFuzz(Camera c,float fuzz)222 DXGetCameraMatrixWithFuzz(Camera c, float fuzz)
223 {
224 Matrix m;
225 if (!c) {
226 m = Identity;
227 m.b[2] = fuzz;
228 } else {
229 m = c->m;
230 if (c->ortho) {
231 m = c->m;
232 m.b[2] += fuzz*c->width/c->resolution;
233 } else {
234 float f = 1.0 - fuzz*c->width/c->resolution;
235 m.A[0][0] *= f; m.A[0][1] *= f; m.A[0][2] *= f;
236 m.A[1][0] *= f; m.A[1][1] *= f; m.A[1][2] *= f;
237 m.A[2][0] *= f; m.A[2][1] *= f; m.A[2][2] *= f;
238 m.b[0] *= f; m.b[1] *= f; m.b[2] *= f;
239 }
240 }
241 return m;
242 }
243
244 Matrix
DXGetCameraRotation(Camera c)245 DXGetCameraRotation(Camera c)
246 {
247 return c? c->rot : Identity;
248 }
249
250
251 Camera
DXGetCameraResolution(Camera c,int * width,int * height)252 DXGetCameraResolution(Camera c, int *width, int *height)
253 {
254 CHECK(c, CLASS_CAMERA);
255
256 if (width)
257 *width = c->resolution;
258 if (height)
259 *height = c->resolution*c->aspect;
260
261 return c;
262 }
263
264 Camera
DXGetView(Camera c,Point * from,Point * to,Vector * up)265 DXGetView(Camera c, Point *from, Point *to, Vector *up)
266 {
267 CHECK(c, CLASS_CAMERA);
268 if (from)
269 *from = c->from;
270 if (to)
271 *to = c->to;
272 if (up)
273 *up = c->up;
274 return c;
275 }
276
277 Camera
DXGetPerspective(Camera c,float * fov,float * aspect)278 DXGetPerspective(Camera c, float *fov, float *aspect)
279 {
280 CHECK(c, CLASS_CAMERA);
281
282 if (c->ortho)
283 return NULL;
284 if (fov)
285 *fov = c->width;
286 if (aspect)
287 *aspect = c->aspect;
288
289 return c;
290 }
291
292 Camera
DXGetOrthographic(Camera c,float * width,float * aspect)293 DXGetOrthographic(Camera c, float *width, float *aspect)
294 {
295 CHECK(c, CLASS_CAMERA);
296
297 if (!c->ortho)
298 return NULL;
299 if (width)
300 *width = c->width;
301 if (aspect)
302 *aspect = c->aspect;
303
304 return c;
305 }
306
307 Camera
DXSetBackgroundColor(Camera c,RGBColor b)308 DXSetBackgroundColor(Camera c, RGBColor b)
309 {
310 CHECK(c, CLASS_CAMERA);
311
312 c->background = b;
313
314 return c;
315 }
316
317 Camera
DXGetBackgroundColor(Camera c,RGBColor * b)318 DXGetBackgroundColor(Camera c, RGBColor *b)
319 {
320 CHECK(c, CLASS_CAMERA);
321
322 *b = c->background;
323
324 return c;
325 }
326