00001
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;
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
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;
00090 ClipXmax=ClipYmax=ClipZmax=UNIT*20;
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){
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;
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
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){;}
00131 else if(strcmp(argv[i],"-zz" ) == 0){
00132 i++;
00133 }
00134 else if(strcmp(argv[i],"-w" ) == 0){
00135 i++;
00136 }
00137 else if(strcmp(argv[i],"-ac" ) == 0){
00138 alfachannelON=YES;
00139 }
00140 else if(strcmp(argv[i],"-acg" ) == 0){
00141 alfagroundON=YES;
00142 }
00143
00144 else if(strcmp(argv[i],"-al" ) == 0){
00145 i++; ambient_light= ((double)atof(argv[i]))/100.0;
00146 ambient_flag=1;
00147 }
00148 else if(strcmp(argv[i],"-sd" ) == 0){
00149 i++; shadow_density = 1.0-((double)atof(argv[i])/100.0);
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);
00154 }
00155 else if(strcmp(argv[i],"-c0" ) == 0){
00156 i++;
00157 if (strcmp(argv[i],"b") == 0){
00158
00159 }
00160 else if(strcmp(argv[i],"w") == 0){
00161
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]);
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]);
00180 }
00181 else if(strcmp(argv[i],"-tot" ) == 0){
00182 i++; trace_face_count_target = atol(argv[i]);
00183 }
00184 else if(strcmp(argv[i],"-tos" ) == 0){
00185 i++; trace_voxel_min_size = atol(argv[i]);
00186 }
00187 #endif
00188 else if(strcmp(argv[i],"-q" ) == 0){
00189 OUTPUT_FILE_TYPE=NUL_FILE;
00190 renderer_silent=1;
00191 }
00192 else if(strcmp(argv[i],"-prv" ) == 0){
00193
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){;}
00205 i++;
00206 }
00207 }
00208 ResolutionX=XMAX; ResolutionY=YMAX;
00209 aaXstep=1; aaYstep=1;
00210
00211
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();
00228 init_structures();
00229 setup_render_discarded_list();
00230 if(AllocateRamBuffers() == FAIL){
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
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'){
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){
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;
00262 NEXTFRAME:
00263 if(StereoRenderingON){
00264
00265
00266
00267 if(StereoFrame)StereoPosition=ftell(CF);
00268 else fseek(CF,StereoPosition,0);
00269 }
00270 frame++;
00271 subframe=0;
00272 NEXTSUBFRAME:
00273 subframe++;
00274 if(frame < firstframe){
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;
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
00305 if((command_id=GetCommand(firstframe,frame,nAnimStart,argv[2])) < 0)goto EXITPOINT;
00306
00307
00308
00309
00310
00311 Render_Message(44,0,NULL);
00312 Xcentre=(XMAX+XMIN)/2;
00313 Ycentre=(YMAX+YMIN)/2;
00314 SetPerspectiveView((int)StereoFrame);
00315 if(TransformSceneForRendering(&failure,frame,firstframe) == FAIL)goto FREEPOINT;
00316
00317 if(bRenderOpenGL){
00318 RenderGL(frame,(ApplyPPtoGL == YES ? FALSE : TRUE));
00319 InvalidateRect(hWndOpenGL,NULL,FALSE);
00320 if(R_terminator() == FAIL)failure=FAIL;
00321 if(FullScreenBuffer != NULL)CopyGLtoFSB();
00322 if(fszBuffer != NULL)CopyGLtoZbuffer();
00323 if(ApplyPPtoGL == YES && failure != FAIL)ExternalImageProcess(frame,1);
00324 }
00325 else{
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
00339 if(command_id == 1)goto FREEPOINT;
00340
00341
00342
00343
00344 strcpy(outputroot,argv[2]);
00345 if(StereoRenderingON){
00346 if(StereoFrame && FullScreenBuffer != NULL){
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){
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
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;
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
00420
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);
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;
00471 Lights[i].cone1 *= PI/360.0;
00472 Lights[i].dot1 = cos(Lights[i].cone1);
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;
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){
00535 for(i=0;i<Nparticles;i++){
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);
00544 else SetUpParticles(Ps);
00545 }
00546 }
00547 }
00548 }
00549
00550 if(ambient_flag == 0)ambient_light=object_ambient_light;
00551 if(Sky.type == SKYMAPPED){
00552 if(Sky.mapped){
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){
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;
00579
00580
00581 Render_Message(57,0,NULL);
00582 MakeVertexNormals();
00583
00584 if(trace_reflections || trace_refractions || trace_shadows){
00585 if(buildBST() == FAIL){ Render_Message(45,0,NULL); *failure=FAIL; return FAIL; }
00586
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];
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){
00638 theta_max=80 * 0.017453; theta_max=tan(theta_max);
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;
00651 if(Map->rp >= 0)Map->rd=((double)Map->rp)*0.01;
00652 else Map->rd=0.0;
00653 }
00654 }
00655
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,
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,
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
00690 v=Object[O].Vbase;
00691 Object[O].visibility=NO;
00692 if(Object[O].effect >= 0){
00693 EffectObjectVertices(0,O);
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);
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];
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];
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){
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{
00743 (Object[O].Vbase+i)->x=xx=(double)Xcentre;
00744 (Object[O].Vbase+i)->y=yy=(double)Ycentre;
00745 }
00746 if(xx < 0)xx = -1; if(xx > XMAX) xx = XMAX+1;
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;
00754 f=Object[O].Fbase;
00755 CalculateFaceNormals(v,f,O);
00756
00757 }
00758
00759 static int PsameSide(vector v, vector p0, vector n){
00760 vector pv;
00761 VECSUB(p0,v,pv)
00762 if(DOT(pv,n)*DOT(p0,n) > 0)return 1;
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
00787
00788
00789
00790
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
00812
00813
00814
00815
00816 if( ( v[ f->V[0] ].p[1] <= FRONT_CLIPPING_PLANE)
00817 && ( v[ f->V[1] ].p[1] <= FRONT_CLIPPING_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
00824 if(fabs(f->c) < 1.e-4) f->top=YMAX+1;
00825
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
00834
00835
00836
00837
00838
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];
00847 } phong;
00848
00849 void MakeVertexNormals(void){
00850
00851 vertex *v;
00852 face *f;
00853
00854
00855 long i,j,k,O,vi,ni,fj,vj,fk;
00856 double c;
00857 vector nn;
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){
00876 for(j=0;j<3;j++){
00877 vi=f[i].V[j];
00878 ni=ph[vi].n;
00879 if(ni < 8){
00880 ph[vi].fv[ni].fid=i;
00881 ph[vi].fv[ni].vid=j;
00882 ph[vi].n++;
00883 }
00884 }
00885 }
00886 }
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 ){
00895 vecsum(f[fj].pn[vj],f[fk].n,f[fj].pn[vj]);
00896 }
00897 else if(c < -smoothing_angle ){
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++){
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
00941
00942 SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL);
00943 p=&thd; if(!AllocateThreadStorage(p))goto THDERROR;
00944
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;
01030
01031
01032
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
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){
01112 void (*fp)(void *);
01113 long i,iThrd;
01114 HANDLE hThrd[16],hEvent[16];
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
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
01144
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
01153
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 }