RENDER.C

Go to the documentation of this file.
00001 // File render.c
00002 
00003 #define MODULE_RENDER
00004 
00005 #include "render.h"
00006 
00007 extern HWND hWndOpenGL;
00008 extern short mirror_ground;
00009 extern init_structures(void);
00010 extern HINSTANCE hThisInstance;
00011 extern void SetLightShadow(long i);
00012 extern void Free_Mirror_On_Ground(void);
00013 extern void Free_Lights_Shadows(void);
00014 extern void Mirror_In_Ground(void);
00015 
00016 static int TransformSceneForRendering(long *, long, long);
00017 static short TransformObjectIntoPosition(long O);
00018 static void CalculateFaceNormals(vertex *v, face *f, long O);
00019 static int PsameSide(vector pt, vector p, vector n);
00020 static CalculateObjectScreenCoordinates(long O);
00021 
00022 BOOL bKeepObjectsInRAM=TRUE;  
00023 FILE *CF=NULL;
00024 long renderer_NT_abort_flag=0;
00025 short End_of_animation;
00026 
00027 static char ambient_flag=0,outputfile[256];
00028 
00029 char *short_form(char *filename){ 
00030  char *sps,*spc;
00031  sps=spc=filename;
00032  while((spc=strchr(spc,'\\')) != NULL){spc++; sps=spc;}
00033  return sps;
00034 }
00035 
00036 short R_terminator(void){    
00037  char c;
00038  if(renderer_NT_abort_flag && ConfirmNTabort())return FAIL;
00039  renderer_NT_abort_flag=0;
00040  return NO;
00041 }
00042 
00058 int render(int argc, char **argv){
00059  char  scriptfile[512];
00060  char  outputroot[512];
00061  char  c,temp_str[256],format[128],temp_message[128];
00062  long  i,j,frame,subframe,command_id,firstframe,lastframe,
00063        failure=NO,x_xmax,y_ymax,nAnimStart,version,
00064        ApplyPPtoGL=NO;
00065  short flash_count,truevision=0,targa_compress=1;
00066  fullscreenbuffer *stereo_buffer=NULL;
00067  long StereoPosition;
00068  BOOL StereoFrame;
00069  //
00070  X_message=X__local_print;
00071  WindowedRenderInfo("Scene:");
00072  renderer_silent=0;/* if printing output, vector printf() function */
00073  firstframe=1; lastframe=65536;
00074  anti_alias=NONE; anti_alias_edges=NO;
00075  remove_hidden_faces=NO;
00076  instant_callback=NO; shadow_buffer_size=300;
00077  //FAST=NO; 
00078  OUTPUT_FILE_TYPE=B24_FILE; XMAX=320; YMAX=200;
00079  ColourResolution=BITS8; End_of_animation=0; colour0_flag=0;
00080  FullScreenBuffer=NULL; fszBuffer=NULL;
00081  objectIDbufferON=YES; ObjectIdBuffer=NULL;
00082  alfachannelON=NO; alfagroundON=NO;
00083  StereoRenderingON=NO;
00084  ntsc_colours=NO; full_mirror=FALSE;
00085  MotionBlurBuffer=NULL; mblurON=0; jpeg_quality=75;
00086  trace_shadows=NO; trace_reflections=NO; trace_refractions=NO;
00087  trace_partition=1; trace_depth=8;
00088  trace_face_count_target=25; trace_voxel_min_size=4;
00089  ClipXmin=ClipYmin=ClipZmin=0;       //BIGN;  // For scripts without scene bounds defined in scripts
00090  ClipXmax=ClipYmax=ClipZmax=UNIT*20; //BIGP;  // some apprximations for the Designer renderer
00091  tzeros=4;
00092  if(argc < 3){
00093   Render_Message(40,0,NULL);
00094   goto EXITPOINT;
00095  }
00096  else if(argc > 3){
00097    i=3;
00098    while(i < argc){
00099      if(strcmp(argv[i],"-an2" ) == 0){  // animation - high colour def
00100        ColourResolution=BITS24; OUTPUT_FILE_TYPE=AVI_FILE;
00101      }
00102      else if(strcmp(argv[i],"-t24") == 0){
00103        ColourResolution=BITS24; OUTPUT_FILE_TYPE=TIF_FILE;
00104      }
00105      else if(strcmp(argv[i],"-b24") == 0){
00106        ColourResolution=BITS24; OUTPUT_FILE_TYPE=B24_FILE;
00107      }
00108      else if(strcmp(argv[i],"-p24") == 0){
00109        ColourResolution=BITS24; OUTPUT_FILE_TYPE=PNG_FILE;
00110      }
00111      else if(strcmp(argv[i],"-j24") == 0){
00112        ColourResolution=BITS24; OUTPUT_FILE_TYPE=J24_FILE;
00113        i++; jpeg_quality = atol(argv[i]);
00114      }
00115      else if(strcmp(argv[i],"-cbk") == 0){
00116        instant_callback=YES;  // show image while rendering 
00117      }
00118      else if(strcmp(argv[i],"-h"   ) == 0){ApplyPPtoGL=YES;}
00119      else if(strcmp(argv[i],"-x"   ) == 0){i++; XMAX=atoi(argv[i]); }
00120      else if(strcmp(argv[i],"-y"   ) == 0){i++; YMAX=atoi(argv[i]); }
00121      //else if(strcmp(argv[i],"-f"   ) == 0)FAST=YES;
00122      else if(strcmp(argv[i],"-ff"  ) == 0){i++; firstframe=atoi(argv[i]); }
00123      else if(strcmp(argv[i],"-lf"  ) == 0){i++; lastframe=atoi(argv[i]);  }
00124      else if(strcmp(argv[i],"-ae"  ) == 0)anti_alias_edges=YES;
00125      else if(strcmp(argv[i],"-a"   ) == 0)anti_alias=LOW;
00126      else if(strcmp(argv[i],"-aa"  ) == 0)anti_alias=MEDIUM;
00127      else if(strcmp(argv[i],"-aaa" ) == 0)anti_alias=HIGH;
00128      else if(strcmp(argv[i],"-aaaa") == 0)anti_alias=ULTRA;
00129      else if(strcmp(argv[i],"-sto" ) == 0)StereoRenderingON=YES;
00130      else if(strcmp(argv[i],"-z"   ) == 0){;} // No dithering 
00131      else if(strcmp(argv[i],"-zz"  ) == 0){ // NO dithering 
00132        i++;
00133      }
00134      else if(strcmp(argv[i],"-w"   ) == 0){ // not used now
00135        i++;
00136      }
00137      else if(strcmp(argv[i],"-ac"  ) == 0){ // not used now (but alpha is used in PNG files!)
00138        alfachannelON=YES;
00139      }
00140      else if(strcmp(argv[i],"-acg" ) == 0){ // not used now
00141        alfagroundON=YES;
00142      }
00143      //else if(strcmp(argv[i],"-zb"  ) == 0){;} // always ON
00144      else if(strcmp(argv[i],"-al"  ) == 0){
00145        i++; ambient_light= ((double)atof(argv[i]))/100.0; /* % light */
00146        ambient_flag=1; /* override script ambients */
00147      }
00148      else if(strcmp(argv[i],"-sd"  ) == 0){
00149        i++; shadow_density = 1.0-((double)atof(argv[i])/100.0); /* %age */
00150        glass_shadow_density = 1.0-0.5*((double)atof(argv[i])/100.0);
00151      }
00152      else if(strcmp(argv[i],"-sc"  ) == 0){
00153        i++; smoothing_angle = cos((double)atof(argv[i])*PI/180.0); /* cos angle */
00154      }
00155      else if(strcmp(argv[i],"-c0"  ) == 0){ // not used now
00156        i++;             /* colour zero option */
00157        if     (strcmp(argv[i],"b") == 0){
00158 //         colour0_flag=1; colour0_red=0; colour0_green=0; colour0_blue=0;
00159        }
00160        else if(strcmp(argv[i],"w") == 0){
00161 //         colour0_flag=2; colour0_red=255; colour0_green=255; colour0_blue=255;
00162        }
00163        else  colour0_flag=0;
00164      }
00165      else if(strcmp(argv[i],"-sb"  ) == 0){
00166        i++; shadow_buffer_size=atoi(argv[i]);
00167        if(shadow_buffer_size < 0)shadow_buffer_size=0;
00168        if(shadow_buffer_size > 1024)shadow_buffer_size=1024;
00169      }
00170      else if(strcmp(argv[i],"-tz"  ) == 0){
00171        i++; tzeros = atol(argv[i]); /* trailing zeros */
00172      }
00173 #if TRACER
00174      else if(strcmp(argv[i],"-trs"  ) == 0)trace_shadows=YES;
00175      else if(strcmp(argv[i],"-trr"  ) == 0)trace_reflections=YES;
00176      else if(strcmp(argv[i],"-trg"  ) == 0)trace_refractions=YES;
00177      else if(strcmp(argv[i],"-to"   ) == 0)trace_partition=0;
00178      else if(strcmp(argv[i],"-tod"  ) == 0){
00179        i++; trace_depth = atol(argv[i]); /* depth of tree */
00180      }
00181      else if(strcmp(argv[i],"-tot"  ) == 0){
00182        i++; trace_face_count_target = atol(argv[i]); /* face in voxel */
00183      }
00184      else if(strcmp(argv[i],"-tos"  ) == 0){
00185        i++; trace_voxel_min_size = atol(argv[i]); /* sizeo of voxel */
00186      }
00187 #endif
00188      else if(strcmp(argv[i],"-q"   ) == 0){  /* quiet operation */
00189        OUTPUT_FILE_TYPE=NUL_FILE;
00190        renderer_silent=1;
00191      }
00192      else if(strcmp(argv[i],"-prv" ) == 0){
00193        // NOT in this renderer - ignore
00194      }
00195      else if(strcmp(argv[i],"-ntsc") == 0){
00196        ntsc_colours=YES;
00197      }
00198      else if(strcmp(argv[i],"-blr") == 0){
00199        i++; mblurON = (int)atoi(argv[i]);
00200      }
00201      else if(strcmp(argv[i],"-fm") == 0){
00202        full_mirror=TRUE;
00203      }
00204      else if(strcmp(argv[i],"-ob") == 0){;} // always ON
00205      i++;
00206    }
00207  }
00208  ResolutionX=XMAX; ResolutionY=YMAX;
00209  aaXstep=1; aaYstep=1;
00210  // IF we are tracing GLASS then there is no need to use the Scanline GLASS layers.
00211  // The function pointers are directed appropriately
00212  if(trace_refractions)UpdateScanBuffers=UpdateNoGlassScanBuffers;
00213  else                 UpdateScanBuffers=UpdateGlassScanBuffers;
00214  if(anti_alias_edges)full_mirror=FALSE;
00215  if(anti_alias == LOW)   {XMAX *= 2; aaXstep=2; aaYstep=1;}
00216  if(anti_alias == MEDIUM){XMAX *= 2; YMAX *= 2; aaXstep=2; aaYstep=2;}
00217  if(anti_alias == HIGH)  {XMAX *= 3; YMAX *= 2; aaXstep=3; aaYstep=2;}
00218  if(anti_alias == ULTRA) {XMAX *= 3; YMAX *= 3; aaXstep=3; aaYstep=3;}
00219  frame=0;
00220  command_id=0;
00221  if(firstframe < 1)firstframe=1;
00222  if(firstframe > lastframe)firstframe=lastframe;
00223  flash_count=0; wave_phase=0.0;
00224  if(InitialiseNoise() == FAIL){
00225    Render_Message(13,0,NULL); goto EXITPOINT;
00226  }
00227  init_spec();        // Initialise the specularity look-up table.
00228  init_structures();  // Initialise the structures that will be used to pass Renderer data to the plug-ins
00229  setup_render_discarded_list();
00230  if(AllocateRamBuffers() == FAIL){ // Allocate the main memory buffers
00231    Render_Message(13,0,NULL); goto EXITPOINT;
00232  }
00233  for (i=0;i<nCOLOUR;i++)colorstats0[i] = 0; colorstats0[0]=65536*1024L;
00234  for(i=0;i<XMAX;i++)DummyShadow[i]=0;
00235  sprintf(scriptfile,"%s.scr",argv[1]);
00236  // NOW READY TO RENDER AN ANIMATION FROM A SCRIPT FILE READ WRITTEN BY ANIMATOR
00237  if((CF=fopen((char *)scriptfile,"r")) == NULL){
00238    Render_Message(41,1,NULL);
00239    goto EXITPOINT;
00240  }
00241  fscanf(CF,"%s",temp_str);
00242  if(temp_str[2] == '2')version=2; else version=1;
00243  if(temp_str[0] == 'R'){ /* get the number of frames in the script */
00244    fscanf(CF,"%s",temp_str);
00245    nScriptframes=atoi(temp_str);
00246    fscanf(CF,"%s",temp_str);
00247    nAnimStart=atoi(temp_str)-1;
00248  }
00249  else{
00250    fscanf(CF,"%s",temp_str);
00251    nScriptframes=9999;
00252    nAnimStart=0;
00253  }
00254  if(version > 1){// Read the scene bounds to use for clipping planes
00255    fscanf(CF,"%ld %ld",&ClipXmin,&ClipXmax);
00256    fscanf(CF,"%ld %ld",&ClipYmin,&ClipYmax);
00257    fscanf(CF,"%ld %ld",&ClipZmin,&ClipZmax);
00258  }
00259  ObjectCount=0; Object=NULL; 
00260  Nshader=0; Shader=NULL;
00261  StereoFrame=TRUE;  // this is rendering the left frame
00262  NEXTFRAME:
00263  if(StereoRenderingON){
00264    // When doing stereo we need to render the frame twice 
00265    // do this by re-rendering the frame from the left and right position
00266    // re-rendering is done by re-reading the script file and adjusting the viewpoint.
00267    if(StereoFrame)StereoPosition=ftell(CF); 
00268    else fseek(CF,StereoPosition,0);
00269  }
00270  frame++;
00271  subframe=0;   // Sub frames are used when rendering motion blur
00272  NEXTSUBFRAME:
00273  subframe++;
00274  if(frame < firstframe){ // Skip frames if not starting from the first 
00275    char c,tt[256];
00276    int ic=0;
00277    LOOP:
00278    ic=0;
00279    LOOP2:
00280    if((c=getc(CF)) == EOF)goto EXITPOINT; 
00281    if(c != '\n'){
00282      tt[ic++]=c;
00283      goto LOOP2;
00284    }
00285    tt[ic]=0;
00286   if(tt[0] != 'f')goto LOOP;
00287    wave_phase += 0.1;          /* move onto next wave phase */
00288    if(wave_phase > 1.99999)wave_phase = 0.0;
00289    goto NEXTFRAME;
00290  }
00291  if(!renderer_silent)UpdateNTFrame(frame,command_id);
00292  if(frame > lastframe){ End_of_animation=1; goto EXITPOINT;}
00293  sprintf(temp_message,"%ld",frame);
00294  Render_Message(42,0,temp_message);
00295  RenderCurrentFrame=frame;
00296  R_Nground=0; 
00297  if(!bKeepObjectsInRAM){
00298    ObjectCount=0; Object=NULL; Nshader=0; Shader=NULL;
00299  }
00300  FirstObject=ObjectCount; 
00301  Nlights=0; Lights=NULL; nImageProcesses=0; ImageProcesses=NULL;
00302  Nparticles=0; ParticleS=NULL;
00303  VGA_screen=NULL; Nsky=0;
00304  // This is the main animation frame rendering start /////////////
00305  if((command_id=GetCommand(firstframe,frame,nAnimStart,argv[2])) < 0)goto EXITPOINT;
00306  //if(debug != NULL){
00307  // fprintf(debug,"Frame %ld with %ld Objects in Scene\n",frame,ObjectCount);
00308  // if(ObjectCount > 0)for(i=0;i<ObjectCount;i++)
00309  //  fprintf(debug,"O %ld in use=%ld\n",i,Object[i].in_use);
00310  //}
00311  Render_Message(44,0,NULL);
00312  Xcentre=(XMAX+XMIN)/2;
00313  Ycentre=(YMAX+YMIN)/2;
00314  SetPerspectiveView((int)StereoFrame); /* build view transformation TRR */
00315  if(TransformSceneForRendering(&failure,frame,firstframe) == FAIL)goto FREEPOINT;
00316  // Now render the scene using either the GPU or Software
00317  if(bRenderOpenGL){ // GPU
00318    RenderGL(frame,(ApplyPPtoGL == YES ? FALSE : TRUE)); // don't PostPprocess(PP) if using SW PP
00319    InvalidateRect(hWndOpenGL,NULL,FALSE);
00320    if(R_terminator() == FAIL)failure=FAIL;
00321    if(FullScreenBuffer != NULL)CopyGLtoFSB();
00322    if(fszBuffer != NULL)CopyGLtoZbuffer(); // Only if enabled 
00323    if(ApplyPPtoGL == YES && failure != FAIL)ExternalImageProcess(frame,1);
00324  }
00325  else{ // Software Renderer
00326    if(RenderHide() == FAIL)failure=FAIL;
00327    if(failure != FAIL && Nparticles > 0 && ParticleS != NULL && 
00328       FullScreenBuffer != NULL && fszBuffer != NULL)RenderParticles();
00329    if(failure != FAIL && nImageProcesses > 0)
00330      failure=ExternalImageProcess(frame,0);
00331    if(failure != FAIL && FullScreenBuffer != NULL && MotionBlurBuffer != NULL)
00332      failure=MotionBlurFrame(frame,subframe,command_id);
00333  }
00334  if(failure != FAIL && instant_callback == YES && FullScreenBuffer != NULL)
00335    AddToRenderImagePreview(0,
00336                            ResolutionX,ResolutionY,
00337                            FullScreenBuffer,NULL,NULL,NULL);
00338  /* if integrating for Motion blur or field rendering don't write yet   */
00339  if(command_id == 1)goto FREEPOINT;
00340  /* if output file type is 24 bit or 16 bit TARGA then do it now         */
00341  /* else if full screen buffer and 8 bit create the compressed truncated */
00342  /* temporary file. If full screen buffer buffer not used, this will     */
00343  /* already have been done (outputfile is temporary arrary)              */
00344  strcpy(outputroot,argv[2]);
00345  if(StereoRenderingON){
00346    if(StereoFrame && FullScreenBuffer != NULL){ // left frame 
00347      if((stereo_buffer=(fullscreenbuffer *)X__Malloc(ResolutionX*ResolutionY*2*(long)sizeof(fullscreenbuffer))) != NULL){
00348        memcpy(stereo_buffer,FullScreenBuffer,sizeof(fullscreenbuffer)*ResolutionX*ResolutionY);
00349      }
00350    }
00351    else if(stereo_buffer != NULL){ // right frame
00352      memcpy((stereo_buffer+ResolutionX*ResolutionY),FullScreenBuffer,sizeof(fullscreenbuffer)*ResolutionX*ResolutionY);
00353      if(OUTPUT_FILE_TYPE == AVI_FILE && failure != FAIL){
00354        failure=ScreenTo32bitFile(frame,outputfile,outputroot,stereo_buffer); 
00355      } 
00356      else {
00357        OneExternalFrame(frame,(char *)stereo_buffer,outputroot,JPS_FILE,jpeg_quality); 
00358      }
00359      free(stereo_buffer); stereo_buffer=NULL;
00360    }
00361    StereoFrame ^= 1;
00362  }
00363  else if(OUTPUT_FILE_TYPE == TIF_FILE && failure != FAIL)
00364    OneExternalFrame(frame,NULL,outputroot,TIF_FILE,100);
00365  else if(OUTPUT_FILE_TYPE == B24_FILE && failure != FAIL)
00366    OneExternalFrame(frame,NULL,outputroot,B24_FILE,100);
00367  else if(OUTPUT_FILE_TYPE == J24_FILE && failure != FAIL)
00368    OneExternalFrame(frame,NULL,outputroot,J24_FILE,jpeg_quality);
00369  else if(OUTPUT_FILE_TYPE == PNG_FILE && failure != FAIL)
00370    OneExternalFrame(frame,NULL,outputroot,PNG_FILE,100);
00371  else if(OUTPUT_FILE_TYPE == AVI_FILE && failure != FAIL && FullScreenBuffer != NULL)
00372    failure=ScreenTo32bitFile(frame,outputfile,outputroot,NULL);
00373  FREEPOINT:
00374  Free_Mirror_On_Ground();
00375  Free_Lights_Shadows();
00376  FreeFrameObjects();
00377  if(!bKeepObjectsInRAM)FreeAllObjects();
00378  if(Lights != NULL){X__Free(Lights); Lights = NULL;}
00379  if(ParticleS != NULL){
00380    for(i=0;i<Nparticles;i++){
00381      if((ParticleS+i)->particles != NULL)X__Free((ParticleS+i)->particles);
00382    }
00383    X__Free(ParticleS); ParticleS = NULL; Nparticles=0;
00384  }
00385  if(nImageProcesses > 0 && ImageProcesses != NULL){
00386    for(i=0;i<nImageProcesses;i++){
00387      if(ImageProcesses[i].parameters != NULL)
00388        X__Free(ImageProcesses[i].parameters);
00389      if(ImageProcesses[i].mparameters != NULL)
00390        X__Free(ImageProcesses[i].mparameters);
00391    }
00392    X__Free(ImageProcesses);
00393    ImageProcesses=NULL;
00394    nImageProcesses=0;
00395  }
00396  if(VGA_screen != NULL){
00397    X__Free(VGA_screen);
00398    VGA_screen=NULL;
00399  }
00400 #ifdef TRACER
00401  if(trace_reflections || trace_refractions || trace_shadows)freeBST();
00402 #endif
00403  //if(debug != NULL)fprintf(debug,"End of FRAME !!!\n");
00404  if(failure == FAIL){
00405    remove(outputfile);
00406    goto EXITPOINT;
00407  }
00408  if(command_id == 1){
00409    goto NEXTSUBFRAME;
00410  }
00411  wave_phase += 0.1;          /* move onto next wave phase */
00412  if(wave_phase > 1.99999)wave_phase = 0.0;
00413  flash_count++; if(flash_count > 5){flash_count=0; flashing ^= 1;}
00414  goto NEXTFRAME;
00415  EXITPOINT:
00416  if(bKeepObjectsInRAM)FreeAllObjects();
00417  FreeTextureHashTable();
00418  if(End_of_animation && failure != FAIL){
00419    // if making gif image (or sequence of GIF images) do it here
00420    // this uses the 16 bit temporary file so that all gif images have same palette.
00421    Render_Message(38,0,NULL);
00422    // 
00423    Render_Message(39,0,NULL);
00424  }
00425  else{
00426   WindowedRenderMessage(WRM_COMPLETE);
00427   Render_Message(43,0,NULL);
00428  }
00429  FreeRamBuffers();
00430  free_render_discarded_list();
00431  ReleaseImageStore();
00432  if(CF != NULL)fclose(CF);
00433  return (int)failure;
00434 }
00435 
00447 static int TransformSceneForRendering(long *failure,long frame, long firstframe){
00448  long i,tFaces=0,tVertices=0;
00449  double light_transformation[4][4],trset[4][4],trinv[4][4];
00450  vector Zero_Vector;
00451  Zero_Vector[0]=Zero_Vector[1]=Zero_Vector[2]=0.0;
00452  if(Nlights > 0)for(i=0;i<Nlights;i++){
00453    Lights[i].shadow_buffer=NULL;
00454    Lights[i].object_buffer=NULL;
00455    Lights[i].face_buffer=NULL;
00456    Lights[i].atmospheric_shadow_buffer=NULL;
00457    if(Lights[i].type == SPOTLIGHT){
00458      MakeObjectTransformation(Lights[i].dPhi,0.0,Lights[i].dAlpha,
00459               Lights[i].internal_type,Lights[i].internal_size,
00460               1.0,1.0,1.0,
00461               Zero_Vector,Lights[i].pin,
00462               light_transformation,trset,trinv);
00463      ApplyViewingTransformToPoint(Lights[i].pin,Lights[i].p);
00464      R_m4by1(light_transformation,
00465              0.0,(double)UNIT,0.0,
00466              &Lights[i].d[0],&Lights[i].d[1],&Lights[i].d[2]);
00467      vecsub(Lights[i].p,Lights[i].d,Lights[i].d);  //d is opposite to light dir
00468      normalize(Lights[i].d);
00469      Lights[i].cone2 = min(89.9,Lights[i].cone1/2+Lights[i].falloff);
00470      Lights[i].cone2 *= PI/180.0;   /* cone + edge */
00471      Lights[i].cone1 *= PI/360.0;   /* half viewing cone angle */
00472      Lights[i].dot1 = cos(Lights[i].cone1);  /* for dot product */
00473      Lights[i].dot2 = cos(Lights[i].cone2);
00474      Lights[i].falloff = 1.0/(Lights[i].dot1-Lights[i].dot2);
00475    }
00476    else ApplyViewingTransformToPoint(Lights[i].pin,Lights[i].p);
00477    Lights[i].Ire = ((double)Lights[i].color[0])/255.0;
00478    Lights[i].Igr = ((double)Lights[i].color[1])/255.0;
00479    Lights[i].Ibl = ((double)Lights[i].color[2])/255.0;
00480  }
00481  else{
00482    if((Lights=(light *)X__Malloc(sizeof(light))) == NULL){
00483      *failure=FAIL; return FAIL;
00484    }
00485    Render_Message(50,0,NULL);
00486    Nlights=1;   /* camera is at origin after transform */
00487    Lights[0].color[0]=Lights[0].color[1]=Lights[0].color[2]=255;
00488    Lights[0].type=NORMAL;
00489    Lights[0].shadow_buffer=NULL;
00490    Lights[0].atmospheric_shadow_buffer=NULL;
00491    Lights[0].AnimatorID=0;
00492    Lights[0].object_buffer=NULL;
00493    Lights[0].face_buffer=NULL;
00494    Lights[0].p[0] = 0.0; Lights[0].p[1] = -0.0; Lights[0].p[2] = 0.0;
00495    Lights[0].d[0] = 0.0; Lights[0].d[1] = -1.0; Lights[0].p[2] = 0.0;
00496    Lights[0].Ire = 1.0;
00497    Lights[0].Igr = 1.0;
00498    Lights[0].Ibl = 1.0;
00499    Lights[0].dc=FALSE;
00500    Lights[0].dc_c=1.0;
00501    Lights[0].dc_l=0.0;
00502    Lights[0].dc_q=0.0;
00503  }
00504  if(R_Nground > 0){
00505   ApplyViewingTransformToPoint(Ground.pin,Ground.p);
00506   ApplyViewingTransformToPoint(Ground.xin,Ground.x);
00507   ApplyViewingTransformToPoint(Ground.yin,Ground.y);
00508   vecsub(Ground.x,Ground.p,Ground.dx);
00509   vecsub(Ground.y,Ground.p,Ground.dy);
00510   cross(Ground.dx,Ground.dy,Ground.n);
00511   normalize(Ground.n);
00512   Ground.lengthx=R_length(Ground.dx);
00513   Ground.lengthy=R_length(Ground.dy);
00514   Ground.bump=1.0/max(1.0,Ground.lengthx);
00515   Ground.range=Ground.lengthy/Ground.lengthx/2.0;
00516   Ground.range *= Ground.range;
00517   if(ambient_flag == 0)Ground.ambient_light=ground_ambient_light;
00518   veccopy(Ground.dy,Ground.dyy);
00519   normalize(Ground.dyy);
00520   vecscale(Ground.lengthx,Ground.dyy,Ground.dyy);
00521   if(Ground.texture > 0 && Ground.texture < 4)Ground.shiny = 1;
00522   else                                        Ground.shiny = 0;
00523   if(frame == firstframe)init_ripples();
00524   if(Ground.mapped){
00525     ApplyViewingTransformToPoint(Ground.map.pin,Ground.map.p);
00526     ApplyViewingTransformToPoint(Ground.map.xin,Ground.map.x);
00527     ApplyViewingTransformToPoint(Ground.map.yin,Ground.map.y);
00528     vecsub(Ground.map.x,Ground.map.p,Ground.map.x);
00529     vecsub(Ground.map.y,Ground.map.p,Ground.map.y);
00530     cross (Ground.map.x,Ground.map.y,Ground.map.n);
00531     normalize(Ground.map.n);
00532   }
00533  }
00534  if(Nparticles > 0 && ParticleS != NULL){  // Transform the particle system & build the particles ready to go 
00535    for(i=0;i<Nparticles;i++){  // number of particle systems
00536      long np=ParticleS[i].Rate;
00537      ParticleSystem *Ps;
00538      Ps=&(ParticleS[i]);
00539      Ps->particles=NULL;
00540      if(np > 0){
00541        Ps->particles=(Particle *)X__Malloc(np*sizeof(Particle));
00542        if(Ps->particles != NULL){
00543          if(Ps->bSingle)SetUpSingleParticle(Ps); // set up a particle system that only needs a single particle
00544          else           SetUpParticles(Ps);   
00545        }
00546      } 
00547    }
00548  }
00549 
00550  if(ambient_flag == 0)ambient_light=object_ambient_light;
00551  if(Sky.type == SKYMAPPED){  /* set up cylindrical map  for use of skymapped texture */
00552    if(Sky.mapped){           /* used when doing a ray-tracing                        */
00553      ApplyViewingTransformToPoint(Sky.map.pin,Sky.map.p);
00554      ApplyViewingTransformToPoint(Sky.map.xin,Sky.map.x);
00555      ApplyViewingTransformToPoint(Sky.map.yin,Sky.map.y);
00556      vecsub(Sky.map.x,Sky.map.p,Sky.map.x);
00557      vecsub(Sky.map.y,Sky.map.p,Sky.map.y);
00558      cross (Sky.map.x,Sky.map.y,Sky.map.n);
00559      normalize(Sky.map.n);
00560    }
00561  }
00562  if(ObjectCount > 0)for(i=0;i<ObjectCount;i++){
00563    if(!Object[i].in_use || Object[i].NoVertices == 0 
00564                         || Object[i].NoFaces == 0)continue;
00565    tVertices += Object[i].NoVertices;
00566    tFaces    += Object[i].NoFaces;
00567    Object[i].ambient_light=ambient_light;
00568    if(TransformObjectIntoPosition(i) == FAIL){
00569      *failure=FAIL;
00570      return FAIL;
00571    }
00572  }
00573  if(!bRenderOpenGL){ // Only for software renderer
00574    for(i=0;i<Nlights;i++)if(Lights[i].type == SPOTLIGHT){
00575      SetLightShadow(i);
00576    }
00577  }
00578  else trace_reflections = trace_refractions = trace_shadows = 0; // NOT for H/W renderer
00579 
00580  // Calculate vertex normals - for each vertex in the faces - moved from the RenderHide function!!!
00581  Render_Message(57,0,NULL);
00582  MakeVertexNormals();
00583  // // end of move
00584  if(trace_reflections || trace_refractions || trace_shadows){
00585    if(buildBST() == FAIL){ Render_Message(45,0,NULL);  *failure=FAIL;  return FAIL; }
00586    // need to re-calcalculate this since objects now split
00587    if(ObjectCount > 0)for(i=0;i<ObjectCount;i++)CalculateObjectScreenCoordinates(i);
00588  }
00589  if(!(trace_reflections || trace_refractions || trace_shadows)){
00590    char tstr[256],text_string[256];
00591    LoadString(hThisInstance,IDX_MISC_STATUS1,
00592               text_string,sizeof(text_string));
00593    sprintf(tstr,text_string,
00594            tFaces,tVertices,ObjectCount);
00595    WindowedRenderInfo(tstr);
00596  }
00597  return OK;
00598 }
00599 
00614 static short TransformObjectIntoPosition(long O){
00615    long i,j;
00616    double temp4,xx,yy,theta_max,
00617           trset[4][4];  // object transform - everything but WITHOUT the view.
00618    vertex   *v;
00619    face     *f;
00620    Object[O].xmin = BIGP;   Object[O].xmax = BIGN;
00621    Object[O].ymin = BIGP;   Object[O].ymax = BIGN;
00622    MakeObjectTransformation(
00623            Object[O].fi,Object[O].theta,Object[O].alpha,
00624            Object[O].im,Object[O].ima,
00625            Object[O].sx,Object[O].sy,Object[O].sz,
00626            Object[O].Centre,Object[O].Offset,
00627            Object[O].trpos,trset,
00628            Object[O].trinv);
00629    if((j=Object[O].NoMaps) > 0){
00630      imap *Map;
00631      for(i=0;i<j;i++){
00632        Map=(Object[O].Mbase+i);
00633        TransformMappingRectangle(Object[O].trpos,
00634                Map->pin,Map->xin,Map->yin,
00635                Map->p,Map->x,Map->y,
00636                Map->n);
00637        if(Map->bp >= 0){ // Bump map is applied
00638          theta_max=80 * 0.017453; theta_max=tan(theta_max); /*  max angle of bend in surface normal */
00639          Map->bumpy = max(1.0,R_length(Map->y));
00640          Map->bumpy = -((double)Map->bp)*0.01*theta_max
00641                           /Map->bumpy/256;
00642          if(Map->map == CYLINDER ||
00643             Map->map == MAP_SPHERICAL ||
00644             Map->map == CYLINDER_MOZIAC)
00645                Map->bumpx = 1.0;
00646          else  Map->bumpx = max(1.0,R_length(Map->x));
00647          Map->bumpx = -((double)Map->bp)*0.01*theta_max
00648                           /Map->bumpx/256;
00649        }
00650        Map->pd=((double)Map->pp)*0.01;   // surface percentage 
00651        if(Map->rp >= 0)Map->rd=((double)Map->rp)*0.01;   // reflection percentage
00652        else Map->rd=0.0;
00653      }
00654    }
00655    // Allow for the transform of the objects material axes - only used by hardware renderer
00656    if((j=Object[O].NoMats) > 0){
00657      matl *Mat;
00658      for(i=0;i<j;i++){
00659        Mat=(Object[O].Tbase+i);
00660        TransformMappingRectangle(Object[O].trpos,
00661              Mat->ax.boin,
00662              Mat->ax.buin,
00663              Mat->ax.bvin,
00664              Mat->ax.bo, /* material axes */
00665              Mat->ax.bu,
00666              Mat->ax.bv,
00667              Mat->ax.bn);
00668        Mat->ax.tl=max(1.0,R_length(Mat->ax.bu));
00669        Mat->ax.tv=max(1.0,R_length(Mat->ax.bv));
00670        vecscale(1.0/Mat->ax.tl,Mat->ax.bu,Mat->ax.bu_norm);
00671        vecscale(1.0/Mat->ax.tv,Mat->ax.bv,Mat->ax.bv_norm);
00672      }
00673    }
00675    TransformMappingRectangle(Object[O].trpos,
00676              Object[O].Abase.boin,
00677              Object[O].Abase.buin,
00678              Object[O].Abase.bvin,
00679              Object[O].Abase.bo, /* shader axes */
00680              Object[O].Abase.bu,
00681              Object[O].Abase.bv,
00682              Object[O].Abase.bn);
00683    Object[O].Abase.tl=max(1.0,R_length(Object[O].Abase.bu));
00684    Object[O].Abase.tv=max(1.0,R_length(Object[O].Abase.bv));
00685    vecscale(1.0/Object[O].Abase.tl,
00686             Object[O].Abase.bu,Object[O].Abase.bu_norm);
00687    vecscale(1.0/Object[O].Abase.tv,
00688             Object[O].Abase.bv,Object[O].Abase.bv_norm);
00689    // Transform the vertices into position
00690    v=Object[O].Vbase;
00691    Object[O].visibility=NO;
00692    if(Object[O].effect >= 0){
00693      EffectObjectVertices(0,O); /* locally  */
00694      for(i=0;i<Object[O].NoVertices;i++){
00695        R_m4by1(trset, (v+i)->p[0], (v+i)->p[1], (v+i)->p[2]
00696                     ,&(v+i)->p[0],&(v+i)->p[1],&(v+i)->p[2]);
00697      }
00698      EffectObjectVertices(1,O); /* globally */
00699      for(i=0;i<Object[O].NoVertices;i++){
00700        R_m4by1(ViewTransform,(v+i)->p[0], (v+i)->p[1], (v+i)->p[2]
00701                   ,&(v+i)->p[0],&(v+i)->p[1],&(v+i)->p[2]);
00702        if((v+i)->p[1] > 1.000)Object[O].visibility=YES;
00703      }
00704    }
00705    else{
00706      for(i=0;i<Object[O].NoVertices;i++){
00707        R_m4by1(Object[O].trpos, (v+i)->p[0], (v+i)->p[1], (v+i)->p[2]
00708                             ,&(v+i)->p[0],&(v+i)->p[1],&(v+i)->p[2]);
00709        if((v+i)->p[1] > 1.000)Object[O].visibility=YES;
00710      }
00711    }
00712 
00713    if(Object[O].visibility == YES){
00714      if(ClipObject(O) == FAIL)return FAIL;
00715    }
00716    v=Object[O].Vbase;
00717    CalculateObjectScreenCoordinates(O);
00718    return OK;
00719 }
00720 
00721 static CalculateObjectScreenCoordinates(long O){
00722  long i,j;
00723  double temp4,xx,yy;
00724   vertex   *v;
00725   face     *f;
00726   v=Object[O].Vbase;
00727   for(i=0;i<Object[O].NoVertices;i++){
00728     (v+i)->ip[0] = (long)(v+i)->p[0]; // assign integer coopy
00729     (v+i)->ip[1] = (long)(v+i)->p[1];
00730     (v+i)->ip[2] = (long)(v+i)->p[2];
00731     (v+i)->p[0] = (double)(v+i)->ip[0]; // make sure final points are also integers 
00732     (v+i)->p[1] = (double)(v+i)->ip[1];
00733     (v+i)->p[2] = (double)(v+i)->ip[2];
00734     if((v+i)->p[1] >= FRONT_CLIPPING_PLANE){  /* point on or in front of view plane */
00735      temp4=(scalex*((v+i)->p[0])/((v+i)->p[1]));
00736      xx=(double)Xcentre + temp4;
00737      (Object[O].Vbase+i)->x=xx;
00738      temp4=(scaley*((v+i)->p[2])/((v+i)->p[1]));
00739      yy=(double)Ycentre - temp4;
00740      (Object[O].Vbase+i)->y=yy;
00741     }
00742     else{ /* just dummy it any face with this node will not be used */
00743      (Object[O].Vbase+i)->x=xx=(double)Xcentre;  /* will be scrapped later */
00744      (Object[O].Vbase+i)->y=yy=(double)Ycentre;
00745     }
00746     if(xx < 0)xx = -1; if(xx > XMAX) xx = XMAX+1; // don't let bounds get outside screen
00747     if(yy < 0)yy = -1; if(yy > YMAX) yy = YMAX+1;
00748     if(xx < Object[O].xmin) Object[O].xmin = xx;
00749     if(xx > Object[O].xmax) Object[O].xmax = xx;
00750     if(yy < Object[O].ymin) Object[O].ymin = yy;
00751     if(yy > Object[O].ymax) Object[O].ymax = yy;
00752    }
00753    v=Object[O].Vbase;     /* NB the object may be invisible but its */
00754    f=Object[O].Fbase;     /* shadow/reflection may be !!            */
00755    CalculateFaceNormals(v,f,O);
00756 
00757 }
00758 
00759 static int PsameSide(vector v, vector p0, vector n){
00760   vector pv;                            /* after reflection - remove faces  */
00761   VECSUB(p0,v,pv)                       /* if all vertices are on same side */
00762   if(DOT(pv,n)*DOT(p0,n) > 0)return 1;  /* as (0,0,0) - put off screen      */
00763   return 0;
00764 }
00765 
00766 static void CalculateFaceNormals(vertex *v, face *f, long O){
00767  long i,badflag;
00768  double c,ftop,fbottom,fleft,fright;
00769  vector p1,p2,p0;
00770  for(i=0;i<Object[O].NoFaces;i++){
00771     p0[0]=(v+f->V[0])->p[0];
00772     p0[1]=(v+f->V[0])->p[1];
00773     p0[2]=(v+f->V[0])->p[2];
00774     p1[0]=(v+f->V[1])->p[0];
00775     p1[1]=(v+f->V[1])->p[1];
00776     p1[2]=(v+f->V[1])->p[2];
00777     p2[0]=(v+f->V[2])->p[0];
00778     p2[1]=(v+f->V[2])->p[1];
00779     p2[2]=(v+f->V[2])->p[2];
00780     vecsub(p2,p0,p2);
00781     vecsub(p1,p0,p1);
00782     cross(p1,p2,f->n);
00783     if(normalize(f->n) == 1)badflag=1; else badflag=0;
00784     c=dot(p0,f->n);
00785     f->c=(double)c;
00786 //    if(c > 0.0){ /* all normals point to camera */  // Removed - seems not necessary
00787 //      vecscale((double)(-1.0),f->n,f->n);
00788 //      f->c=(double)c*(-1.0);
00789 //    }
00790     /* get face screen limits */
00791     ftop=min((v+(f->V[0]))->y,(v+(f->V[1]))->y);
00792     ftop=min((v+(f->V[2]))->y,ftop);
00793     fbottom=max((v+(f->V[0]))->y,(v+(f->V[1]))->y);
00794     fbottom=max((v+(f->V[2]))->y,fbottom)+1;
00795     fleft=min((v+(f->V[0]))->x,(v+(f->V[1]))->x);
00796     fleft=min((v+(f->V[2]))->x,fleft);
00797     fright=max((v+(f->V[0]))->x,(v+(f->V[1]))->x);
00798     fright=max((v+(f->V[2]))->x,fright)+1;
00799     if(ftop < 0.0)f->top= -1;
00800     else if(ftop > YMAX)f->top=YMAX+1;
00801     else f->top=(short)ftop;
00802     if(fbottom < 0.0)f->bottom= -1;
00803     else if(fbottom > YMAX)f->bottom=YMAX+1;
00804     else f->bottom=(short)fbottom;
00805     if(fleft < 0.0)f->left= -1;
00806     else if(fleft > XMAX)f->left=XMAX+1;
00807     else f->left=(short)fleft;
00808     if(fright < 0.0)f->right= -1;
00809     else if(fright > XMAX)f->right=XMAX+1;
00810     else f->right=(short)fright;
00811 /* eliminate faces with all vertices behind clipping plane,
00812    faces that span the clipping plane have been cliped in ClipObject,
00813    by setting the face top value to  > YMAX this face will then
00814    fail the first test in Active.  Also eliminate faces to left
00815    or right of screen by using the same trick */
00816     if( ( v[ f->V[0] ].p[1] <= FRONT_CLIPPING_PLANE)  /* nodes in face are either behind */
00817      && ( v[ f->V[1] ].p[1] <= FRONT_CLIPPING_PLANE)  /* or on viewing plane */
00818      && ( v[ f->V[2] ].p[1] <= FRONT_CLIPPING_PLANE)){
00819        f->top=YMAX+1;
00820     }
00821     if(f->left >= XMAX)      f->top=YMAX+1;
00822     if(f->right < XMIN)      f->top=YMAX+1;
00823 /* eliminate faces that are perpendicular to the viewing plane */
00824     if(fabs(f->c) < 1.e-4)   f->top=YMAX+1;
00825 /* and faces with bad normals this put in for DEC aXP and may be wrong */
00826     if(badflag == 1){
00827       f->top=YMAX+1; f->n[0]=f->n[1]=f->n[2]=1.0;
00828     }
00829     f++;
00830  }
00831 }
00832 
00833 /*  Do the scan line rendering here */
00834 
00835 /* Functions to build the phong smoothing vectors and do the scanline */
00836 /* algorithm. The geometry calculations are doen in file   GEO.C      */
00837 /* and the surface properties are calculated in TEXTURE.C + TEXTUR1.C */
00838 /* Also inclued the "CORE" of the scanline algorithm                  */
00839 
00840 typedef struct PHONG1_tag { 
00841   int fid,vid;
00842 } PHONG1;
00843 
00844 typedef struct PHONG_tag { 
00845   int n;
00846   PHONG1 fv[8];   /* 10 seems to be too big */
00847 } phong;
00848 
00849 void MakeVertexNormals(void){   /* This is a horrible thing that asembles */
00850                                 /* the PHONG vectors 3 for each FACE      */
00851  vertex   *v;                   /* umpteen different procedures have been */
00852  face     *f;                   /* tried - this gives the best results    */
00853                                 /* the diff. only occurs when faces are   */
00854                                 /* perpend.r to the line of sight.        */
00855  long i,j,k,O,vi,ni,fj,vj,fk;   /* All other faces are turned to face the */
00856  double c;                      /* camera there is no problem there.       */
00857  vector nn;                     /* TRY AND BUILD MODELS WITH CONSISTENT NORMALS INSTEAD */     
00858  phong *ph;
00859  for(O=0; O<ObjectCount; O++){
00860    if(!Object[O].in_use || Object[O].NoVertices == 0 || Object[O].NoFaces == 0)continue;
00861    v=Object[O].Vbase;
00862    f=Object[O].Fbase;
00863  
00864    for(i=0;i<Object[O].NoFaces;i++){
00865      for(j=0;j<3;j++)VECCOPY(f[i].n,f[i].pn[j]);
00866    }
00867    if((ph = (phong *)X__Malloc(Object[O].NoVertices*sizeof(phong))) == NULL){
00868      Render_Message(11,0,NULL);
00869      return;
00870    }
00871    for(i=0;i<Object[O].NoVertices;i++){
00872      ph[i].n=0;
00873    }
00874    for(i=0;i<Object[O].NoFaces;i++){
00875      if(1){ /* need to smooth all faces because a material will need this */
00876        for(j=0;j<3;j++){  /* make list of faces adjacent to vertex */
00877          vi=f[i].V[j];
00878          ni=ph[vi].n;
00879          if(ni < 8){ /* for windows just use ? (10 too big) so no reallocation needed */
00880            ph[vi].fv[ni].fid=i;
00881            ph[vi].fv[ni].vid=j;
00882            ph[vi].n++;
00883          }
00884        }
00885      }
00886    }  /* now we have a list of faces adjacent to each vertex */
00887    {   
00888      for(i=0;i<Object[O].NoVertices;i++){
00889        if((ni=ph[i].n) > 0){
00890          for(j=0;j<ni;j++){
00891            fj=ph[i].fv[j].fid; vj=ph[i].fv[j].vid;
00892            for(k=0;k<ni;k++)if(k != j){
00893              fk=ph[i].fv[k].fid;
00894              if((c=dot(f[fj].n,f[fk].n)) > smoothing_angle /*0.01*/){ /* keep same */
00895                vecsum(f[fj].pn[vj],f[fk].n,f[fj].pn[vj]);
00896              }
00897              else if(c < -smoothing_angle /*-0.01*/){  /* invert before adding */
00898                nn[0] = -f[fk].n[0]; nn[1] = -f[fk].n[1]; nn[2] = -f[fk].n[2];
00899                vecsum(f[fj].pn[vj],nn,f[fj].pn[vj]);
00900              }
00901            }
00902          }
00903        }
00904      }
00905    }
00906    for(i=0;i<Object[O].NoFaces;i++){ /* normalize vertex vectors */
00907      for(j=0;j<3;j++)normalize(f[i].pn[j]);
00908    }
00909    X__Free(ph);
00910  }
00911 }
00912 
00913 typedef struct THSTART_tag{ 
00914  int start,skip;
00915  HANDLE h;
00916 } THSTART;
00917 
00918 static BOOL all_terminate_flag=FALSE; 
00919 static long last_update=0;
00920 
00933 void RenderMultiThreaded(void *arg){
00934  long i,j,k,l,m,Wsky;
00935  double d2,xl,xr,Rsky=0.0;
00936  vertex *v;
00937  face   *f;
00938  THD    thd,*p;
00939  THSTART *s=(THSTART *)arg;
00940  //{char temp[255]; sprintf(temp,"Normal Thread %ld -> %ld",s->start,s->skip);
00941  //MessageBox(NULL,temp,"Thread",MB_OK);}
00942  SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL);
00943  p=&thd; if(!AllocateThreadStorage(p))goto THDERROR;
00944  //MessageBeep(MB_OK);
00945  for(l=s->start*aaYstep;l<YMAX;l+=(aaYstep*(s->skip))){
00946    for(i=0;i<XMAX;i++){p->Xbuffer[i] = -1; p->Xobject[i] = -4;}
00947    for(m=0;m<aaYstep;m++){
00948      k=l+m;
00949      d2=(double)(Ycentre-k);
00950      d2/=scaley;
00951      Wsky=PutBackIntersection(k,d2,p->Alfa,p->Zground,
00952                               p->Zglass,p->ZglassO,p->Zglassd,
00953                               p->Zbuffer,p->Zobject,p->Zdepth,p->Zposn,
00954                               &Rsky);
00955      for(i=0;i<ObjectCount;i++){
00956        if(!Object[i].in_use)continue;
00957        if((k > Object[i].ymin) && (k < Object[i].ymax) && !Object[i].wireframe
00958                &&(Object[i].visibility == YES)){
00959         v=Object[i].Vbase;
00960         f=Object[i].Fbase;
00961         for(j=0;j<Object[i].NoFaces;j++)
00962          if( Active(k,v,f+j,&xl,&xr) ){
00963            UpdateScanBuffers(xl,xr,j,i,f+j,d2,
00964                            p->Zglass,p->ZglassO,p->Zglassd,
00965                            p->Zbuffer,p->Zobject,p->Zdepth,p->Zposn);
00966          }
00967        }
00968      }
00969      if(ShadedScanline(
00970                     k,d2,p->Red,p->Green,p->Blue,
00971                     p->Zground,Wsky,Rsky,
00972                     p->Zglass,p->ZglassO,p->Zglassd,
00973                     p->Zbuffer,p->Zobject,p->Zdepth,p->Zposn) == FAIL){
00974        goto THDERROR;
00975      }
00976      if(alfachannelON == YES)FillAlfaLine(p->Alfa,p->ZglassO,p->Zobject);
00977      if(AntiAliasLine(k,anti_alias,
00978                       p->Red,p->Green,p->Blue,p->Alfa,
00979                       p->L_Red,p->L_Green,p->L_Blue,p->L_Alfa,
00980                       p->LL_Red,p->LL_Green,p->LL_Blue,p->LL_Alfa) == FAIL){
00981        Render_Message(0,0,NULL);
00982        goto THDERROR;
00983      }
00984      if(fszBuffer != NULL)ScanlineToZbuffer(k,p->Zdepth);
00985      if(ObjectIdBuffer != NULL)ScanlineToZobject(k,p->Zobject);
00986      if(!renderer_silent){
00987        long ud;
00988        if     (anti_alias == ULTRA)                        ud=((k+1)/3);
00989        else if(anti_alias == MEDIUM || anti_alias == HIGH )ud=((k+1)/2);
00990        else                                                ud=(k+1);
00991        if(ud > last_update){
00992          last_update=ud;
00993          UpdateNTTrace(ud);
00994        }
00995      }
00996      if(all_terminate_flag)goto THDEND;
00997    }
00998  }
00999  goto THDEND;
01000  THDERROR:
01001  all_terminate_flag=TRUE;
01002  THDEND:
01003  FreeThreadStorage(p);
01004  SetEvent(s->h);
01005  _endthread();
01006  return;
01007 }
01008 
01021 void FastAntiAliasRenderMultiThreaded(void *arg){
01022  long i,j,k,l,m,Wsky;
01023  double d2,xl,xr,Rsky=0.0;
01024  vertex *v;
01025  face   *f;
01026  THD    thd,*p;
01027  THSTART *s=(THSTART *)arg;
01028  SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL);
01029  p=&thd; if(!AllocateThreadStorage(p))goto THDERROR; // allocate local storage for this thread */
01030 //{char temp[255]; sprintf(temp,"Thread %ld -> %ld",s->start,s->skip);
01031 //MessageBox(NULL,temp,"Thread",MB_OK);}
01032 //MessageBeep(MB_OK);
01033  for(l=s->start*aaYstep;l<YMAX;l+=(aaYstep*(s->skip))){
01034    for(i=0;i<XMAX;i++){p->Xbuffer[i] = -1; p->Xobject[i] = -4;}
01035    for(m=0;m<aaYstep;m++){
01036 //Sleep(0);
01037      k=l+m;
01038      d2=(double)(Ycentre-k);
01039      d2/=scaley;
01040      Wsky=PutBackIntersection(k,d2,p->Alfa,p->Zground,
01041                               p->Zglass,p->ZglassO,p->Zglassd,
01042                               p->Zbuffer,p->Zobject,p->Zdepth,p->Zposn,
01043                               &Rsky);
01044      for(i=0;i<ObjectCount;i++){
01045        if(!Object[i].in_use)continue;
01046        if((k > Object[i].ymin) && (k < Object[i].ymax) && !Object[i].wireframe
01047                &&(Object[i].visibility == YES)){
01048         v=Object[i].Vbase;
01049         f=Object[i].Fbase;
01050         for(j=0;j<Object[i].NoFaces;j++)
01051          if( Active(k,v,f+j,&xl,&xr) ){
01052            UpdateScanBuffers(xl,xr,j,i,f+j,d2,
01053                            p->Zglass,p->ZglassO,p->Zglassd,
01054                            p->Zbuffer,p->Zobject,p->Zdepth,p->Zposn);
01055          }
01056        }
01057      }
01058      if(alfachannelON == YES)FillAlfaLine(p->Alfa,p->ZglassO,p->Zobject);
01059      if(FastAntiAliasShadedScanline(
01060                          k,m,d2,p->Red,p->Green,p->Blue,
01061                          p->Zground,Wsky,Rsky,p->Xbuffer,p->Xobject,
01062                          p->Zglass,p->ZglassO,p->Zglassd,
01063                          p->Zbuffer,p->Zobject,p->Zdepth,p->Zposn) == FAIL){
01064        goto THDERROR;
01065      }
01066      if(AntiAliasLine(k,anti_alias,
01067                       p->Red,p->Green,p->Blue,p->Alfa,
01068                       p->L_Red,p->L_Green,p->L_Blue,p->L_Alfa,
01069                       p->LL_Red,p->LL_Green,p->LL_Blue,p->LL_Alfa) == FAIL){
01070        Render_Message(0,0,NULL);
01071        goto THDERROR;
01072      }
01073      if(fszBuffer != NULL)ScanlineToZbuffer(k,p->Zdepth);
01074      if(ObjectIdBuffer != NULL)ScanlineToZobject(k,p->Zobject);
01075      if(!renderer_silent){
01076        long ud;
01077        if     (anti_alias == ULTRA)                        ud=((k+1)/3);
01078        else if(anti_alias == MEDIUM || anti_alias == HIGH )ud=((k+1)/2);
01079        else                                                ud=(k+1);
01080        if(ud > last_update){
01081          last_update=ud;
01082          UpdateNTTrace(ud);
01083        }
01084      }
01085      if(all_terminate_flag)goto THDEND;
01086      for(i=0;i<XMAX;i++){p->Xbuffer[i] = p->Zbuffer[i]; p->Xobject[i] = p->Zobject[i];}
01087    }
01088  }
01089  goto THDEND;
01090  THDERROR:
01091  all_terminate_flag=TRUE;
01092  THDEND:
01093  FreeThreadStorage(p);
01094  SetEvent(s->h);
01095  _endthread();
01096  return;
01097 }
01098 
01111 long RenderHide(void){  /* only get phong shading if each sample diff */
01112  void (*fp)(void *);
01113  long i,iThrd;
01114  HANDLE hThrd[16],hEvent[16]; // render in up to 16 threads/
01115  THSTART Sup[16],*p;
01116  DWORD tID,result,Np;
01117  char str[16];
01118  if(R_terminator() == FAIL)return FAIL;
01119  Render_Message(60,0,NULL);
01120  if(R_Nground > 0){
01121    Render_Message(52,0,NULL);
01122    ShadowGround();
01123  }
01124  if(R_terminator() == FAIL)return FAIL;
01125 // MakeVertexNormals();  // removed
01126  if(R_terminator() == FAIL)return FAIL;
01127  if(R_Nground > 0 && Ground.refl > 0.0){
01128    Render_Message(58,0,NULL);
01129    Mirror_In_Ground();
01130  }
01131  if(Nthreads > 0)Np=Nthreads;
01132  else            Np=min(16,Nprocessors);
01133  sprintf(str,"%ld processors %ld",Nprocessors,Np);
01134  if(in_mirror_phase)Render_Message(99,0,NULL);
01135  else Render_Message(100,0,str);
01136  for(i=XMIN;i<XMAX;i++){
01137    DL[i]=(double)(i - Xcentre);        DL[i]/=scalex;
01138    DR[i]=(double)(i+1-Xcentre);        DR[i]/=scalex;
01139    D1[i]=(double)(i - Xcentre) + 0.5;  D1[i]/=scalex;
01140  }
01141  GetSkyLocation();
01142  all_terminate_flag=FALSE; last_update=0;
01143  //{char temp[255]; sprintf(temp,"Nps=%ld XMAX=%ld YMAX=%ld aaYstep=%ld,aaXstep=%ld",
01144  //Nprocessors,XMAX,YMAX,aaYstep,aaXstep); MessageBox(NULL,temp,"Debug",MB_OK);}
01145  for(i=0;i<Np;i++){
01146    Sup[i].start=i; Sup[i].skip=Np;
01147    hEvent[i]=CreateEvent(NULL,TRUE,FALSE,NULL);
01148    p=&Sup[i]; p->h=hEvent[i];
01149    if(anti_alias_edges == YES && anti_alias > LOW)
01150         fp=FastAntiAliasRenderMultiThreaded;
01151    else fp=RenderMultiThreaded;
01152 //fp=RenderMultiThreaded;
01153 //fp=FastAntiAliasRenderMultiThreaded;
01154 #if  __WATCOMC__ && __WATCOMC__ < 1100
01155   iThrd=_beginthread(fp,0,65536,(void *)p);
01156 #else
01157   iThrd=_beginthread(fp,0,(void *)p);
01158 #endif
01159    if(iThrd == -1){
01160      MessageBox(NULL,"Error Creating Thread",NULL,MB_OK);
01161      return FAIL;
01162    }
01163    hThrd[i]=(HANDLE)iThrd;
01164  }
01165  while(1){
01166    if(!all_terminate_flag && renderer_NT_abort_flag){
01167      for(i=0;i<Np;i++)SuspendThread(hThrd[i]);
01168      if(ConfirmNTabort()){
01169        for(i=0;i<Np;i++)ResumeThread(hThrd[i]);
01170        all_terminate_flag=TRUE;
01171        WaitForMultipleObjects(Np,hEvent,TRUE,INFINITE);
01172        break;
01173      }
01174      else renderer_NT_abort_flag=0;
01175      for(i=0;i<Np;i++)ResumeThread(hThrd[i]);
01176    }
01177    result=WaitForMultipleObjects(Np,hEvent,TRUE,75);
01178    if(result == WAIT_TIMEOUT)RenderYield();
01179    else break;
01180  }
01181  for(i=0;i<Np;i++){
01182    CloseHandle(hEvent[i]);
01183  }
01184  if(all_terminate_flag)return FAIL;
01185  return 0;
01186 }

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