Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

SpanBuffer.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  SpanBuffer.C                                                                        */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                */
00005 /*  Description:  This is a raster-line based span buffer (like a z buffer but it works */
00006 /*                with groups of horizontal pixels, rather than single pixels)          */
00007 /*                                                                                      */
00008 /*  The contents of this file are subject to the Genesis3D Public License               */
00009 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00010 /*  compliance with the License. You may obtain a copy of the License at                */
00011 /*  http://www.genesis3d.com                                                            */
00012 /*                                                                                      */
00013 /*  Software distributed under the License is distributed on an "AS IS"                 */
00014 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00015 /*  the License for the specific language governing rights and limitations              */
00016 /*  under the License.                                                                  */
00017 /*                                                                                      */
00018 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00019 /*Genesis3D Version 1.1 released November 15, 1999                            */
00020 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00021 /*                                                                                      */
00022 /****************************************************************************************/
00023 #include <Assert.h>
00024 
00025 #include "SpanBuffer.h"
00026 #include "Ram.h"
00027 
00028 #ifdef GENESIS_VERSION_2
00029 #include "errorlog.h"
00030 #else
00031 #define geErrorLog_AddString(Error,xx,yy) 
00032 #endif
00033 
00034 //#define SPAN_MAX_SPARES 25000 
00035 //#define SPAN_MAX_LINES 768
00036 //#define RESOLUTION_X 640
00037 //#define RESOLUTION_Y 640
00038 
00039 typedef struct SpanBuffer_Span SpanBuffer_Span;
00040 
00041 typedef struct SpanBuffer_Span
00042 {
00043         int     Min, Max;
00044     SpanBuffer_Span *Next;
00045 } SpanBuffer_Span;
00046 
00047 static SpanBuffer_Span  **SpanBuffer_Lines;                     // list of spans for each scanline
00048 static SpanBuffer_Span *SpanBuffer_Spares;                      // unused spans since last Clear
00049 static int                              SpanBuffer_FirstSpare;          // index of next spare span: SpanBuffer_Spares[SpanBuffer_FirstSpare]
00050 static int                              SpanBuffer_LineCount;           // number of lines in span buffer table.
00051 static int                              SpanBuffer_MaxSpares;
00052 SpanBuffer_ClipSegment  *SpanBuffer_Segments;           // epxorted list of clipped spans (segments)    
00053 
00054 
00055 void SpanBuffer_Destroy(void)
00056 {
00057         if ( SpanBuffer_Lines != NULL )
00058                 geRam_Free(SpanBuffer_Lines);
00059         SpanBuffer_Lines = NULL;
00060 
00061         if ( SpanBuffer_Spares != NULL )
00062                 geRam_Free(SpanBuffer_Spares);
00063         SpanBuffer_Spares = NULL;
00064 
00065         if ( SpanBuffer_Segments != NULL )
00066                 geRam_Free(SpanBuffer_Segments);
00067         SpanBuffer_Segments = NULL;
00068 }
00069 
00070 void SpanBuffer_Clear(void)
00071 { 
00072         int i;
00073         assert(SpanBuffer_Lines!=NULL);
00074 
00075         for (i=0; i<SpanBuffer_LineCount; i++) 
00076                 {
00077                         SpanBuffer_Lines[i] = NULL;
00078                 }       
00079         SpanBuffer_FirstSpare = 0;
00080 }
00081 
00082 geBoolean SpanBuffer_Create(int Width, int Height, int MaxSpans)
00083 {
00084         assert( Width > 0 );
00085         assert( Height > 0 );
00086         assert( MaxSpans > 0 );
00087 
00088         SpanBuffer_Destroy();
00089 
00090         SpanBuffer_MaxSpares = MaxSpans;
00091         SpanBuffer_LineCount = Height;
00092 
00093         SpanBuffer_Lines = geRam_Allocate(sizeof(SpanBuffer_Span *) * Height);
00094         if (SpanBuffer_Lines == NULL)
00095                 {
00096                         geErrorLog_AddString( GE_ERR_MEMORY_RESOURCE,"Unable to create span buffer table",NULL);
00097                         return GE_FALSE;
00098                 }
00099 
00100         SpanBuffer_Spares = geRam_Allocate(sizeof(SpanBuffer_Span) * MaxSpans);
00101         if (SpanBuffer_Lines == NULL)
00102                 {
00103                         geErrorLog_AddString(GE_ERR_MEMORY_RESOURCE ,"Unable to create spare span list",NULL);
00104                         geRam_Free(SpanBuffer_Lines);
00105                         SpanBuffer_Lines = NULL;
00106                         return GE_FALSE;
00107                 }
00108 
00109         SpanBuffer_Segments = geRam_Allocate(sizeof(SpanBuffer_ClipSegment) * (Width/2) );
00110         if (SpanBuffer_Segments == NULL )
00111                 {
00112                         geErrorLog_AddString( GE_ERR_MEMORY_RESOURCE,"Unable to create span buffer clip segment list",NULL);
00113                         geRam_Free(SpanBuffer_Lines); 
00114                         SpanBuffer_Lines = NULL;
00115                         geRam_Free(SpanBuffer_Spares);
00116                         SpanBuffer_Spares = NULL;
00117                         return GE_FALSE;
00118                 }
00119         SpanBuffer_Clear();
00120         return GE_TRUE;
00121 }
00122 
00123 #if 0 // not used (yet)
00124 geBoolean SpanBuffer_Visible(int Line, int Left, int Right)
00125 {
00126         SpanBuffer_Span *S;
00127         assert( Line>=0 );
00128         assert( Line< SpanBuffer_LineCount );
00129         assert( Right>=Left );
00130         // assumes that adjacent spans are always merged.
00131 
00132         S = SpanBuffer_Lines[Line];
00133         while (S)
00134                 {
00135                         if (Left<S->Min)
00136                                 return GE_TRUE;
00137                         if (Right<=S->Max)
00138                                 return GE_FALSE;
00139                         S=S->Next;
00140                 }
00141         return GE_TRUE;
00142 }
00143 #endif
00144 
00145 int SpanBuffer_ClipAndAdd(int Line, int LeftStart, int Width)
00146 {
00147         SpanBuffer_Span *LastSpan;
00148         SpanBuffer_Span *NewSpan;
00149         SpanBuffer_Span *Span;
00150         SpanBuffer_ClipSegment *Segment;
00151         int Left = LeftStart;
00152         int Right = LeftStart + Width -1;  
00153         int SegmentCount = 0;
00154         #pragma message("fix this off by one problem here and in the engine!")
00155         if (Line>=SpanBuffer_LineCount)
00156                 return 0;
00157 
00158         assert( Line >= 0 );
00159         assert( Line< SpanBuffer_LineCount );
00160         assert( Width >= 0 ); 
00161         assert( LeftStart >=0 );
00162 
00163         Segment  = &(SpanBuffer_Segments[0]);
00164         LastSpan = NULL;
00165         Span     = SpanBuffer_Lines[Line];
00166 
00167         while (Span)
00168                 {
00169                         if (Left < Span->Min)
00170                                 {   // new span starts to left of this span
00171                                         if (Right<Span->Min)  
00172                                                 {       // new span ends to left of this span
00173                                                         break;
00174                                                 }
00175                                         else
00176                                                 {       // new span ends in or to the right of this span
00177                                                         Segment->LeftOffset = Left - LeftStart;
00178                                                         Segment->Width = Span->Min - Left;
00179                                                         SegmentCount++;
00180                                                         Segment++;
00181                                                         // Stretch Span to Left. 
00182                                                         Span->Min = Left;
00183                                                         if (LastSpan)
00184                                                                 {
00185                                                                         if (LastSpan->Max+1 == Span->Min)
00186                                                                                 {       // collapse LastSpan with Span
00187                                                                                         LastSpan->Max = Span->Max;
00188                                                                                         LastSpan->Next = Span->Next;
00189                                                                                         Span = LastSpan;
00190                                                                                         // *Span is lost for this frame
00191                                                                                 }
00192                                                                 }
00193                                                 }
00194                                 }
00195                         if (Left <= Span->Max)
00196                                 {
00197                                         Left = Span->Max + 1;
00198                                         if (Left > Right)
00199                                                 return SegmentCount;
00200                                 }
00201                         LastSpan = Span;
00202                         Span = Span->Next;
00203                 }
00204 
00205         // add span
00206         Segment->LeftOffset = Left - LeftStart;
00207         Segment->Width = Right - Left + 1;
00208         SegmentCount++;
00209 
00210 
00211         if (LastSpan)
00212                 {
00213                         if (LastSpan->Max+1 == Left)
00214                                 {       // stretch LastSpan 
00215                                         LastSpan->Max = Right;
00216                                 }
00217                         else
00218                                 {
00219                                         if (SpanBuffer_FirstSpare<SpanBuffer_MaxSpares)
00220                                                 NewSpan = &(SpanBuffer_Spares[SpanBuffer_FirstSpare++]);
00221                                         else
00222                                                 return SegmentCount;
00223                                         NewSpan->Min   = Left;
00224                                         NewSpan->Max   = Right;
00225                                         NewSpan->Next  = Span;
00226                                         LastSpan->Next = NewSpan;
00227                                 }       
00228                 }
00229         else
00230                 {
00231                         if (SpanBuffer_FirstSpare<SpanBuffer_MaxSpares)
00232                                 NewSpan = &(SpanBuffer_Spares[SpanBuffer_FirstSpare++]);
00233                         else
00234                                 return SegmentCount;
00235                         NewSpan->Min   = Left;
00236                         NewSpan->Max   = Right;
00237                         NewSpan->Next  = Span;
00238                         SpanBuffer_Lines[Line] = NewSpan;
00239                 }
00240 
00241 
00242         return SegmentCount;
00243 }       
00244 
00245 
00246 #if 0
00247 void SpanBuffer_Test()
00248 {
00249         int Visible;
00250 
00251         SpanBufferReset(1);
00252         Visible = SpanBuffer_Visible(0, 5,9 );
00253 
00254         SpanBufferClipAndAdd(0,30,10);
00255         Visible = SpanBuffer_Visible(0, 5,9 );
00256         Visible = SpanBuffer_Visible(0, 30,40);
00257         Visible = SpanBuffer_Visible(0, 30,41);
00258         Visible = SpanBuffer_Visible(0, 29,40);
00259         
00260         SpanBufferClipAndAdd(0,10,10);
00261         Visible = SpanBuffer_Visible(0, 10,50);
00262         Visible = SpanBuffer_Visible(0, 30,41);
00263         Visible = SpanBuffer_Visible(0, 50,60);
00264         Visible = SpanBuffer_Visible(0, 1,2);
00265         Visible = SpanBuffer_Visible(0, 15,35);
00266         Visible = SpanBuffer_Visible(0, 25,26);
00267         
00268         Visible = SpanBuffer_Visible(0, 10,20);
00269         Visible = SpanBuffer_Visible(0, 30,40);
00270         
00271                 
00272         SpanBufferClipAndAdd(0,5,50);
00273         Visible = SpanBuffer_Visible(0, 5,10);
00274         Visible = SpanBuffer_Visible(0, 60,70);
00275         Visible = SpanBuffer_Visible(0, 1,2);
00276 
00277 
00278 }
00279 #endif

Generated on Tue Sep 30 12:36:25 2003 for GTestAndEngine by doxygen 1.3.2