/* -------------------------------------------------------- planet.c General Graphics Interface demo A simple rotating planet Frederic Stark, 20 Nov 1997 -------------------------------------------------------- */ #include #include #include #include #include #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif /* Size of the in-memory picture Can be reduced for low-end machines, but resulting planet won't rotate much faster */ #define TX_XPOW 10 #define TX_YPOW 9 #define TX_WIDTH (1<HIGH_TEXTURE) return HIGH_TEXTURE; return aTexel; } /* Generate a texel randomly interpolated from v0 and v1 */ int GenTex2( int v0, int v1, int decal ) { int v = (v0+v1)/2; return Random( ClampTexel( v-decal ), ClampTexel( v+decal ) ); } /* Generate a texel randomly interpolated from v0, v1, v2, v3 */ int GenTex4( int v0, int v1, int v2, int v3, int step ) { return GenTex2( GenTex2( v0, v1, step ), GenTex2( v2, v3, step ), step ); } /* Builds a random texture */ void BuildTexture() { int x, y, theStep, theHalfStep; int theRandomStep; int theMax = min(TX_XPOW,TX_YPOW); float theHarsh; /* If theRandomStep is low, many texture points are fixed */ theRandomStep = 1<1) { theHalfStep = theStep/2; for (x=0;x!=TX_WIDTH;x+=theStep) for (y=0;y!=TX_HEIGHT;y+=theStep) { gTexture[y][x+theHalfStep] = GenTex2( GetTexture(x,y), GetTexture(x+theStep,y), theStep*theHarsh ); gTexture[y+theHalfStep][x] = GenTex2( GetTexture(x,y), GetTexture(x,y+theStep), theStep*theHarsh ); } for (x=0;x!=TX_WIDTH;x+=theStep) for (y=0;y!=TX_HEIGHT;y+=theStep) gTexture[y+theHalfStep][x+theHalfStep] = GenTex4( GetTexture(x,y), GetTexture(x+theStep,y), GetTexture(x,y+theStep), GetTexture(x+theStep,y+theStep), theStep*theHarsh ); theStep/=2; } } int SCREEN_WIDTH; int SCREEN_HEIGHT; #define gHALF_LINES HALF_LINES int HALF_LINES; int *gYOffsets; int *gXPixelCount; int **gOffsets; #define KPI 3.1415926535897932385 /* Builds the projection tables */ void BuildProjTables() { int i,j; gYOffsets = malloc( sizeof(int)*HALF_LINES ); gXPixelCount = malloc( sizeof(int)*HALF_LINES ); gOffsets = malloc( sizeof(int*)*HALF_LINES ); for (i=0;i!=HALF_LINES;i++) { gXPixelCount[i] = 0; gYOffsets[i]=0; if (gOffsets[i]) free(gOffsets[i]); gOffsets[i] = 0; } for (i=0;i!=gHALF_LINES;i++) { // Y offsets gYOffsets[i] = asin( i/(float)gHALF_LINES )/KPI*2*TX_HEIGHT/2; // Pixel count gXPixelCount[i] = sqrt( gHALF_LINES*gHALF_LINES-i*i ); // Offsets gOffsets[i] = malloc( sizeof(int)*gXPixelCount[i] ); for (j=0;j!=gXPixelCount[i];j++) gOffsets[i][j] = asin( j/(float)gXPixelCount[i] )/KPI*2*TX_WIDTH/4; } } #include ggi_visual_t disp; ggi_directbuffer_t dbuf; ggi_pixellinearbuffer *plb; char *fb; ggi_color clut[256]; /* Make a color */ ggi_color MakeColor( int r, int g, int b ) { ggi_color theColor; theColor.r = r; theColor.g = g; theColor.b = b; return theColor; } /* Returns a random color */ ggi_color RandomColor( ) { return MakeColor( Random( 0, 65535 ), Random( 0, 65535 ), Random( 0, 65535 ) ); } /* Set a color ramp in global palette */ void SetColorRamp( int aStart, int aEnd, ggi_color aStartColor, ggi_color aEndColor ) { int i; for (i=aStart;i<=aEnd;i++) { float pos = (i-aStart)/(float)(aEnd-aStart); clut[i].r = aStartColor.r*(1-pos)+aEndColor.r*pos; clut[i].g = aStartColor.g*(1-pos)+aEndColor.g*pos; clut[i].b = aStartColor.b*(1-pos)+aEndColor.b*pos; } } /* Set a black palette */ void BlackPalette() { int i; for (i=0;i!=256;i++) clut[i].r = clut[i].g = clut[i].b = 0; } /* TEST: Build a earth looking planet (dark-blue->blue->white)*/ void EarthColor() { int theWaterLimit = (LOW_TEXTURE+HIGH_TEXTURE)/2; theWaterLimit = ClampTexel( Random( theWaterLimit-32, theWaterLimit+32 ) ); SetColorRamp( LOW_TEXTURE, theWaterLimit, MakeColor( 237*256, 100*256, 23*256 ), MakeColor( 216*256, 96*256, 82*256 ) ); SetColorRamp( theWaterLimit, HIGH_TEXTURE, MakeColor( 216*256, 96*256, 82*256 ), MakeColor( 65535, 65535, 65535 ) ); } /* Set a random palette */ #define MAX_COLORS 5 void RandomPalette() { int i; int theColorCount; int theIndexes[MAX_COLORS+1]; int theSum=0; /* Choose how much color we want to have */ theColorCount = Random( 2, MAX_COLORS ); /* Choose indexes */ theIndexes[0] = 0; for (i=0;i!=theColorCount;i++) theIndexes[i+1] = theIndexes[i]+Random( 1, 100 ); /* Normalize in range LOW_TEXTURE, HIGH_TEXTURE */ theSum = theIndexes[theColorCount]; for (i=0;i!=theColorCount+1;i++) theIndexes[i] = theIndexes[i]/(float)theSum*(HIGH_TEXTURE-LOW_TEXTURE)+.5+LOW_TEXTURE; /* Build the ramp */ clut[LOW_TEXTURE] = RandomColor(); for (i=0;i!=theColorCount;i++) SetColorRamp( theIndexes[i], theIndexes[i+1], clut[theIndexes[i]], RandomColor() ); /* Sometimes we choose the last color to match the first to get nice(?) looking rotating palettes */ if (Random(0,1)==0) SetColorRamp( theIndexes[theColorCount-1], theIndexes[theColorCount], clut[theIndexes[theColorCount-1]], clut[LOW_TEXTURE] ); } /* Set the needed graphic mode */ /* FIXME: if graph mode fails, we'll just core dump */ void SetupGraphics() { ggiInit(); disp = ggiOpen(NULL); ggiSetFocus(disp); ggiSetGraphMode( disp, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, GT_8BIT ); ggiDBGetBuffer(disp,&dbuf); plb = ggiDBGetPLB(dbuf); fb = plb->write; } /* Set current palette */ void SetPalette() { ggiSetPaletteVec(disp,0,256,clut); } /* Current position of the planet */ int gOffset = 0; /* #### Set rotated palette */ void AnimatePalette() { int theStart = gOffset%(HIGH_TEXTURE-LOW_TEXTURE+1); ggiSetPaletteVec(disp,LOW_TEXTURE,HIGH_TEXTURE-LOW_TEXTURE+1-theStart,clut+LOW_TEXTURE+theStart); ggiSetPaletteVec(disp,HIGH_TEXTURE-theStart+1,theStart,clut+LOW_TEXTURE); } /* Draws the planet */ void Draw() { int x; int y; /* Enable this define to see the texture instead of the palette */ #if 0 for (x=0;x!=SCREEN_WIDTH;x++) for (y=0;y!=SCREEN_HEIGHT;y++) if (x /* For getpid() */ int main( int argc, char **argv ) { int c; int animFlag; int theSeed; if (argc<3 || argc>5) { fprintf( stderr, "%s WIDTH HEIGHT [RADIUS] []\n", argv[0] ); fprintf( stderr, " RADIUS have to be less or equal to the min of WIDTH and HEIGHT\n" ); fprintf( stderr, " NUMBER is a random seed\n" ); fprintf( stderr, "During the demo: \n" ); fprintf( stderr, " 'p': change palette\n" ); fprintf( stderr, " 'a' to animate it\n" ); fprintf( stderr, " any other key to exit\n" ); exit( EXIT_FAILURE ); } SCREEN_WIDTH = atoi(argv[1]); SCREEN_HEIGHT = atoi(argv[2]); HALF_LINES = SCREEN_HEIGHT/2; if (argc>3) HALF_LINES = atoi(argv[3]); if (argc==4) { theSeed = getpid(); printf( "SEED=%d\n", theSeed ); } else theSeed = atoi(argv[4]); HALF_LINES = min( HALF_LINES, SCREEN_HEIGHT/2 ); HALF_LINES = min( HALF_LINES, SCREEN_WIDTH/2 ); srand(theSeed); animFlag = Random(0,1); SetupGraphics(); // EarthColor(); RandomPalette(); SetPalette(); BuildTexture(); BuildProjTables(); while(1) { if (ggiKbhit(disp)) switch (c=KVAL(U(ggiGetc(disp)))) { case 'p': RandomPalette(); SetPalette(); break; case 'a': animFlag = 1-animFlag; break; default: return EXIT_SUCCESS; } Draw(); if (animFlag) AnimatePalette(); ggiFlush(disp); gOffset+=1; } /* Not reached */ return EXIT_SUCCESS; }