STARS.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 - OpenFX Development Team
00004 -- */
00005 
00006 /* STARS.C  example image post-processing module                        */
00007 /*                                                                      */
00008 /*  This post processing example give users the opportunity to set an   */
00009 /*  animation agains a background of a starfield, the stars can be      */
00010 /*  as simple as a regular grid to a astronomically accurate cluster.   */
00011 /*  The example illustrates drawing pixels in the screenbuffer and      */
00012 /*  using the TransformIntoView function to bring the star location     */
00013 /*  given in World Coordinates to the screen.  It also shows how the    */
00014 /*  "ruler" varible is used to switch from User to World co-ords.       */
00015 /*                                                                      */
00016 
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <float.h>
00020 #include <math.h>
00021 #include <windows.h>
00022 #include <gl\gl.h>
00023 #include <gl\glu.h>
00024 
00025 #include "struct.h"           /* general structures    */
00026 #include "..\common\postprocess\ximage.h"
00027 #include "local.h"
00028 
00029 #include "stars.h"    /* dialog box id's    */
00030 
00031 #if __X__MIPS__
00032 BOOL WINAPI _CRT_INIT(HINSTANCE ,DWORD , LPVOID );
00033 #endif
00034 
00035 static HINSTANCE hDLLinstance=NULL; /* use to pick up resources from DLL   */
00036 static long version=1;
00037 
00038 /************************** Local Utility Functions ***********************/
00039 
00040 #include "utils.h"
00041 #include "paint.c"
00042 
00043 /************************** DLL entry point ********************************/
00044 
00045 #if __WATCOMC__
00046 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00047 #elif __BC__
00048 BOOL WINAPI DllEntryPoint(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00049 #else
00050 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00051 #endif
00052   switch (dwReason) {
00053     case DLL_PROCESS_ATTACH:
00054 #if __X__MIPS__
00055       if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00056 #endif
00057       hDLLinstance = hDLL;  /* handle to DLL file */
00058       break;
00059     case DLL_PROCESS_DETACH:
00060 #if __X__MIPS__
00061       if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00062 #endif
00063       break;
00064   }
00065 return (int)TRUE;
00066 }
00067 
00068 #if __SC__
00069 #pragma startaddress(DllMain)
00070 #endif
00071 
00072 /*******************************************************************\
00073 |                Code that executes the process                     |
00074 \*******************************************************************/
00075 
00076 void DrawInBuffer(BOOL black,
00077                   fullscreenbuffer *Screen, int Xmax, int Ymax,
00078                   int x, int y, unsigned char v ){
00079  int r,g,b;
00080  fullscreenbuffer *S;
00081  if(x < 0 || y < 0 || x >= Xmax || y >= Ymax)return;
00082  S=(Screen+y*Xmax+x);
00083  if(black &&(S->R > 1 || S->G > 1 || S->B > 1))return;
00084  r=(int)S->R+(int)v;
00085  g=(int)S->G+(int)v;
00086  b=(int)S->B+(int)v;
00087  S->R=(r>255) ? 255:r;
00088  S->G=(g>255) ? 255:g;
00089  S->B=(b>255) ? 255:b;
00090 }
00091 
00092 #define frac(z) fmod(z,1.0)
00093 
00094 void DrawAApixel(BOOL black,
00095                  double x, double y, double w, double h,int brite,
00096                  fullscreenbuffer *S, int X, int Y){
00097   int xa,xb,ya,yb,i,j;
00098   double x2,y2,lfrac,rfrac,tfrac,bfrac,xfrac,yfrac;
00099   x2 = x + w;
00100   y2 = y + w;
00101   xa = (int)x;
00102   xb = (int)x2;
00103   ya = (int)y;
00104   yb = (int)y2;
00105   lfrac = 1.0-frac(x);
00106   rfrac = frac(x2);
00107   tfrac = 1.0-frac(y);
00108   bfrac = frac(y2);
00109   if (xa==xb) {
00110     xfrac = lfrac+rfrac-1.0;
00111     if (ya==yb) {
00112       DrawInBuffer(black,S,X,Y,xa,ya,xfrac*(tfrac+bfrac-1.0)*brite);
00113     }
00114     else {
00115       DrawInBuffer(black,S,X,Y,xa,ya,xfrac*tfrac*brite);
00116       for (j=ya+1; j<yb; j++) DrawInBuffer(black,S,X,Y,xa,j,xfrac*brite);
00117       DrawInBuffer(black,S,X,Y,xa,yb,xfrac*bfrac*brite);
00118     }
00119   }
00120   else {
00121     if (ya==yb) {
00122       yfrac = tfrac+bfrac-1.0;
00123       DrawInBuffer(black,S,X,Y,xa,ya,yfrac*lfrac*brite);
00124       for (i=xa+1; i<xb; i++) DrawInBuffer(black,S,X,Y,i,ya,yfrac*brite);
00125       DrawInBuffer(black,S,X,Y,xb,ya,yfrac*rfrac*brite);
00126     }
00127     else {
00128       DrawInBuffer(black,S,X,Y,xa,ya,tfrac*lfrac*brite);
00129       for (i=xa+1; i<xb; i++) DrawInBuffer(black,S,X,Y,i,ya,tfrac*brite);
00130       DrawInBuffer(black,S,X,Y,xb,ya,tfrac*rfrac*brite);
00131       for (j=ya+1; j<yb; j++) {
00132         DrawInBuffer(black,S,X,Y,xa,j,lfrac*brite);
00133         for (i=xa+1; i<xb; i++)DrawInBuffer(black,S,X,Y,i,j,brite);
00134         DrawInBuffer(black,S,X,Y,xb,j,rfrac*brite);
00135       }
00136       DrawInBuffer(black,S,X,Y,xa,yb,bfrac*lfrac*brite);
00137       for (i=xa+1; i<xb; i++) DrawInBuffer(black,S,X,Y,i,yb,bfrac*brite);
00138       DrawInBuffer(black,S,X,Y,xb,yb,bfrac*rfrac*brite);
00139     }
00140   }
00141 }
00142 
00143 static void DrawPointInBuffer(BOOL black, long x, long y,
00144                               fullscreenbuffer *Screen,
00145                               long X, long Y){
00146  /* draw a white star at screen co-ordinate (x,y)                  */
00147  fullscreenbuffer *S;
00148  S=(Screen + y*X + x);
00149  /* if not black don't draw, this is like 'blue screen' and should */
00150  /* simulate drawing in background only (well quite near!)         */
00151  if(black && (S->R > 1 || S->G > 1 || S->B > 1))return;
00152  S->R = (unsigned char)255.0;
00153  S->G = (unsigned char)255.0;
00154  S->B = (unsigned char)255.0;
00155  return;
00156 }
00157 
00158 long RegularGridOfStars(char *PrmList, XIMAGE *lpXimage){
00159  /* lights have been transformed to Renderer frame of reference  */
00160  /* Z is UP, Y is forward (in front of observer, X to the RIGHT  */
00161  /* the camera is located at 0,0,0. All real numbers are floats  */
00162  /* xx and yy are screen co-ords of light (0,0) is at top left   */
00163  /* With a big grid the camera can be made to appear to move     */
00164  /* inside the star field.                                       */
00165  long i,j,k,ispacing,nside,ifade,mi,mispacing,mnside,mifade;
00166  char dummy[255];
00167  double x,y,z,xp,yp,zp;
00168  double xx,yy,fade,mr;      /* screen coordinates of point to be plotted  */
00169  float *Zb;
00170  BOOL bMorph=FALSE;
00171  sscanf(PrmList,"%s %ld %ld %ld %s %ld %ld",
00172         dummy,&i,&nside,&ispacing,dummy,&version,&ifade);
00173  if(lpXimage->Morph && lpXimage->mParameters != NULL){
00174    bMorph=TRUE; mr=lpXimage->MorphRatio;
00175    sscanf(lpXimage->mParameters,"%s %ld %ld %ld %s %ld %ld",
00176         dummy,&mi,&mnside,&mispacing,dummy,&version,&mifade);
00177  }
00178  if(bMorph){
00179    fade=((double)mifade + mr*((double)ifade-(double)mifade))/100.0;
00180  }
00181  else fade=1.0;
00182  /* calculate regular 3D grid of stars spaced "ispacing" apart,   */
00183  /* ispacing is a World (long int) co-ordinate                    */
00184  Zb=lpXimage->Zbuffer;
00185  for(i=0;i<nside;i++){
00186    xp=(double)((i-nside/2)*ispacing);
00187  for(j=0;j<nside;j++){
00188    yp=(double)((j-nside/2)*ispacing);
00189  for(k=0;k<nside;k++){
00190    zp=(double)((k-nside/2)*ispacing);
00191    TransformIntoView(lpXimage->ViewTransform,xp,yp,zp,&x,&y,&z);
00192    if(y >= 1.000){  /* all points in front of viewer */
00193      xx=(double)lpXimage->Xmax/2.0 + (lpXimage->Xscale*x/y);
00194      yy=(double)lpXimage->Ymax/2.0 - (lpXimage->Yscale*z/y);
00195      if((long)xx >= 0 && (long)xx < lpXimage->Xmax &&
00196         (long)yy >= 0 && (long)yy < lpXimage->Ymax){
00197        /* this point is visible on screen */
00198        if(Zb != NULL){
00199         if(*(Zb + ((long)yy * lpXimage->Xmax) + (long)xx) > FARAWAY-10.0)
00200           DrawAApixel(FALSE,(long)xx,(long)yy,1.5,1.5,
00201                         (long)(255.0*fade),lpXimage->Screen,
00202                         lpXimage->Xmax,lpXimage->Ymax);
00203        }
00204        else DrawAApixel(TRUE,(long)xx,(long)yy,1.5,1.5,
00205                         (long)(255.0*fade),lpXimage->Screen,
00206                         lpXimage->Xmax,lpXimage->Ymax);
00207      }
00208    }
00209  }
00210  }
00211  }
00212  return 1;
00213 }
00214 
00215 /* A utility function that helps determine the name of the Star data file. */
00216 /* The Star data filename is derived from the name and the directory where */
00217 /* the STAR.DLL image processor is located                                 */
00218 
00219 #include "..\animate\wspaces.c"
00220 
00221 PSTR FileInPath(PSTR pstrPath){
00222  PSTR pstr;
00223  pstr = pstrPath + strlen(pstrPath);
00224  while (pstr > pstrPath) {
00225      pstr = (AnsiPrev(pstrPath, pstr));
00226      if (*pstr == '\\' || *pstr == ':' || *pstr == '/') {
00227          pstr = (AnsiNext(pstr));
00228          break;
00229      }
00230  }
00231  return pstr;
00232 }
00233 
00234 typedef struct{     /* star data base */
00235   long x,y,z;
00236 } Star;
00237 
00238 long _RenderImageProcess(char *PrmList, XIMAGE *lpXimage){
00239  int ix,nStars;
00240  Star *stardata=NULL;
00241  FILE *ifp=NULL;
00242  long i,j,k,ispacing,nside,ifade,mi,mj,mk,mifade;
00243  char xname[255],dummy[255],starname[16];
00244  double x,y,z,xp,yp,zp,mr;
00245  double xx,yy,fade;      /* screen coordinates of point to be plotted  */
00246  float *Zb;
00247  BOOL bMorph=FALSE;
00248  sscanf(PrmList,"%s %ld",dummy,&i);
00249  if(i == 0){ /* use a regular grid of stars */
00250    RegularGridOfStars(PrmList,lpXimage);
00251    return 1;
00252  }
00253  /* use the data from the database          */
00254  sscanf(PrmList,"%s %ld %ld %ld %s %ld %ld",
00255         xname,&i,&j,&k,starname,&version,&ifade);
00256  if(lpXimage->Morph && lpXimage->mParameters != NULL){
00257    bMorph=TRUE; mr=lpXimage->MorphRatio;
00258    sscanf(lpXimage->mParameters,"%s %ld %ld %ld %s %ld %ld",
00259         dummy,&mi,&mj,&mk,dummy,&version,&mifade);
00260  }
00261  if(bMorph){
00262    fade=((double)mifade + mr*((double)ifade-(double)mifade))/100.0;
00263  }
00264  else fade=1.0;
00265  /* get the name of the data file based on the processing module filename */
00266  /* this assumes that the data file is in the Ximage directory            */
00267  RestoreWhiteSpaces(xname);
00268  *FileInPath(xname) = '\0';
00269  strcat(xname,starname);
00270  if((ifp=fopen(xname,"rb"))== NULL){
00271    /* Try to base file on module base */
00272    strcpy(xname,lpXimage->ModuleName);
00273    *FileInPath(xname) = '\0';
00274    strcat(xname,starname);
00275    if((ifp=fopen(xname,"rb"))== NULL){
00276      MessageBeep(MB_OK);
00277      return 0;
00278    }
00279  }
00280  /* read the number of stars */
00281  if(fread(&nStars,sizeof(int),1,ifp)!=1)goto CLOSEDOWN;
00282  if(nStars < 1)goto CLOSEDOWN;
00283  if((stardata=X__Malloc(nStars*sizeof(Star)))==NULL){
00284    MessageBeep(MB_OK);
00285    goto CLOSEDOWN;
00286  }
00287  /* Read the star data, the data is recorded in long ints that are    */
00288  /* sufficiently large so that they are apparently over the horizon!  */
00289  if(fread(stardata,sizeof(Star),nStars,ifp)!=nStars){
00290    MessageBeep(MB_OK);
00291    goto CLOSEDOWN;
00292  }
00293  fclose(ifp); ifp=NULL;
00294  Zb=lpXimage->Zbuffer;
00295  for(i=0;i<nStars;i++){
00296    xp=(double)stardata[i].x;
00297    yp=(double)stardata[i].y;
00298    zp=(double)stardata[i].z;
00299    TransformIntoView(lpXimage->ViewTransform,xp,yp,zp,&x,&y,&z);
00300    if(y >= 1.000){  /* all points in front of viewer */
00301      xx=(double)lpXimage->Xmax/2.0 + (lpXimage->Xscale*x/y);
00302      yy=(double)lpXimage->Ymax/2.0 - (lpXimage->Yscale*z/y);
00303      if((long)xx >= 0 && (long)xx < lpXimage->Xmax &&
00304         (long)yy >= 0 && (long)yy < lpXimage->Ymax){
00305        /* this point is visible on screen */
00306      if(Zb != NULL){
00307         if(*(Zb + ((long)yy * lpXimage->Xmax) + (long)xx) > FARAWAY-10.0)
00308           DrawAApixel(FALSE,(long)xx,(long)yy,1.5,1.5,
00309                         (long)(255.0*fade),lpXimage->Screen,
00310                         lpXimage->Xmax,lpXimage->Ymax);
00311        }
00312          else DrawAApixel(TRUE,(long)xx,(long)yy,1.5,1.5,
00313                         (long)(255.0*fade),lpXimage->Screen,
00314                         lpXimage->Xmax,lpXimage->Ymax);
00315      }
00316    }
00317  }
00318  CLOSEDOWN:
00319  if(stardata != NULL)X__Free(stardata);
00320  if(ifp != NULL)fclose(ifp);
00321  return 1;
00322 }
00323 
00324 /*************** Function that renders anyof the OpenGL Functionality ************/
00325 
00326 long _RenderGLexternal(char *PrmList, XIMAGE *lpXimage){
00327  //MessageBox(NULL,"Stars OpenGL function called","OK",MB_OK);
00328  return 1;
00329 }
00330 
00331 
00332 /******** Functions used to set process parameters ***********/
00333 
00334 /* Dialog box callback  */
00335 BOOL CALLBACK DlgProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);
00336 
00337 /* static variables that give defaults                                   */
00338 static double spacing=1.0;          /*              in user co-ordinates */
00339 static long startype=0,nside=10,ifade=100;
00340 static char starfile[16]="STARS.DAT";
00341 
00342 char * _SetExternalParameters(
00343   char *Op,                 /* string for the parameters                  */
00344   HWND hWnd,                /* parent window                              */
00345   long ruler,               /* ruler scale value to facilitate scaling    */
00346   char *name,               /* name of DLL file with the effect           */
00347   X__MEMORY_MANAGER *lpEVI /* pointer to structure with memory functions */
00348                                     ){
00349  /* output name and buffer should be as long as necessary to hold full string */
00350  char buffer[256];
00351  int ispacing;
00352  if(Op != NULL){  /* parameters exist so read them off the list             */
00353    sscanf(Op,"%s %ld %ld %ld %s %ld %ld",buffer,&startype,&nside,&ispacing,
00354           starfile,&version,&ifade);
00355    /* transform from World co-ordinates stored in parameter list to User    */
00356    /* coords for Dialog box edit control. The variable "ruler" is the ratio */
00357    /* between the integer co-ordinates used internally and the dimensions   */
00358    /* set by the user in the animator's Co-ord dialog box.                  */
00359    spacing=(double)ispacing/(double)ruler;
00360  }
00361  /*   Do the user interface as required to set up the effect, may use a     */
00362  /*   dialog box etc. Return old string if effect is cancelled (no change)  */
00363  if(DialogBox(hDLLinstance,MAKEINTRESOURCE(DLG_STARS),hWnd,
00364               (DLGPROC)DlgProc) == FALSE)return Op;
00365  /* Free space occupied by old parameter string */
00366  if(Op != NULL)CALL_FREE(Op);  /* free the old string */
00367  /* print the parameters into the buffer */
00368  ispacing=(long)(spacing*(double)ruler);
00369  sprintf(buffer,"%s %ld %ld %ld %s %ld %ld",name,startype,nside,ispacing,
00370          starfile,version,ifade);
00371  /* Prepare the output buffer to take copy of parameter list */
00372  if((Op=(char *)CALL_MALLOC(strlen(buffer)+1)) == NULL){
00373   MessageBox (GetFocus(),"External effect: Out of memory","Error",
00374                 MB_OK|MB_TASKMODAL|MB_ICONSTOP);
00375    return NULL;
00376  }
00377  /* Copy the parameter string to the output buffer */
00378  strcpy(Op,buffer);
00379  return Op;
00380 }
00381 
00382 BOOL CALLBACK DlgProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam){
00383  char temp[16];
00384  BOOL err;
00385  switch( msg ) {
00386    case WM_INITDIALOG:
00387      if(startype == 0)
00388        SendDlgItemMessage(hwnd,DLG_STARS_REGULAR,BM_SETCHECK,TRUE,0);
00389      else
00390        SendDlgItemMessage(hwnd,DLG_STARS_FILE,BM_SETCHECK,TRUE,0);
00391      SetDlgItemText(hwnd,DLG_STARS_NAME,starfile);
00392      SetDlgItemInt(hwnd,DLG_STARS_NSIDE,nside,FALSE);
00393      SetDlgItemInt(hwnd,DLG_STARS_BRIGHTNESS,ifade,FALSE);
00394      sprintf(temp,"%.2f",spacing);
00395      SetDlgItemText(hwnd,DLG_STARS_SPACING,temp);
00396      CentreDialogOnScreen(hwnd);
00397      return TRUE;
00398    case WM_PAINT:
00399      PaintBackground(hwnd);
00400      break;
00401    case WM_COMMAND:
00402      switch(LOWORD(wparam)){
00403         case IDCANCEL:
00404           EndDialog(hwnd,FALSE);
00405           return(TRUE);
00406         case IDOK:
00407           if(SendDlgItemMessage(hwnd,DLG_STARS_FILE,BM_GETCHECK,0,0))
00408                startype=1;
00409           else startype=0;
00410           if(GetDlgItemText(hwnd,DLG_STARS_NAME,starfile,12) == 0)
00411             strcpy(starfile,"EARTH.STB");
00412           if(GetDlgItemText(hwnd,DLG_STARS_SPACING,temp,12) == 0)
00413             spacing=1.0;
00414           else spacing=atof(temp);
00415           nside=GetDlgItemInt(hwnd,DLG_STARS_NSIDE,&err,FALSE);
00416           if(nside < 2)nside=2;
00417           ifade=GetDlgItemInt(hwnd,DLG_STARS_BRIGHTNESS,&err,FALSE);
00418           EndDialog(hwnd,TRUE);
00419           return(TRUE);
00420         default:
00421           break;
00422       }
00423       break;
00424     default: break;
00425  }
00426  return FALSE;
00427 }
00428 

Generated on Sun Apr 27 14:20:12 2014 for OpenFX by  doxygen 1.5.6