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

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2000-02-09 13:38:19