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