5752001 [rkeene@sledge /home/rkeene/devel/old/stereograph-0.14]$ cat -n renderer.c
  1 /* Stereograph 0.14, 08/04/2000;
  2  * renderer, stereographer's engine;
  3  * Copyright (c) 2000 by Fabian Januszewski <fabian.linux@januszewski.de>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU General Public License as published by
  7  * the Free Software Foundation; either version 2 of the License, or
  8  * (at your option) any later version.
  9  *
 10  * This program is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  * GNU General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU General Public License
 16  * along with this program; if not, write to the Free Software
 17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 18  */
 19 
 20 #define _GNU_SOURCE
 21 
 22 #include <stdio.h>
 23 #include <stdlib.h>
 24 #include <math.h>
 25 
 26 #include "renderer.h"
 27 
 28 
 29 /* here we go... */
 30 
 31 struct GFX_DATA Base, Texture, Stereo;
 32 struct RENDERER_DATA Renderer;
 33 struct PARAMS Param;
 34 
 35 
 36 /* 1st of all: send all releavant data (pointers) to foreign functions */
 37 int Get_GFX_Pointers(struct PARAMS **pParam, struct GFX_DATA **pBase, struct GFX_DATA **pTexture, struct GFX_DATA
	**pStereo) {
 38     (*pParam) = &Param;
 39     (*pBase) = &Base;
 40     (*pTexture) = &Texture;
 41     (*pStereo) = &Stereo;
 42     return 0;
 43 }
 44 
 45 
 46 /* render a mere line */
 47 int ProcessLine(int base_line) {
 48     return RenderLine(Base.Data + Base.Width * base_line, Texture.Data + Texture.Width * ((base_line + Param.Starty) %
	Texture.Height), Stereo.Data + Stereo.Width*base_line*Renderer.nzoom);
 49 }
 50 
 51 
 52 /* destroy memory reservations, internals; NOTE: Stereo also belongs to the renderer! */
 53 void Clear_Renderer(void)
 54 {
 55     free(Renderer.right_change_map);
 56     free(Renderer.left_change_map);
 57     free(Renderer.scanline);
 58     free(Stereo.Data);
 59 }
 60 
 61 
 62 /* initialize internal rendering engine data */
 63 int Initialize_Renderer(void)
 64 {
 65     Renderer.startx = Param.Startx;
 66     Renderer.max_change_tex_width = (int)((Texture.Width - 1) * Param.Front);
 67     Renderer.right_change_map = (float*)malloc(sizeof(float) * (Base.Width + 1));
 68     Renderer.left_change_map = (float*)malloc(sizeof(float) * (Base.Width + 1));
 69     Renderer.naa = Param.AA + 0;
 70     Renderer.nzoom = Param.Zoom + 0;
 71     Renderer.realdist = Texture.Width * (Param.Distance + 1);
 72     Renderer.internal_a = (1.0 / (Texture.Width * Texture.Width)) - (0.25 / (Renderer.realdist * Renderer.realdist));
 73     Renderer.eyeshift = Param.Eyeshift*0.5;
 74     if(
 75         ((Param.Distance + 1) > 1.0) && ((Param.Distance + 1) <= 9.0) &&
 76         (Renderer.eyeshift >= -0.5) && (Renderer.eyeshift <= 0.5) &&
 77         (Renderer.naa > 0) && (Renderer.naa <= 32) &&
 78         (Renderer.nzoom > 0) && (Renderer.nzoom <= 32) &&
 79         (Renderer.startx >= 0) && (Renderer.startx < (Base.Width - Texture.Width)) &&
 80         (Param.Starty >= 0) &&
 81         (Param.Front > 0.0) && (Param.Front <= 1.0)
 82     ) {
 83         Renderer.nfactor = Renderer.naa * Renderer.nzoom;
 84         if(Param.AA - 1)
 85             Renderer.scanline = (int*)malloc(sizeof(int) * (Base.Width * Renderer.nfactor));
 86         else
 87             Renderer.scanline = NULL;
 88 
 89         Stereo.Width = Base.Width * Renderer.nzoom;
 90         Stereo.Height = Base.Height * Renderer.nzoom;
 91         Stereo.Data = (int*)malloc(sizeof(int) * Stereo.Width * Stereo.Height);
 92 
 93             if(Renderer.right_change_map && Renderer.left_change_map && Stereo.Data && Base.Data && Texture.Data) {
 94             if(Base.Width >= Texture.Width)
 95                 return 0;
 96             else
 97                 return -2;
 98         } else
 99             return -3;
100     } else {
101         return -1;
102     }
103 }
104 
105 
106 /* Render a mere line of data, may be completely independent of any gfx_data structure */
107 int RenderLine(int *base_data, int *texture_data, int *stereo_data)
108 {
109     InitMap(Renderer.left_change_map, 0, Base.Width, (float)(Texture.Width + 1));
110     
111     FillMapsLeftToRight(base_data);
112 
113     if(Param.AA - 1)
114     {
115         if(Param.Zoom - 1)
116             return ZoomAAScan(stereo_data, texture_data);
117         else
118             return AAScan(stereo_data, texture_data);
119     } else if(Param.Zoom)
120         return ZoomScan(stereo_data, texture_data);
121     else
122         return NormalScan(stereo_data, texture_data);
123 }
124 
125 
126 /* intialize changemap internals */
127 int InitMap(float *change_map, int a, int b, float v)
128 {
129     for( ; a < b; a++)
130         change_map[a] = v;
131     return 0;
132 }
133 
134 
135 /* set changevalues */
136 int FillMapsLeftToRight(int *base_data)
137 {
138         int z, scanx, i_c;
139     float c;
140 
141     /* advanced full centered perspective; reimplemented february 4th 2000 */
142     /* added eyeshift february 11th 2000 */
143         for (scanx = 0; scanx < (Base.Width + Texture.Width); scanx++)
144         {
145         if((scanx + (int)(c = GetChange(scanx, base_data))) > 0) {
146             i_c = (int) (scanx + c*(0.5 - Renderer.eyeshift)) + (Texture.Width*Renderer.eyeshift*2.0);
147             if (i_c < Base.Width) {
148                         Renderer.right_change_map[i_c] = -c;
149                         z = i_c + Renderer.right_change_map[i_c];
150                         if ((z >= 0) && (z < Base.Width))
151                                 if (Renderer.left_change_map[z] > c)
152                                         Renderer.left_change_map[z] = c;
153             }
154         }
155         }
156 
157     /* checking for construction errors - `black holes' */
158         if (Renderer.left_change_map[0] > Texture.Width)
159                 Renderer.left_change_map[0] = Texture.Width;
160         for (z = 1; z < Base.Width; z++)
161                 if (Renderer.left_change_map[z] > Texture.Width)
162                         Renderer.left_change_map[z] = Renderer.left_change_map[z - 1];
163     return 0;
164 }
165 
166 
167 /* This is float because of high precision effects such as zoom'n'anti-aliasing */
168 /* In a simple reference implementation an integer value should be suffisant */
169 float GetChange(int x, int *base_data)
170 {
171     float s, b, d;
172     /* extracting out of 24 bit RGB data the brightness/intensitiy indicating information */
173     /* value is extended from 0-255 up to 0-765 */
174     s = ((base_data[x] & 255) + ((base_data[x] >> 8) & 255) + ((base_data[x] >> 16) & 255)) / 765.0;
175     d = Renderer.realdist - (float) Renderer.max_change_tex_width * s;
176     b = 1.0 / sqrt(Renderer.internal_a + 0.25 / (d * d));
177     return b;
178 }
179 
180 
181 /* reference renderer without any special effects */
182 int NormalScan(int *stereo_data, int *texture_data)
183 {
184     float z;
185     int scanx;
186 
187     /* insert the texture at x */
188     memcpy(stereo_data + Renderer.startx, texture_data, Texture.Width * sizeof(int));
189 
190     /* we've to scan into two directions, beginning @ startx */
191     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
192     {
193         z = scanx + Renderer.right_change_map[scanx];
194         if (((int) z >= Renderer.startx) && ((int) z < Base.Width))
195             stereo_data[scanx] = stereo_data[(int) z];
196     }
197     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
198     {
199         z = scanx + Renderer.right_change_map[scanx];
200         if( ((int) z < Base.Width) && ((int) z >= 0))
201             stereo_data[scanx] = stereo_data[(int) z];
202     }
203     for (scanx = Renderer.startx; scanx >= 0; scanx--)
204     {
205         z = scanx + Renderer.left_change_map[scanx];
206         /* 'cause of problems without the round function - internal round, it's a cut - it is NOT symmetric */
207         if (z != ((int) z))
208             z++;
209         if (((int) z >= 0) && ((int) z < Base.Width))
210             stereo_data[scanx] = stereo_data[(int) z];
211     }
212     return 0;
213 }
214 
215 
216 /* First and most effective of all special: anti-aliasing */
217 int AAScan(int *stereo_data, int *texture_data)
218 {
219     int scanx,a;
220     float z;
221     int r, g, b;
222 
223         /* insert the texture without any special fx */
224     for (scanx = 0; scanx < Texture.Width; scanx++)
225         for (a = 0; a < Renderer.nfactor; a++)
226             Renderer.scanline[((scanx + Renderer.startx) * Renderer.nfactor) + a] = texture_data[scanx];
227 
228     /* scanning... */
229     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
230     {
231         z = scanx + Renderer.right_change_map[scanx];
232         if ((z >= Renderer.startx) && (z < Base.Width))
233             for (a = 0; a < Renderer.nfactor; a++)
234                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
235         else if (z > (Renderer.startx - 1) && (z < Renderer.startx))
236                 for (a = (-z + (float) Renderer.startx) * Renderer.nfactor; a < Renderer.nfactor; a++)
237                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
238     }
239     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
240     {
241         z = scanx + Renderer.right_change_map[scanx];
242         if( (z < Base.Width) && (z >= 0))
243             for (a = 0; a < Renderer.nfactor; a++)
244                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
245     }
246     for (scanx = Renderer.startx; scanx >= 0; scanx--)
247     {
248         z = scanx + Renderer.left_change_map[scanx];
249         if((z < Base.Width) && (z >= 0))
250         {
251             z *= Renderer.nfactor;
252             if (z != ((int) z))
253                 z++;
254             for (a = 0; a < Renderer.nfactor; a++)
255                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) z + a)];
256         }
257     }
258 
259     /* flush mem back into stereo_data, fixed */
260     for (scanx = 0; scanx < Base.Width; scanx++)
261     {
262         stereo_data[scanx] = r = g = b = 0;
263         for (a = 0; a < Renderer.naa; a++)
264         {
265             r +=  Renderer.scanline[scanx * Renderer.naa + a]        & 255;
266             g += (Renderer.scanline[scanx * Renderer.naa + a] >>  8) & 255;
267             b += (Renderer.scanline[scanx * Renderer.naa + a] >> 16) & 255;
268         }
269         stereo_data[scanx] +=  (r / Renderer.naa) & 255;
270         stereo_data[scanx] += ((g / Renderer.naa) & 255) << 8;
271         stereo_data[scanx] += ((b / Renderer.naa) & 255) << 16;
272     }
273     return 0;
274 }
275 
276 
277 /* Second effect: zoom */
278 int ZoomScan(int *stereo_data, int *texture_data)
279 {
280     int scanx, a;
281     float z;
282 
283         /* insert the texture without any special fx */
284     for (scanx = 0; scanx < Texture.Width; scanx++)
285         for (a = 0; a < Renderer.nfactor; a++)
286             stereo_data[((scanx + Renderer.startx) * Renderer.nfactor) + a] = texture_data[scanx];
287 
288         /* already scanning, nothing to prepare */
289     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
290     {
291         z = scanx + Renderer.right_change_map[scanx];
292         if ((z >= Renderer.startx) && (z < Base.Width))
293             for (a = 0; a < Renderer.nfactor; a++)
294                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[(int) (z * Renderer.nfactor) + a];
295         else if ((z > (Renderer.startx - 1)) && (z < Renderer.startx))
296                 for (a = (-z + (float) Renderer.startx) * Renderer.nfactor; a < Renderer.nfactor; a++)
297                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[((int) (z * Renderer.nfactor) + a)];
298     }
299     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
300     {
301         z = scanx + Renderer.right_change_map[scanx];
302         if((z < Base.Width) && (z >= 0))
303             for (a = 0; a < Renderer.nfactor; a++)
304                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[(int) (z * Renderer.nfactor) + a];
305     }
306 
307     for (scanx = Renderer.startx; scanx >= 0; scanx--)
308     {
309         z = scanx + Renderer.left_change_map[scanx];
310         if((z < Base.Width) && (z >= 0))
311         {
312             z *= Renderer.nfactor;
313             if (z != ((int) z))
314                 z++;
315             for (a = 0; a < Renderer.nfactor; a++)
316                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[(int) z + a];  /* attention : z is was already
	multiplied above!!! */
317         }
318     }
319 
320     /* fill the comple row down with the same values to construct square pixels */
321     for (a = 1; a < Renderer.nfactor; a++)
322         memcpy(stereo_data + Stereo.Width*a, stereo_data, Stereo.Width * sizeof(int));
323     return 0;
324 }
325 
326 
327 /* ZOOM'N'AA */
328 /* Final effects: fx pair in cooperation */
329 int ZoomAAScan(int *stereo_data, int *texture_data)
330 {
331     int scanx, a;
332     float z;
333     int r, g, b;
334 
335         /* insert the texture without any special fx */
336     /* the same as anti-aliasing implementation above */
337     for (scanx = 0; scanx < Texture.Width; scanx++)
338         for (a = 0; a < Renderer.nfactor; a++)
339             Renderer.scanline[((scanx + Renderer.startx) * Renderer.nfactor) + a] = texture_data[scanx];
340 
341     /* scanning */
342     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
343     {
344         z = scanx + Renderer.right_change_map[scanx];
345         if ((z >= Renderer.startx) && (z < Base.Width))
346             for (a = 0; a < Renderer.nfactor; a++)
347                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[(int) (z * Renderer.nfactor) + a];
348         else if (z > (Renderer.startx - 1) && (z < Renderer.startx))
349                 for (a = (-z + (float) Renderer.startx) * Renderer.nfactor; a < Renderer.nfactor; a++)
350                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
351     }
352     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
353     {
354         z = scanx + Renderer.right_change_map[scanx];
355         if ((z >= 0) && (z < Base.Width))
356             for (a = 0; a < Renderer.nfactor; a++)
357                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[(int) (z * Renderer.nfactor) + a];
358     }
359     for (scanx = Renderer.startx; scanx >= 0; scanx--)
360     {
361         z = scanx + Renderer.left_change_map[scanx];
362         if ((z >= 0) && (z < Base.Width))
363         {
364             z *= Renderer.nfactor;
365             if (z != ((int) z))
366                 z++;
367             for (a = 0; a < Renderer.nfactor; a++)
368                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[(int) z + a];  /* z was already
	multiplied above; */
369         }
370     }
371 
372     /* flush it down, fixed */
373     for (scanx = 0; scanx < Stereo.Width; scanx++)
374     {
375         stereo_data[scanx] = r = g = b = 0;
376         for (a = 0; a < Renderer.naa; a++)
377         {
378             r +=  Renderer.scanline[scanx * Renderer.naa + a]        & 255;
379             g += (Renderer.scanline[scanx * Renderer.naa + a] >>  8) & 255;
380             b += (Renderer.scanline[scanx * Renderer.naa + a] >> 16) & 255;
381         }
382         stereo_data[scanx] +=  (r / Renderer.naa) & 255;
383         stereo_data[scanx] += ((g / Renderer.naa) & 255) << 8;
384         stereo_data[scanx] += ((b / Renderer.naa) & 255) << 16;
385     }
386 
387 
388     /* fill it down to produce square pixels */
389     for (a = 1; a < Renderer.nzoom; a++)
390         memcpy(stereo_data + Stereo.Width*a, stereo_data, Stereo.Width*sizeof(int));
391     return 0;
392 }

renderer.c contains code to make the program actually process data and stereograph it.
5752002 [rkeene@sledge /home/rkeene/devel/old/stereograph-0.14]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2000-04-08 17:49:42