//"ls" is light source. U0 Lighting(CDC *dc,CD3I32 *ls,CD3I32 *poly,I64 color) {//color is a color from 0-7 CD3I32 v1,v2; I64 *r=dc->r,i,vn_x,vn_y,vn_z; F64 d; v1.x=poly[0].x-poly[1].x; v1.y=poly[0].y-poly[1].y; v1.z=poly[0].z-poly[1].z; v2.x=poly[2].x-poly[1].x; v2.y=poly[2].y-poly[1].y; v2.z=poly[2].z-poly[1].z; //V1 and V2 are vects along two sides //of the polygon joined at point[1]. vn_x=v1.y*v2.z-v1.z*v2.y; vn_y=v1.z*v2.x-v1.x*v2.z; vn_z=v1.x*v2.y-v1.y*v2.x; if (d=Sqrt(SqrI64(vn_x)+SqrI64(vn_y)+SqrI64(vn_z))) d=1<<16/d; vn_x*=d; vn_y*=d; vn_z*=d; //Vn is the cross product of V1 and V3 //which means it is perpendicular. It //is the normal vect to the surface. //It has been scaled to length 65536. Mat4x4MulXYZ(r,&vn_x,&vn_y,&vn_z); i=(vn_x*ls->x+vn_y*ls->y+vn_z*ls->z)>>16; //The dot product of the light source //vect and the surface normal //gives an illumination number. //TempleOS will generate a random U16 //and compare to dither_probability_u16 and //will pick from two colors. //Probability dithering does not work with thick>1 at this time. if (i<0) { dc->color=ROPF_PROBABILITY_DITHER+BLACK<<16+color; dc->dither_probability_u16=-i; } else { dc->color=ROPF_PROBABILITY_DITHER+(color^8)<<16+color; dc->dither_probability_u16=i; } } #define RINGS 8 #define FACES 32 #define SLOP 0.03 //Gaps appear without this. U0 DrawIt(CTask *task,CDC *dc) { CCtrl *c=CtrlFindUnique(task,CTRLT_VIEWING_ANGLES); CViewAngles *s=c->state; F64 tt=0.5*(Sin(pi*2*(tS%10.0)/10.0)+2.0), theta,theta2,phi,phi2,radius,d; I64 i,j,cx=task->pix_width/2,cy=task->pix_height/2; CD3I32 poly[3],ls; dc->flags|=DCF_TRANSFORMATION; DCDepthBufAlloc(dc); Mat4x4IdentEqu(dc->r); Mat4x4RotZ(dc->r,s->az); Mat4x4RotY(dc->r,s->ay); Mat4x4RotX(dc->r,s->ax+pi); Mat4x4Scale(dc->r,tt); DCMat4x4Set(dc,dc->r); ls.x=-(ms.pos.x-task->pix_left-task->scroll_x-cx); ls.y=-(ms.pos.y-task->pix_top-task->scroll_y-cy); ls.z=GR_WIDTH/8; d=1<<16/D3I32Norm(&ls); ls.x*=d; ls.y*=d; ls.z*=d; dc->x=cx; dc->y=cy; dc->z=MaxI64(cx,cy); radius =MinI64(cx,cy)/2; for (i=0; i<RINGS; i++) { phi = i*pi/2/RINGS; phi2=(i+1)*pi/2/RINGS+SLOP; for (j=0; j<FACES; j++) { theta =j*2*pi/FACES; theta2=(j+1)*2*pi/FACES+SLOP; //Upper half poly[0].x=radius*Cos(phi)*Cos(theta); poly[0].y=radius*Cos(phi)*Sin(theta); poly[0].z=radius*Sin(phi); poly[1].x=radius*Cos(phi)*Cos(theta2); poly[1].y=radius*Cos(phi)*Sin(theta2); poly[1].z=radius*Sin(phi); poly[2].x=radius*Cos(phi2)*Cos(theta+2*pi/FACES/2); poly[2].y=radius*Cos(phi2)*Sin(theta+2*pi/FACES/2); poly[2].z=radius*Sin(phi2); Lighting(dc,&ls,poly,BLUE); GrFillPoly3(dc,3,poly); poly[2].x=radius*Cos(phi2)*Cos(theta +2*pi/FACES/2); poly[2].y=radius*Cos(phi2)*Sin(theta +2*pi/FACES/2); poly[2].z=radius*Sin(phi2); poly[1].x=radius*Cos(phi2)*Cos(theta2+2*pi/FACES/2); poly[1].y=radius*Cos(phi2)*Sin(theta2+2*pi/FACES/2); poly[1].z=radius*Sin(phi2); poly[0].x=radius*Cos(phi)*Cos(theta2); poly[0].y=radius*Cos(phi)*Sin(theta2); poly[0].z=radius*Sin(phi); Lighting(dc,&ls,poly,BLUE); GrFillPoly3(dc,3,poly); //Lower half poly[2].x=radius*Cos(phi)*Cos(theta); poly[2].y=radius*Cos(phi)*Sin(theta); poly[2].z=-radius*Sin(phi); poly[1].x=radius*Cos(phi)*Cos(theta2); poly[1].y=radius*Cos(phi)*Sin(theta2); poly[1].z=-radius*Sin(phi); poly[0].x=radius*Cos(phi2)*Cos(theta+2*pi/FACES/2); poly[0].y=radius*Cos(phi2)*Sin(theta+2*pi/FACES/2); poly[0].z=-radius*Sin(phi2); Lighting(dc,&ls,poly,RED); GrFillPoly3(dc,3,poly); poly[0].x=radius*Cos(phi2)*Cos(theta +2*pi/FACES/2); poly[0].y=radius*Cos(phi2)*Sin(theta +2*pi/FACES/2); poly[0].z=-radius*Sin(phi2); poly[1].x=radius*Cos(phi2)*Cos(theta2+2*pi/FACES/2); poly[1].y=radius*Cos(phi2)*Sin(theta2+2*pi/FACES/2); poly[1].z=-radius*Sin(phi2); poly[2].x=radius*Cos(phi)*Cos(theta2); poly[2].y=radius*Cos(phi)*Sin(theta2); poly[2].z=-radius*Sin(phi); Lighting(dc,&ls,poly,RED); GrFillPoly3(dc,3,poly); } } } //See ::/Demo/Graphics/SpritePlot3D.HC. //for a CSprite example. //See SpriteMeshEd() for a fancy example. U0 Main() { CCtrl *c=ViewAnglesNew; CViewAngles *s=c->state; s->sx=2*VIEWANGLES_SNAP; s->sy=7*VIEWANGLES_SNAP; s->sz=6*VIEWANGLES_SNAP; SettingsPush; //See SettingsPush AutoComplete; WinBorder; WinMax; DocClear; Fs->draw_it=&DrawIt; try { "\n\nMove mouse to change light source.\n\n"; PressAKey; } catch PutExcept; DocClear; SettingsPop; ViewAnglesDel; } Main;