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

178 lines
4.6 KiB
HolyC
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//"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(ã*2*(tS%10.0)/10.0)+2.0),
é,é2,è,è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+ã);
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++) {
è = i*ã/2/RINGS;
è2=(i+1)*ã/2/RINGS+SLOP;
for (j=0;j<FACES;j++) {
é =j*2*ã/FACES;
é2=(j+1)*2*ã/FACES+SLOP;
//Upper half
poly[0].x=radius*Cos(è)*Cos(é);
poly[0].y=radius*Cos(è)*Sin(é);
poly[0].z=radius*Sin(è);
poly[1].x=radius*Cos(è)*Cos(é2);
poly[1].y=radius*Cos(è)*Sin(é2);
poly[1].z=radius*Sin(è);
poly[2].x=radius*Cos(è2)*Cos(é+2*ã/FACES/2);
poly[2].y=radius*Cos(è2)*Sin(é+2*ã/FACES/2);
poly[2].z=radius*Sin(è2);
Lighting(dc,&ls,poly,BLUE);
GrFillPoly3(dc,3,poly);
poly[2].x=radius*Cos(è2)*Cos(é +2*ã/FACES/2);
poly[2].y=radius*Cos(è2)*Sin(é +2*ã/FACES/2);
poly[2].z=radius*Sin(è2);
poly[1].x=radius*Cos(è2)*Cos(é2+2*ã/FACES/2);
poly[1].y=radius*Cos(è2)*Sin(é2+2*ã/FACES/2);
poly[1].z=radius*Sin(è2);
poly[0].x=radius*Cos(è)*Cos(é2);
poly[0].y=radius*Cos(è)*Sin(é2);
poly[0].z=radius*Sin(è);
Lighting(dc,&ls,poly,BLUE);
GrFillPoly3(dc,3,poly);
//Lower half
poly[2].x=radius*Cos(è)*Cos(é);
poly[2].y=radius*Cos(è)*Sin(é);
poly[2].z=-radius*Sin(è);
poly[1].x=radius*Cos(è)*Cos(é2);
poly[1].y=radius*Cos(è)*Sin(é2);
poly[1].z=-radius*Sin(è);
poly[0].x=radius*Cos(è2)*Cos(é+2*ã/FACES/2);
poly[0].y=radius*Cos(è2)*Sin(é+2*ã/FACES/2);
poly[0].z=-radius*Sin(è2);
Lighting(dc,&ls,poly,RED);
GrFillPoly3(dc,3,poly);
poly[0].x=radius*Cos(è2)*Cos(é +2*ã/FACES/2);
poly[0].y=radius*Cos(è2)*Sin(é +2*ã/FACES/2);
poly[0].z=-radius*Sin(è2);
poly[1].x=radius*Cos(è2)*Cos(é2+2*ã/FACES/2);
poly[1].y=radius*Cos(è2)*Sin(é2+2*ã/FACES/2);
poly[1].z=-radius*Sin(è2);
poly[2].x=radius*Cos(è)*Cos(é2);
poly[2].y=radius*Cos(è)*Sin(é2);
poly[2].z=-radius*Sin(è);
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;