5751991 [rkeene@sledge /home/rkeene/devel/old/stereograph-0.16]$ cat -n renderer.c
  1 /* Stereograph 0.16, 12/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     static int a = 0, aar_x, xaar_x = -1;
110     InitMap(Renderer.left_change_map, 0, Base.Width, (float)(Texture.Width + 1));
111     
112     FillMapsLeftToRight(base_data);
113 
114     if(xaar_x == -1)
115         xaar_x = Renderer.startx;
116     a++; a %= 2;
117     if(a && Param.AAr) {
118         //aar_x = Stereo.Width - Texture.Width - 1;
119         /* tracing alternative startx */
120         for (aar_x = Renderer.startx; (aar_x + Renderer.left_change_map[aar_x]) < (Stereo.Width - Texture.Width - 1); )
121             aar_x += Renderer.left_change_map[aar_x];
122         Renderer.startx = aar_x;
123     } else {
124         Renderer.startx = xaar_x;
125     }
126     if(Param.AA - 1)
127     {
128         if(Param.Zoom - 1)
129             return ZoomAAScan(stereo_data, texture_data);
130         else
131             return AAScan(stereo_data, texture_data);;
132     } else if(Param.Zoom)
133         return ZoomScan(stereo_data, texture_data);
134     else
135         return NormalScan(stereo_data, texture_data);
136 }
137 
138 
139 /* intialize changemap internals */
140 int InitMap(float *change_map, int a, int b, float v)
141 {
142     for( ; a < b; a++)
143         change_map[a] = v;
144     return 0;
145 }
146 
147 
148 /* set changevalues */
149 int FillMapsLeftToRight(int *base_data)
150 {
151         int z, scanx, i_c;
152     float c;
153 
154     /* advanced full centered perspective; reimplemented february 4th 2000 */
155     /* added eyeshift february 11th 2000 */
156         for (scanx = 0; scanx < (Base.Width + Texture.Width); scanx++)
157         {
158         if((scanx + (int)(c = GetChange(scanx, base_data))) > 0) {
159             i_c = (int) (scanx + c*(0.5 - Renderer.eyeshift)) + (Texture.Width*Renderer.eyeshift*2.0);
160             if (i_c < Base.Width) {
161                         Renderer.right_change_map[i_c] = -c;
162                         z = i_c + Renderer.right_change_map[i_c];
163                         if ((z >= 0) && (z < Base.Width))
164                                 if (Renderer.left_change_map[z] > c)
165                                         Renderer.left_change_map[z] = c;
166             }
167         }
168         }
169 
170     /* checking for construction errors - `black holes' */
171         if (Renderer.left_change_map[0] > Texture.Width)
172                 Renderer.left_change_map[0] = Texture.Width;
173         for (z = 1; z < Base.Width; z++)
174                 if (Renderer.left_change_map[z] > Texture.Width)
175                         Renderer.left_change_map[z] = Renderer.left_change_map[z - 1];
176     return 0;
177 }
178 
179 
180 /* This is float because of high precision effects such as zoom'n'anti-aliasing */
181 /* In a simple reference implementation an integer value should be suffisant */
182 float GetChange(int x, int *base_data)
183 {
184     float s, b, d;
185     /* extracting out of 24 bit RGB data the brightness/intensitiy indicating information */
186     /* value is extended from 0-255 up to 0-765 */
187     s = ((base_data[x] & 255) + ((base_data[x] >> 8) & 255) + ((base_data[x] >> 16) & 255)) / 765.0;
188     d = Renderer.realdist - (float) Renderer.max_change_tex_width * s;
189     b = 1.0 / sqrt(Renderer.internal_a + 0.25 / (d * d));
190     return b;
191 }
192 
193 
194 /* reference renderer without any special effects */
195 int NormalScan(int *stereo_data, int *texture_data)
196 {
197     float z;
198     int scanx;
199 
200     /* insert the texture at x */
201     memcpy(stereo_data + Renderer.startx, texture_data, Texture.Width * sizeof(int));
202 
203     /* we've to scan into two directions, beginning @ startx */
204     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
205     {
206         z = scanx + Renderer.right_change_map[scanx];
207         if (((int) z >= Renderer.startx) && ((int) z < Base.Width))
208             stereo_data[scanx] = stereo_data[(int) z];
209     }
210     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
211     {
212         z = scanx + Renderer.right_change_map[scanx];
213         if( ((int) z < Base.Width) && ((int) z >= 0))
214             stereo_data[scanx] = stereo_data[(int) z];
215     }
216     for (scanx = Renderer.startx; scanx >= 0; scanx--)
217     {
218         z = scanx + Renderer.left_change_map[scanx];
219         /* 'cause of problems without the round function - internal round, it's a cut - it is NOT symmetric */
220         if (z != ((int) z))
221             z++;
222         if (((int) z >= 0) && ((int) z < Base.Width))
223             stereo_data[scanx] = stereo_data[(int) z];
224     }
225     return 0;
226 }
227 
228 
229 /* First and most effective of all special: anti-aliasing */
230 int AAScan(int *stereo_data, int *texture_data)
231 {
232     int scanx,a;
233     float z;
234     int r, g, b;
235 
236         /* insert the texture without any special fx */
237     for (scanx = 0; scanx < Texture.Width; scanx++)
238         for (a = 0; a < Renderer.nfactor; a++)
239             Renderer.scanline[((scanx + Renderer.startx) * Renderer.nfactor) + a] = texture_data[scanx];
240 
241     /* scanning... */
242     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
243     {
244         z = scanx + Renderer.right_change_map[scanx];
245         if ((z >= Renderer.startx) && (z < Base.Width))
246             for (a = 0; a < Renderer.nfactor; a++)
247                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
248         else if (z > (Renderer.startx - 1) && (z < Renderer.startx))
249                 for (a = (-z + (float) Renderer.startx) * Renderer.nfactor; a < Renderer.nfactor; a++)
250                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
251     }
252     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
253     {
254         z = scanx + Renderer.right_change_map[scanx];
255         if( (z < Base.Width) && (z >= 0))
256             for (a = 0; a < Renderer.nfactor; a++)
257                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
258     }
259     for (scanx = Renderer.startx; scanx >= 0; scanx--)
260     {
261         z = scanx + Renderer.left_change_map[scanx];
262         if((z < Base.Width) && (z >= 0))
263         {
264             z *= Renderer.nfactor;
265             if (z != ((int) z))
266                 z++;
267             for (a = 0; a < Renderer.nfactor; a++)
268                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) z + a)];
269         }
270     }
271 
272     /* flush mem back into stereo_data, fixed */
273     for (scanx = 0; scanx < Base.Width; scanx++)
274     {
275         stereo_data[scanx] = r = g = b = 0;
276         for (a = 0; a < Renderer.naa; a++)
277         {
278             r +=  Renderer.scanline[scanx * Renderer.naa + a]        & 255;
279             g += (Renderer.scanline[scanx * Renderer.naa + a] >>  8) & 255;
280             b += (Renderer.scanline[scanx * Renderer.naa + a] >> 16) & 255;
281         }
282         stereo_data[scanx] +=  (r / Renderer.naa) & 255;
283         stereo_data[scanx] += ((g / Renderer.naa) & 255) << 8;
284         stereo_data[scanx] += ((b / Renderer.naa) & 255) << 16;
285     }
286     return 0;
287 }
288 
289 
290 /* Second effect: zoom */
291 int ZoomScan(int *stereo_data, int *texture_data)
292 {
293     int scanx, a;
294     float z;
295 
296         /* insert the texture without any special fx */
297     for (scanx = 0; scanx < Texture.Width; scanx++)
298         for (a = 0; a < Renderer.nfactor; a++)
299             stereo_data[((scanx + Renderer.startx) * Renderer.nfactor) + a] = texture_data[scanx];
300 
301         /* already scanning, nothing to prepare */
302     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
303     {
304         z = scanx + Renderer.right_change_map[scanx];
305         if ((z >= Renderer.startx) && (z < Base.Width))
306             for (a = 0; a < Renderer.nfactor; a++)
307                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[(int) (z * Renderer.nfactor) + a];
308         else if ((z > (Renderer.startx - 1)) && (z < Renderer.startx))
309                 for (a = (-z + (float) Renderer.startx) * Renderer.nfactor; a < Renderer.nfactor; a++)
310                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[((int) (z * Renderer.nfactor) + a)];
311     }
312     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
313     {
314         z = scanx + Renderer.right_change_map[scanx];
315         if((z < Base.Width) && (z >= 0))
316             for (a = 0; a < Renderer.nfactor; a++)
317                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[(int) (z * Renderer.nfactor) + a];
318     }
319 
320     for (scanx = Renderer.startx; scanx >= 0; scanx--)
321     {
322         z = scanx + Renderer.left_change_map[scanx];
323         if((z < Base.Width) && (z >= 0))
324         {
325             z *= Renderer.nfactor;
326             if (z != ((int) z))
327                 z++;
328             for (a = 0; a < Renderer.nfactor; a++)
329                 stereo_data[(scanx * Renderer.nfactor) + a] = stereo_data[(int) z + a];  /* attention : z is was already
	multiplied above!!! */
330         }
331     }
332 
333     /* fill the comple row down with the same values to construct square pixels */
334     for (a = 1; a < Renderer.nfactor; a++)
335         memcpy(stereo_data + Stereo.Width*a, stereo_data, Stereo.Width * sizeof(int));
336     return 0;
337 }
338 
339 
340 /* ZOOM'N'AA */
341 /* Final effects: fx pair in cooperation */
342 int ZoomAAScan(int *stereo_data, int *texture_data)
343 {
344     int scanx, a;
345     float z;
346     int r, g, b;
347 
348         /* insert the texture without any special fx */
349     /* the same as anti-aliasing implementation above */
350     for (scanx = 0; scanx < Texture.Width; scanx++)
351         for (a = 0; a < Renderer.nfactor; a++)
352             Renderer.scanline[((scanx + Renderer.startx) * Renderer.nfactor) + a] = texture_data[scanx];
353 
354     /* scanning */
355     for (scanx = Renderer.startx; scanx < (Renderer.startx + Texture.Width); scanx++)
356     {
357         z = scanx + Renderer.right_change_map[scanx];
358         if ((z >= Renderer.startx) && (z < Base.Width))
359             for (a = 0; a < Renderer.nfactor; a++)
360                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[(int) (z * Renderer.nfactor) + a];
361         else if (z > (Renderer.startx - 1) && (z < Renderer.startx))
362                 for (a = (-z + (float) Renderer.startx) * Renderer.nfactor; a < Renderer.nfactor; a++)
363                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[((int) (z * Renderer.nfactor) +
	a)];
364     }
365     for (scanx = Renderer.startx + Texture.Width; scanx < Base.Width; scanx++)
366     {
367         z = scanx + Renderer.right_change_map[scanx];
368         if ((z >= 0) && (z < Base.Width))
369             for (a = 0; a < Renderer.nfactor; a++)
370                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[(int) (z * Renderer.nfactor) + a];
371     }
372     for (scanx = Renderer.startx; scanx >= 0; scanx--)
373     {
374         z = scanx + Renderer.left_change_map[scanx];
375         if ((z >= 0) && (z < Base.Width))
376         {
377             z *= Renderer.nfactor;
378             if (z != ((int) z))
379                 z++;
380             for (a = 0; a < Renderer.nfactor; a++)
381                 Renderer.scanline[(scanx * Renderer.nfactor) + a] = Renderer.scanline[(int) z + a];  /* z was already
	multiplied above; */
382         }
383     }
384 
385     /* flush it down, fixed */
386     for (scanx = 0; scanx < Stereo.Width; scanx++)
387     {
388         stereo_data[scanx] = r = g = b = 0;
389         for (a = 0; a < Renderer.naa; a++)
390         {
391             r +=  Renderer.scanline[scanx * Renderer.naa + a]        & 255;
392             g += (Renderer.scanline[scanx * Renderer.naa + a] >>  8) & 255;
393             b += (Renderer.scanline[scanx * Renderer.naa + a] >> 16) & 255;
394         }
395         stereo_data[scanx] +=  (r / Renderer.naa) & 255;
396         stereo_data[scanx] += ((g / Renderer.naa) & 255) << 8;
397         stereo_data[scanx] += ((b / Renderer.naa) & 255) << 16;
398     }
399 
400 
401     /* fill it down to produce square pixels */
402     for (a = 1; a < Renderer.nzoom; a++)
403         memcpy(stereo_data + Stereo.Width*a, stereo_data, Stereo.Width*sizeof(int));
404     return 0;
405 }

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

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2000-04-12 10:54:09