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

329 lines
6.4 KiB
HolyC
Raw Normal View History

2024-03-16 10:26:19 +00:00
//This is a whimsical program which demonstrates some techniques.
#define BORDER 20
#define PTY_PT 0
#define PTY_CIRCLE 1
#define PTY_LINE 2
#define PTY_SPRITE 3
#define PTY_NUM 4
extern class PObj;
class PPt
{
CD3I32 p;
};
class PCircle
{
PObj *p;
I64 radius;
};
class PLine
{
PObj *p1,*p2;
};
class PCSprite
{
PObj *p;
U8 *img;
I64 *r,
*dr; //Rounding error might eventually screw this up
}
class PObj
{
PObj *next,*last;
I64 type,color;
union {
PPt p;
PCircle c;
PLine l;
PCSprite g;
};
};
class PickFrame
{
PObj o_head;
I64 o_cnts[PTY_NUM];
I64 cx,cy;
};
#define IMGS_NUM 3
$SP,"<1>",BI=1$
$SP,"<2>",BI=2$
$SP,"<3>",BI=3$
U8 *imgs[IMGS_NUM]={$IB,"<1>",BI=1$,$IB,"<2>",BI=2$,$IB,"<3>",BI=3$};
U0 DrawIt(CTask *task,CDC *dc)
{
I64 *r,*old_r;
PickFrame *pf=FramePtr("PickFrame",task);
PObj *tmpo=pf->o_head.next;
pf->cx=task->pix_width>>1;
pf->cy=task->pix_height>>1;
DCDepthBufAlloc(dc);
dc->color=LTRED;
dc->thick=3;
GrBorder(dc,BORDER,BORDER,2*pf->cx-BORDER,2*pf->cy-BORDER);
while (tmpo!=&pf->o_head) {
dc->color=tmpo->color;
switch (tmpo->type) {
case PTY_PT:
GrLine(dc,pf->cx+tmpo->p.p.x+2,pf->cy+tmpo->p.p.y+2,
pf->cx+tmpo->p.p.x-2,pf->cy+tmpo->p.p.y-2);
GrLine(dc,pf->cx+tmpo->p.p.x-2,pf->cy+tmpo->p.p.y+2,
pf->cx+tmpo->p.p.x+2,pf->cy+tmpo->p.p.y-2);
break;
case PTY_CIRCLE:
GrCircle(dc,pf->cx+tmpo->c.p->p.p.x,pf->cy+tmpo->c.p->p.p.y,
tmpo->c.radius);
break;
case PTY_LINE:
GrLine(dc,pf->cx+tmpo->l.p1->p.p.x,pf->cy+tmpo->l.p1->p.p.y,
pf->cx+tmpo->l.p2->p.p.x,pf->cy+tmpo->l.p2->p.p.y);
break;
case PTY_SPRITE:
old_r=dc->r;
dc->r=tmpo->g.r;
dc->x=pf->cx+tmpo->g.p->p.p.x;
dc->y=pf->cy+tmpo->g.p->p.p.y;
dc->z=GR_Z_ALL;
dc->flags|=DCF_TRANSFORMATION;
Sprite3(dc,0,0,0,tmpo->g.img);
dc->flags&=~DCF_TRANSFORMATION;
dc->r=old_r;
//Updated each refresh, not guarenteed to be uniform.
//Rounding error might corrupt, as well.
r=Mat4x4MulMat4x4New(tmpo->g.dr,tmpo->g.r,task);
Free(tmpo->g.r);
tmpo->g.r=r;
break;
}
tmpo=tmpo->next;
}
}
PObj *PObjNew(PickFrame *pf,I64 type,I64 color)
{
PObj *tmpo=CAlloc(sizeof(PObj));
tmpo->type=type;
tmpo->color=color;
pf->o_cnts[type]++;
QueIns(tmpo,pf->o_head.last);
return tmpo;
}
U0 PObjDel(PickFrame *pf,PObj *tmpo)
{
QueRem(tmpo);
switch (tmpo->type) {
case PTY_SPRITE:
Free(tmpo->g.r);
Free(tmpo->g.dr);
break;
}
pf->o_cnts[tmpo->type]--;
Free(tmpo);
}
PObj *PPtNew(PickFrame *pf,I64 x,I64 y)
{
PObj *tmpo=PObjNew(pf,PTY_PT,BLACK);
tmpo->p.p.x=x;
tmpo->p.p.y=y;
return tmpo;
}
PObj *PPtNum(PickFrame *pf,I64 num)
{
PObj *tmpo=pf->o_head.next;
while (tmpo!=&pf->o_head) {
if (tmpo->type==PTY_PT && !num--)
return tmpo;
tmpo=tmpo->next;
}
return NULL;
}
PObj *PPtFind(PickFrame *pf,I64 x,I64 y)
{
I64 dd,best_dd=I64_MAX;
PObj *tmpo=pf->o_head.next,*res=NULL;
while (tmpo!=&pf->o_head) {
if (tmpo->type==PTY_PT) {
dd=SqrI64(tmpo->p.p.x-x)+SqrI64(tmpo->p.p.y-y);
if (dd<best_dd) {
best_dd=dd;
res=tmpo;
}
}
tmpo=tmpo->next;
}
return res;
}
PObj *PCircleNew(PickFrame *pf,I64 p_num,I64 r)
{
PObj *tmpo=PObjNew(pf,PTY_CIRCLE,RED);
tmpo->c.p=PPtNum(pf,p_num);
tmpo->c.radius=r;
return tmpo;
}
PObj *PLineNew(PickFrame *pf,I64 p1_num,I64 p2_num)
{
PObj *tmpo=PObjNew(pf,PTY_LINE,GREEN);
tmpo->l.p1=PPtNum(pf,p1_num);
tmpo->l.p2=PPtNum(pf,p2_num);
return tmpo;
}
PObj *PCSpriteNew(PickFrame *pf,U8 *img,I64 p_num,I64 *r,I64 *dr)
{
PObj *tmpo=PObjNew(pf,PTY_SPRITE,BLACK);
tmpo->g.p=PPtNum(pf,p_num);
tmpo->g.img=img;
tmpo->g.r=r;
tmpo->g.dr=dr;
return tmpo;
}
PickFrame *Init()
{
PickFrame *pf=CAlloc(sizeof(PickFrame));
I64 i,*r,*dr;
pf->cx=Fs->pix_width>>1;
pf->cy=Fs->pix_height>>1;
pf->o_head.next=pf->o_head.last=&pf->o_head;
for (i=0;i<50;i++)
PPtNew(pf,RandI32%(pf->cx-BORDER),RandI32%(pf->cy-BORDER));
for (i=0;i<20;i++)
PCircleNew(pf,pf->o_cnts[PTY_PT]*RandU16/U16_MAX,6);
for (i=0;i<20;i++)
PLineNew(pf,pf->o_cnts[PTY_PT]*RandU16/U16_MAX,
pf->o_cnts[PTY_PT]*RandU16/U16_MAX);
for (i=0;i<10;i++) {
r=Mat4x4IdentNew;
dr=Mat4x4IdentNew;
Mat4x4RotZ(dr,0.05*2*(Rand-0.5));
Mat4x4RotY(dr,0.05*2*(Rand-0.5));
Mat4x4RotX(dr,0.05*2*(Rand-0.5));
PCSpriteNew(pf,imgs[IMGS_NUM*RandU16/U16_MAX],
pf->o_cnts[PTY_PT]*RandU16/U16_MAX,r,dr);
}
FramePtrSet("PickFrame",pf);
return pf;
}
U0 CleanUp(PickFrame *pf)
{
PObj *tmpo=pf->o_head.next,*tmpo1;
while (tmpo!=&pf->o_head) {
tmpo1=tmpo->next;
PObjDel(pf,tmpo);
tmpo=tmpo1;
}
Free(pf);
}
U0 Pick3D()
{
I64 msg_code,arg1,arg2;
PObj *tmpo;
PickFrame *pf=NULL;
FramePtrAdd("PickFrame");
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,'\n');"
"}"
);
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
AutoComplete;
WinBorder;
WinMax;
DocClear;
"$$BK,1$$Move things around.$$BK,0$$\n";
pf=Init;
tmpo=NULL;
Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS
-WIF_SELF_CTRLS-WIF_FOCUS_TASK_MENU;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
switch (msg_code=GetMsg(&arg1,&arg2,
1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|1<<MSG_MS_MOVE)) {
case MSG_KEY_DOWN:
switch (arg1) {
case '\n':
CleanUp(pf);
pf=Init;
tmpo=NULL;
break;
case CH_SHIFT_ESC:
case CH_ESC:
goto pd_done;
}
break;
case MSG_MS_L_DOWN:
tmpo=PPtFind(pf,arg1-pf->cx,arg2-pf->cy);
break;
case MSG_MS_L_UP:
if (tmpo) {
tmpo->p.p.x=arg1-pf->cx;
tmpo->p.p.y=arg2-pf->cy;
tmpo=NULL;
}
break;
case MSG_MS_MOVE:
if (tmpo) {
tmpo->p.p.x=arg1-pf->cx;
tmpo->p.p.y=arg2-pf->cy;
}
break;
}
}
pd_done:
GetMsg(,,1<<MSG_KEY_UP);
} catch
PutExcept;
SettingsPop;
MenuPop;
CleanUp(pf);
FramePtrDel("PickFrame");
}
Pick3D;
z<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>