templeos-info/public/Wb/Demo/Graphics/Shading.HC

178 lines
4.6 KiB
HolyC
Raw Normal View History

2024-03-16 10:26:19 +00:00
//"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(<EFBFBD>*2*(tS%10.0)/10.0)+2.0),
<EFBFBD>,<EFBFBD>2,<EFBFBD>,<EFBFBD>2,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+<EFBFBD>);
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++) {
<EFBFBD> = i*<EFBFBD>/2/RINGS;
<EFBFBD>2=(i+1)*<EFBFBD>/2/RINGS+SLOP;
for (j=0;j<FACES;j++) {
<EFBFBD> =j*2*<EFBFBD>/FACES;
<EFBFBD>2=(j+1)*2*<EFBFBD>/FACES+SLOP;
//Upper half
poly[0].x=radius*Cos(<EFBFBD>)*Cos(<EFBFBD>);
poly[0].y=radius*Cos(<EFBFBD>)*Sin(<EFBFBD>);
poly[0].z=radius*Sin(<EFBFBD>);
poly[1].x=radius*Cos(<EFBFBD>)*Cos(<EFBFBD>2);
poly[1].y=radius*Cos(<EFBFBD>)*Sin(<EFBFBD>2);
poly[1].z=radius*Sin(<EFBFBD>);
poly[2].x=radius*Cos(<EFBFBD>2)*Cos(<EFBFBD>+2*<EFBFBD>/FACES/2);
poly[2].y=radius*Cos(<EFBFBD>2)*Sin(<EFBFBD>+2*<EFBFBD>/FACES/2);
poly[2].z=radius*Sin(<EFBFBD>2);
Lighting(dc,&ls,poly,BLUE);
GrFillPoly3(dc,3,poly);
poly[2].x=radius*Cos(<EFBFBD>2)*Cos(<EFBFBD> +2*<EFBFBD>/FACES/2);
poly[2].y=radius*Cos(<EFBFBD>2)*Sin(<EFBFBD> +2*<EFBFBD>/FACES/2);
poly[2].z=radius*Sin(<EFBFBD>2);
poly[1].x=radius*Cos(<EFBFBD>2)*Cos(<EFBFBD>2+2*<EFBFBD>/FACES/2);
poly[1].y=radius*Cos(<EFBFBD>2)*Sin(<EFBFBD>2+2*<EFBFBD>/FACES/2);
poly[1].z=radius*Sin(<EFBFBD>2);
poly[0].x=radius*Cos(<EFBFBD>)*Cos(<EFBFBD>2);
poly[0].y=radius*Cos(<EFBFBD>)*Sin(<EFBFBD>2);
poly[0].z=radius*Sin(<EFBFBD>);
Lighting(dc,&ls,poly,BLUE);
GrFillPoly3(dc,3,poly);
//Lower half
poly[2].x=radius*Cos(<EFBFBD>)*Cos(<EFBFBD>);
poly[2].y=radius*Cos(<EFBFBD>)*Sin(<EFBFBD>);
poly[2].z=-radius*Sin(<EFBFBD>);
poly[1].x=radius*Cos(<EFBFBD>)*Cos(<EFBFBD>2);
poly[1].y=radius*Cos(<EFBFBD>)*Sin(<EFBFBD>2);
poly[1].z=-radius*Sin(<EFBFBD>);
poly[0].x=radius*Cos(<EFBFBD>2)*Cos(<EFBFBD>+2*<EFBFBD>/FACES/2);
poly[0].y=radius*Cos(<EFBFBD>2)*Sin(<EFBFBD>+2*<EFBFBD>/FACES/2);
poly[0].z=-radius*Sin(<EFBFBD>2);
Lighting(dc,&ls,poly,RED);
GrFillPoly3(dc,3,poly);
poly[0].x=radius*Cos(<EFBFBD>2)*Cos(<EFBFBD> +2*<EFBFBD>/FACES/2);
poly[0].y=radius*Cos(<EFBFBD>2)*Sin(<EFBFBD> +2*<EFBFBD>/FACES/2);
poly[0].z=-radius*Sin(<EFBFBD>2);
poly[1].x=radius*Cos(<EFBFBD>2)*Cos(<EFBFBD>2+2*<EFBFBD>/FACES/2);
poly[1].y=radius*Cos(<EFBFBD>2)*Sin(<EFBFBD>2+2*<EFBFBD>/FACES/2);
poly[1].z=-radius*Sin(<EFBFBD>2);
poly[2].x=radius*Cos(<EFBFBD>)*Cos(<EFBFBD>2);
poly[2].y=radius*Cos(<EFBFBD>)*Sin(<EFBFBD>2);
poly[2].z=-radius*Sin(<EFBFBD>);
Lighting(dc,&ls,poly,RED);
GrFillPoly3(dc,3,poly);
}
}
}
//See $LK,"::/Demo/Graphics/SpritePlot3D.HC"$.
//for a CSprite example.
//See $LK,"SpriteMeshEd",A="MN: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 $LK,"SettingsPush",A="MN: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;