//$FG,4$You probably want to avoid $FG$//$FG,4$three dimensional graphics because $FG$//$FG,4$support is not very good. There $FG$//$FG,4$is no support for hidden surface $FG$//$FG,4$removal.$FG$ #define MAP_WIDTH 1024 #define MAP_HEIGHT 1024 #define MAP_SCALE 20 #define FORSHORTENING 100 #define CONTROLS_SCALE 0.05 #define COORDINATE_SCALE 256 #define COORDINATE_BITS 8 I2 elevations[MAP_HEIGHT][MAP_WIDTH]; double phi =-45.0*pi/180.0, theta1= 0.0*pi/180.0, theta2= 0.0*pi/180.0, speed = 0.2; I8 x=MAP_WIDTH>>1 *COORDINATE_SCALE*MAP_SCALE, y=MAP_HEIGHT>>1*COORDINATE_SCALE*MAP_SCALE, z=64 *COORDINATE_SCALE*MAP_SCALE; double grid_size=64.0; class MPCtrl { double phi,theta1,theta2,grid_size; I8 x,y,z; BoolU4 update,done; TssStruct *win_tss; }; MPCtrl *mp; void InitMap() { I8 i,j,k1,k2,x,y,xx,yy; MemSet(elevations,0,sizeof(elevations)); for (i=0;i<10000;i++) { x=RandU4%MAP_WIDTH; y=RandU4%MAP_HEIGHT; j=1<<(RandU4%6); for (k1=-j;k1<=j;k1++) for (k2=-j;k2<=j;k2++) { xx=x+k2; yy=y+k1; if (xx>=0 && xx=0 && yywin_pixel_right-tss->win_pixel_left)>>1, cy=(tss->win_pixel_bottom-tss->win_pixel_top)>>1,height; double d; GrBitMap *base=GrAlias(grbase2,tss); I1 buf[128]; BoolU4 first; //Adjust grid size to utilize whole CPU power d=1.05*win_refresh/win_max_refresh; if (d>1.5) d=1.5; if (d<0.666666) d=0.666666; grid_size*=0.975+0.025*d; if (grid_size<10.0) grid_size=10.0; grid_s=grid_size; //Pass stuff to other CPU mp->phi=phi; mp->theta1=theta1; mp->theta2=theta2; mp->x=x; mp->y=y; mp->z=z; mp->update=TRUE; mp->grid_size=grid_size; xx=x/MAP_SCALE/COORDINATE_SCALE; yy=y/MAP_SCALE/COORDINATE_SCALE; height=z/COORDINATE_SCALE-elevations[yy][xx]; if (height<0) Sound(1000); //Signal plane crashed base->color=BLACK; ClearWinText(tss); SPrintF(buf,"Theta1:%5.1f Phi:%5.1f Theta2:%5.1f Box:%5.1f", theta1*180/pi,phi*180/pi,theta2*180/pi,grid_size); GrText(base,0,0,buf); SPrintF(buf,"x:%5.1f y:%5.1f z:%5.1f height:%3d", x*1.0/COORDINATE_SCALE,y*1.0/COORDINATE_SCALE,z*1.0/COORDINATE_SCALE, height); GrText(base,0,FONT_HEIGHT,buf); //World to screen coordinates r1=GrTheta(theta1); r2=GrPhi(phi); r3=GrTheta(theta2); r4=GrMulMat(r1,r2); r=GrMulMat(r4,r3); Free(r1); Free(r2); Free(r3); Free(r4); base->pen_width=2; base->color=BLACK; GrLine3(base,cx+5,cy,0,cx-5,cy,0); GrLine3(base,cx,cy+5,0,cx,cy-5,0); base->color=GREEN; x2=0;y2=0;z2=0; for (i=yy-grid_s;i=0 && i=0 && j>COORDINATE_BITS; y1=i*MAP_SCALE-y>>COORDINATE_BITS; z1=elevations[i][j]-z>>COORDINATE_BITS; GrRotate(r,&x1,&y1,&z1); if (z1<0) { z1=AbsI8(z1)+FORSHORTENING; x1=x1*FORSHORTENING/z1; y1=y1*FORSHORTENING/z1; if (!first) GrLine(base,x1+cx,cy-y1,x2+cx,cy-y2); } x2=x1;y2=y1;z2=z1; first=FALSE; } } } } Free(r); GrDel(base); } void MPDrawIt(MPCtrl *mp) { TssStruct *tss=mp->win_tss; I8 i,j,*r1,*r2,*r3,*r4,*r,x1,y1,z1,x2,y2,z2,xx,yy, cx=(tss->win_pixel_right-tss->win_pixel_left)>>1, cy=(tss->win_pixel_bottom-tss->win_pixel_top)>>1; GrBitMap *base=GrAlias(Gs->grbase,Fs); BoolU4 first; I8 x=mp->x,y=mp->y,z=mp->z,grid_s=mp->grid_size; base->win_tss=tss; xx=x/MAP_SCALE/COORDINATE_SCALE; yy=y/MAP_SCALE/COORDINATE_SCALE; //World to screen coordinates r1=GrTheta(mp->theta1); r2=GrPhi(mp->phi); r3=GrTheta(mp->theta2); r4=GrMulMat(r1,r2); r=GrMulMat(r4,r3); Free(r1); Free(r2); Free(r3); Free(r4); GrClear(base); base->color=GREEN^WHITE; x2=0;y2=0;z2=0; for (j=xx-grid_s;j=0 && j=0 && i>COORDINATE_BITS; y1=i*MAP_SCALE-y>>COORDINATE_BITS; z1=elevations[i][j]-z>>COORDINATE_BITS; GrRotate(r,&x1,&y1,&z1); if (z1<0) { z1=AbsI8(z1)+FORSHORTENING; x1=x1*FORSHORTENING/z1; y1=y1*FORSHORTENING/z1; if (!first) GrLine(base,x1+cx,cy-y1,x2+cx,cy-y2); } x2=x1;y2=y1;z2=z1; first=FALSE; } } } } Free(r); GrDel(base); } void MPFSim() { while (!mp->done) { while (!mp->update && !mp->done) SwapInNext; MPDrawIt(mp); mp->update=FALSE; } GrClear(Gs->grbase); mp->done=FALSE; } void AnimateTsk() { I8 *r1,*r2,*r3,*r4,*r,x1,y1,z1; while (TRUE) { //Screen to world coordinates r1=GrTheta(-theta2); r2=GrPhi(-phi); r3=GrTheta(-theta1); r4=GrMulMat(r1,r2); r=GrMulMat(r4,r3); x1=0;y1=0;z1=-1.0*speed*COORDINATE_SCALE; GrRotate(r,&x1,&y1,&z1); x+=x1; y+=y1; z+=z1; Free(r1); Free(r2); Free(r3); Free(r4); Free(r); Sleep(1); } } void SongEndTsk() { Sound(0); Exit; } void SongTsk() { Fs->end_task_cb=&SongEndTsk; ResetMusicSettings; while (TRUE) { Play("3etDCDqDetABFsFBFBqC2G3BeDF"); Play("etDCDqDetABFsFBFBqC2G3BeDF"); Play("qReFDqDeF2GqR3sABABqFetREA"); Play("qReFDqDeF2GqR3sABABqFetREA"); } } void EndFSim() { mp->done=TRUE; while (mp->done) SwapInNext; FreeHC(mp,mp_heap); } void EndFSimCB() { //We need this to shut-down CPU#1 task //in case of CPU0 task getting terminated //irregularly. EndFSim; Exit; } void FlightSim() { I8 ch,sc; double pp,tt1,tt2; void *old_update=Fs->update_win; TssStruct *animate_tss,song_tss; BoolU4 old_border=WinBorder(OFF); BoolU4 old_wordstat=WordStat(OFF); //Set callback for irregular aborts Fs->end_task_cb=&EndFSimCB; WinMax; InitMap; Fs->update_win=&DrawIt; animate_tss=Spawn(&AnimateTsk,"FlightSim Animate",Fs); song_tss=Spawn(&SongTsk,"FlightSim Song",Fs); //This heap is uncached mp=MAllocHCZ(sizeof(MPCtrl),mp_heap); WbInvd; //Write mp out of cache mp->win_tss=Fs; if (mp_cnt>1) MPQueueJob(&MPFSim,NULL,1<catch_except=TRUE; Kill(animate_tss); Kill(song_tss); Fs->update_win=old_update; Fs->end_task_cb=NULL; WinBorder(old_border); WordStat(old_wordstat); EndFSim; } FlightSim;