1 | /***************************************
2 | $Header: /cvsroot/petscgraphics/render.c,v 1.5 2004/08/17 15:05:56 hazelsct Exp $
3 |
4 | This file contains the rendering code for Illuminator, which renders 2-D or
5 | 3-D data into an RGB(A) unsigned char array (using perspective in 3-D).
6 | ***************************************/
7 |
8 | #include "illuminator.h"
9 |
10 |
11 | #undef __FUNCT__
12 | #define __FUNCT__ "pseudocolor"
13 |
14 | /*++++++++++++++++++++++++++++++++++++++
15 | This little function converts a scalar value into an rgb color from red to
16 | blue.
17 |
18 | PetscScalar val Value to convert.
19 |
20 | PetscScalar* minmax Array with minimum and maximum values in which to scale
21 | val.
22 |
23 | guchar *pixel Address in rgb buffer where this pixel should be painted.
24 | ++++++++++++++++++++++++++++++++++++++*/
25 |
26 | static inline void pseudocolor (PetscScalar val, PetscScalar* minmax,
27 | guchar *pixel)
28 | {
29 | PetscScalar shade = (val - minmax[0]) / (minmax[1] - minmax[0]);
30 | /* Old stuff *
31 | if (shade < 0.2) { /* red -> yellow *
32 | *pixel++ = 255;
33 | *pixel++ = 1275*shade;
34 | *pixel++ = 0; }
35 | else if (shade < 0.4) { /* yellow -> green *
36 | *pixel++ = 510-1275*shade;
37 | *pixel++ = 255;
38 | *pixel++ = 0; }
39 | else if (shade < 0.6) { /* green -> cyan *
40 | *pixel++ = 0;
41 | *pixel++ = 255;
42 | *pixel++ = 1275*shade-510; }
43 | else if (shade < 0.8) { /* cyan -> blue *
44 | *pixel++ = 0;
45 | *pixel++ = 1020-1275*shade;
46 | *pixel++ = 255; }
47 | else { /* blue -> magenta *
48 | *pixel++ = 1275*shade-1020;
49 | *pixel++ = 0;
50 | *pixel++ = 255; }
51 | /* New stuff */
52 | if (shade < 0.25) { /* red -> yellow */
53 | *pixel++ = 255;
54 | *pixel++ = 1020*shade;
55 | *pixel++ = 0; }
56 | else if (shade < 0.5) { /* yellow -> green */
57 | *pixel++ = 510-1020*shade;
58 | *pixel++ = 255;
59 | *pixel++ = 0; }
60 | else if (shade < 0.75) { /* green -> cyan */
61 | *pixel++ = 0;
62 | *pixel++ = 255;
63 | *pixel++ = 1020*shade-510; }
64 | else { /* cyan -> blue */
65 | *pixel++ = 0;
66 | *pixel++ = 1020-1020*shade;
67 | *pixel++ = 255; }
68 | }
69 |
70 |
71 | #undef __FUNCT__
72 | #define __FUNCT__ "pseudohueintcolor"
73 |
74 | /*++++++++++++++++++++++++++++++++++++++
75 | This little function converts a vector into an rgb color with hue indicating
76 | direction (green, yellow, red, blue at 0, 90, 180, 270 degrees) and intensity
77 | indicating magnitude relative to reference magnitude in minmax[1].
78 |
79 | PetscScalar vx Vector's
80 | +latex+$x$-component.
81 | +html+ <i>x</i>-component.
82 |
83 | PetscScalar vy Vector's
84 | +latex+$y$-component.
85 | +html+ <i>y</i>-component.
86 |
87 | PetscScalar *minmax Array whose second entry has the reference magnitude.
88 |
89 | guchar *pixel Address in rgb buffer where this pixel should be painted.
90 | ++++++++++++++++++++++++++++++++++++++*/
91 |
92 | static inline void pseudohueintcolor
93 | (PetscScalar vx, PetscScalar vy, PetscScalar *minmax, guchar *pixel)
94 | {
95 | PetscScalar mag=sqrt(vx*vx+vy*vy), theta=atan2(vy,vx), red, green, blue;
96 | if (minmax[1] <= 0.)
97 | {
98 | *pixel = *(pixel+1) = *(pixel+2) = 0;
99 | return;
100 | }
101 | mag = (mag > minmax[1]) ? 1.0 : mag/minmax[1];
102 |
103 | red = 2./M_PI * ((theta<-M_PI/2.) ? -M_PI/2.-theta :
104 | ((theta<0.) ? 0. : ((theta<M_PI/2.) ? theta : M_PI/2.)));
105 | green = 2./M_PI * ((theta<-M_PI/2.) ? 0. :
106 | ((theta<0.) ? theta+M_PI/2. :
107 | ((theta<M_PI/2.) ? M_PI/2. : M_PI-theta)));
108 | blue = 2./M_PI * ((theta<-M_PI/2.) ? theta+M_PI :
109 | ((theta<0.) ? -theta : 0.));
110 |
111 | *pixel++ = 255*mag*red;
112 | *pixel++ = 255*mag*green;
113 | *pixel++ = 255*mag*blue;
114 | }
115 |
116 | #undef __FUNCT__
117 | #define __FUNCT__ "pseudoternarycolor"
118 |
119 | /*++++++++++++++++++++++++++++++++++++++
120 | This little function converts two ternary fractions into an rgb color, with
121 | yellow, cyan and magenta indicating the corners.
122 |
123 | PetscScalar A First ternary fraction.
124 |
125 | PetscScalar B Second ternary fraction.
126 |
127 | PetscScalar *minmax Array first and second ternary fractions of each of the
128 | three corner values for scaling.
129 |
130 | guchar *pixel Address in rgb buffer where this pixel should be painted.
131 | ++++++++++++++++++++++++++++++++++++++*/
132 |
133 | static inline void pseudoternarycolor
134 | (PetscScalar A, PetscScalar B, PetscScalar *minmax, guchar *pixel)
135 | {
136 | PetscScalar x1, x2, inverse_det;
137 |
138 | /* Transform A,B into x1,x2 based on corners */
139 | inverse_det = 1./((minmax[2]-minmax[0])*(minmax[5]-minmax[1]) -
140 | (minmax[4]-minmax[0])*(minmax[3]-minmax[1]));
141 | x1 = ((A-minmax[0])*(minmax[5]-minmax[1]) -
142 | (B-minmax[1])*(minmax[4]-minmax[0])) * inverse_det;
143 | x2 = ((B-minmax[1])*(minmax[2]-minmax[0]) -
144 | (A-minmax[0])*(minmax[3]-minmax[1])) * inverse_det;
145 |
146 | /* Now colorize */
147 | *pixel++ = 255*(1.-x1);
148 | *pixel++ = 255*(x1+x2);
149 | *pixel++ = 255*(1.-x2);
150 | }
151 |
152 |
153 | #undef __FUNCT__
154 | #define __FUNCT__ "render_rgb_local_2d"
155 |
156 | /*++++++++++++++++++++++++++++++++++++++
157 | Render data from global_array into local part of an RGB buffer. When running
158 | in parallel, these local buffers should be collected and layered to produce
159 | the full image.
160 |
161 | int render_rgb_local_2d Returns zero or an error code.
162 |
163 | guchar *rgb RGB buffer in which to render.
164 |
165 | int rwidth Total width of the RGB buffer.
166 |
167 | int rheight Total height of the RGB buffer.
168 |
169 | int bytes_per_pixel Number of bytes per pixel in this RGB buffer (typically 3
170 | or 4).
171 |
172 | PetscScalar *global_array Local array of global vector data to render.
173 |
174 | int num_fields Number of field variables in the array.
175 |
176 | int display_field The (first) field we are rendering now.
177 |
178 | field_plot_type fieldtype The type of this field.
179 |
180 | PetscScalar *minmax Array of minimum and maximum values to pass to the
181 | various pseudocolor functions; if NULL, call minmax_scale to determine those
182 | values.
183 |
184 | int nx Width of the array.
185 |
186 | int ny Height of the array.
187 |
188 | int xs Starting
189 | +latex+$x$-coordinate
190 | +html+ <i>x</i>-coordinate
191 | of the local part of the global vector.
192 |
193 | int ys Starting
194 | +latex+$y$-coordinate
195 | +html+ <i>y</i>-coordinate
196 | of the local part of the global vector.
197 |
198 | int xm Width of the local part of the global vector.
199 |
200 | int ym Height of the local part of the global vector.
201 | ++++++++++++++++++++++++++++++++++++++*/
202 |
203 | int render_rgb_local_2d
204 | (guchar *rgb, int rwidth, int rheight, int bytes_per_pixel,
205 | PetscScalar *global_array, int num_fields, int display_field,
206 | field_plot_type fieldtype, PetscScalar *minmax, int nx,int ny, int xs,int ys,
207 | int xm,int ym)
208 | {
209 | int ix,iy, ierr;
210 | PetscScalar local_minmax[6];
211 |
212 | /* Determine default min and max if none are provided */
213 | if (minmax == NULL)
214 | {
215 | minmax = local_minmax;
216 | ierr = minmax_scale (global_array, xm*ym, num_fields, display_field,
217 | fieldtype, 2, minmax); CHKERRQ (ierr);
218 | }
219 |
220 | /* Do the rendering (note switch in inner loop, gotta get rid of that) */
221 | for (iy=rheight*ys/ny; iy<rheight*(ys+ym)/ny; iy++)
222 | for (ix=rwidth*xs/nx; ix<rwidth*(xs+xm)/nx; ix++)
223 | {
224 | int vecindex = (((rheight-iy-1)*ny/rheight)*nx +
225 | ix*nx/rwidth)*num_fields + display_field;
226 | guchar *pixel = rgb + bytes_per_pixel*(iy*rwidth + ix);
227 |
228 | switch (fieldtype)
229 | {
230 | case FIELD_SCALAR:
231 | case FIELD_SCALAR+1:
232 | {
233 | pseudocolor (global_array [vecindex], minmax, pixel);
234 | break;
235 | }
236 | case FIELD_VECTOR:
237 | case FIELD_VECTOR+1:
238 | {
239 | pseudohueintcolor
240 | (global_array [vecindex], global_array [vecindex+1], minmax,
241 | pixel);
242 | break;
243 | }
244 | case FIELD_TERNARY:
245 | {
246 | pseudoternarycolor
247 | (global_array [vecindex], global_array [vecindex+1], minmax,
248 | pixel);
249 | break;
250 | }
251 | default:
252 | SETERRQ (PETSC_ERR_ARG_OUTOFRANGE, "Field type not yet supported");
253 | }
254 | }
255 | return 0;
256 | }
257 |
258 |
259 | /*++++++++++++++++++++++++++++++++++++++
260 | Render triangle data into an RGB buffer. When called in parallel, the
261 | resulting images should be layered to give the complete picture. Zooming is
262 | done by adjusting the ratio of the dir vector to the right vector.
263 |
264 | int render_rgb_local_3d Returns zero or an error code.
265 |
266 | guchar *rgb RGB buffer in which to render.
267 |
268 | int rwidth Total width of the RGB buffer.
269 |
270 | int rheight Total height of the RGB buffer.
271 |
272 | int bytes_per_pixel Number of bytes per pixel in this RGB buffer (typically 3
273 | or 4).
274 |
275 | int num_triangles Number of triangles to render.
276 |
277 | PetscScalar *vertices Table of coordinates (x1,y1,z1, x2,y2,z2, x3,y3,z3) and
278 | colors (RGBA 0-1) making thirteen values per triangle.
279 |
280 | PetscScalar *eye Point from where we're looking (x,y,z).
281 |
282 | PetscScalar *dir Direction we're looking (x,y,z).
283 |
284 | PetscScalar *right Rightward direction in physical space (x,y,z).
285 | ++++++++++++++++++++++++++++++++++++++*/
286 |
287 | int render_rgb_local_3d
288 | (guchar *rgb, int rwidth, int rheight, int bytes_per_pixel,
289 | int num_triangles, PetscScalar *vertices,
290 | PetscScalar *eye, PetscScalar *dir, PetscScalar *right)
291 | {
292 | SETERRQ (PETSC_ERR_SUP, "3-D rendering is not yet ready");
293 | }