hschumann2/TempleOS-Source-Code
0847
1 2#help_index "Graphics/Mesh"3#define MESH_WORKSPACE_SIZE 40004 5#define VF_SEL 16#define VF_COPIED 27#define VF_IGNORE 48 9class CMeshEdVertex10{11 CMeshEdVertex *next,*last,*copy;12 13 U0 start;14 CD3I32 p; //World coordinates of the point.15 U0 end;16 CD3I32 p0,17 pt; //Transformed coordinates. (Scrn)18 I32 num,flags;19};20 21#define TF_SEL 122#define TF_COPIED 223 24class CMeshEdTri25{26 CMeshEdTri *next,*last;27 28 U0 start;29 CMeshTri mt;30 U0 end;31 32 I32 cpu_num,flags; //Draw different tris with different cores.33 CMeshEdVertex *t[3];34};35 36class CMeshFrame37{38 I64 ms_z,thickness; //Mouse Z-coordinate39 I64 ed_mode,cx,cy;40 CColorROPU32 cur_color;41 Bool grid_on,flip_y,sel_rect,vertex_on,closed,pad[3];42 I64 mp_not_done_flags; //Used for multiprocessing signaling.43 F64 view_scale;44 CDC *dc;45 I32 *depth_buf;46 I64 *w2s,*s2w; //Scrn-to-world and world-to-scrn transform matrices.47 I64 vertex_cnt,tri_cnt; //Set by MeshSize48 CMeshEdVertex vertex_head,*cur_vertex,*chain_pred;49 CMeshEdTri tri_head,*cur_tri;50 I64 x1,y1,x2,y2,cur_snap;51};52 53CMeshEdVertex *MeshVertexNew(CMeshFrame *e,I64 x,I64 y,I64 z)54{55 CMeshEdVertex *tmpv=CAlloc(sizeof(CMeshEdVertex));56 tmpv->p.x=x;57 tmpv->p.y=y;58 tmpv->p.z=z;59 QueIns(tmpv,e->vertex_head.last);60 return tmpv;61}62 63CMeshEdTri *MeshTriNew(CMeshFrame *e,CColorROPU32 color,64 CMeshEdVertex *v1,CMeshEdVertex *v2,CMeshEdVertex *v3)65{66 static I64 cpu_num=0;67 CMeshEdTri *tmpt=CAlloc(sizeof(CMeshEdTri));68 tmpt->cpu_num=cpu_num++%mp_cnt;69 tmpt->mt.color=color;70 tmpt->t[0]=v1;71 tmpt->t[1]=v2;72 tmpt->t[2]=v3;73 QueIns(tmpt,e->tri_head.last);74 return tmpt;75}76 77CMeshEdVertex *MeshVertexFindScrPt(CMeshFrame *e,I64 x,I64 y)78{//Scrn coordinates79 CMeshEdVertex *res=NULL,*tmpv=e->vertex_head.next;80 I64 dd,dz,best_dd=I64_MAX,best_dz=I64_MAX;81 while (tmpv!=&e->vertex_head) {82 if (!(tmpv->flags&VF_IGNORE)) {83 dd=SqrI64(x-tmpv->pt.x)+SqrI64(y-tmpv->pt.y);84 dz=AbsI64(e->ms_z-tmpv->p.z);85 if (dd<best_dd || dd==best_dd && dz<best_dz) {86 res=tmpv;87 best_dd=dd;88 best_dz=dz;89 }90 }91 tmpv=tmpv->next;92 }93 return res;94}95 96CMeshEdVertex *MeshVertexFindNum(CMeshFrame *haystack_e,I64 needle_num)97{98 CMeshEdVertex *tmpv=haystack_e->vertex_head.next;99 while (tmpv!=&haystack_e->vertex_head) {100 if (tmpv->num==needle_num)101 return tmpv;102 tmpv=tmpv->next;103 }104 return NULL;105}106 107U0 MeshTriDel(CMeshFrame *e,CMeshEdTri *tmpt)108{109 if (tmpt) {110 if (tmpt==e->cur_tri)111 e->cur_tri=NULL;112 QueRem(tmpt);113 Free(tmpt);114 }115}116 117U0 MeshVertexDel(CMeshFrame *e,CMeshEdVertex *tmpv)118{119 I64 i;120 CMeshEdTri *tmpt,*tmpt1;121 if (tmpv) {122 tmpt=e->tri_head.next;123 while (tmpt!=&e->tri_head) {124 tmpt1=tmpt->next;125 for (i=0;i<3;i++)126 if (tmpt->t[i]==tmpv)127 break;128 if (i<3)129 MeshTriDel(e,tmpt);130 tmpt=tmpt1;131 }132 if (tmpv==e->cur_vertex)133 e->cur_vertex=NULL;134 if (tmpv==e->chain_pred)135 e->chain_pred=NULL;136 QueRem(tmpv);137 Free(tmpv);138 }139}140 141U0 MeshFence(CMeshFrame *e)142{143 CMeshEdVertex *tmpv,*tmpv1,*tmpv_last=NULL,*tmpv1_last=NULL,144 *start=e->chain_pred->next,*end=e->vertex_head.last;145 tmpv=start;146 while (TRUE) {147 tmpv1=MeshVertexNew(e,tmpv->p.x,tmpv->p.y,tmpv->p.z+e->thickness);148 if (tmpv_last) {149 MeshTriNew(e,e->cur_color,tmpv_last,tmpv,tmpv1);150 MeshTriNew(e,e->cur_color,tmpv1,tmpv1_last,tmpv_last);151 }152 tmpv_last=tmpv;153 tmpv1_last=tmpv1;154 if (tmpv==end)155 break;156 tmpv=tmpv->next;157 }158 if (e->closed && tmpv_last) {159 MeshTriNew(e,e->cur_color,tmpv_last,start,end->next);160 MeshTriNew(e,e->cur_color,end->next,tmpv1_last,tmpv_last);161 }162}163 164U0 MeshPolygon(CMeshFrame *e,CMeshEdVertex *start,CMeshEdVertex *end,Bool rev)165{166 CMeshEdVertex *tmpv,*tmpv1;167 if (start!=end) {168 tmpv=start;169 tmpv1=tmpv->next;170 while (tmpv1!=end) {171 if (rev)172 MeshTriNew(e,e->cur_color,tmpv1,tmpv,end);173 else174 MeshTriNew(e,e->cur_color,tmpv,tmpv1,end);175 tmpv=tmpv->next;176 tmpv1=tmpv1->next;177 }178 }179}180 181U0 MeshPrism(CMeshFrame *e)182{183 CMeshEdVertex *start=e->chain_pred->next,*end=e->vertex_head.last;184 MeshFence(e);185 MeshPolygon(e,start,end,FALSE);186 MeshPolygon(e,end->next,e->vertex_head.last,TRUE);187}188 189U0 MeshVertexSelAll(CMeshFrame *e,Bool val)190{191 CMeshEdVertex *tmpv=e->vertex_head.next;192 while (tmpv!=&e->vertex_head) {193 if (val)194 tmpv->flags|=VF_SEL;195 else196 tmpv->flags&=~VF_SEL;197 tmpv=tmpv->next;198 }199}200 201U0 MeshTriSelAll(CMeshFrame *e,Bool val)202{203 CMeshEdTri *tmpt=e->tri_head.next;204 while (tmpt!=&e->tri_head) {205 if (val)206 tmpt->flags|=TF_SEL;207 else208 tmpt->flags&=~TF_SEL;209 tmpt=tmpt->next;210 }211}212 213U0 MeshVertexIgnoreSet(CMeshFrame *e,Bool val)214{215 CMeshEdVertex *tmpv=e->vertex_head.next;216 while (tmpv!=&e->vertex_head) {217 tmpv->flags&=~VF_IGNORE;218 if (tmpv->flags&VF_SEL && val)219 tmpv->flags|=VF_IGNORE;220 tmpv=tmpv->next;221 }222}223 224U0 MeshP0Capture(CMeshFrame *e)225{226 CMeshEdVertex *tmpv=e->vertex_head.next;227 while (tmpv!=&e->vertex_head) {228 MemCpy(&tmpv->p0,&tmpv->p,sizeof(CD3I32));229 tmpv=tmpv->next;230 }231}232 233U0 MeshP0Offset(CMeshFrame *e,I64 dx,I64 dy,I64 dz)234{235 CMeshEdVertex *tmpv=e->vertex_head.next;236 while (tmpv!=&e->vertex_head) {237 if (tmpv->flags&VF_SEL) {238 tmpv->p.x=tmpv->p0.x+dx;239 tmpv->p.y=tmpv->p0.y+dy;240 tmpv->p.z=tmpv->p0.z+dz;241 }242 tmpv=tmpv->next;243 }244}245 246#define SEL_MESH_EQU 0247#define SEL_MESH_OR 1248#define SEL_MESH_AND 2249 250U0 MeshVertexSelRect(CMeshFrame *e,I64 sel_mode,I64 x1,I64 x2,I64 y1,I64 y2)251{252 CMeshEdVertex *tmpv=e->vertex_head.next;253 if (x1>x2) SwapI64(&x1,&x2);254 if (y1>y2) SwapI64(&y1,&y2);255 while (tmpv!=&e->vertex_head) {256 if (x1<=tmpv->pt.x<=x2 &&257 y1<=tmpv->pt.y<=y2) {258 if (sel_mode==SEL_MESH_AND)259 tmpv->flags&=~VF_SEL;260 else261 tmpv->flags|=VF_SEL;262 } else if (sel_mode==SEL_MESH_EQU)263 tmpv->flags&=~VF_SEL;264 tmpv=tmpv->next;265 }266}267 268U0 MeshTriSelRect(CMeshFrame *e,I64 sel_mode,I64 x1,I64 x2,I64 y1,I64 y2)269{270 CMeshEdTri *tmpt=e->tri_head.next;271 if (x1>x2) SwapI64(&x1,&x2);272 if (y1>y2) SwapI64(&y1,&y2);273 while (tmpt!=&e->tri_head) {274 if (x1<=tmpt->t[0]->pt.x<=x2 &&275 y1<=tmpt->t[0]->pt.y<=y2 &&276 x1<=tmpt->t[1]->pt.x<=x2 &&277 y1<=tmpt->t[1]->pt.y<=y2 &&278 x1<=tmpt->t[2]->pt.x<=x2 &&279 y1<=tmpt->t[2]->pt.y<=y2) {280 if (sel_mode==SEL_MESH_AND)281 tmpt->flags&=~TF_SEL;282 else283 tmpt->flags|=TF_SEL;284 } else {285 if (sel_mode==SEL_MESH_EQU)286 tmpt->flags&=~TF_SEL;287 else if (sel_mode==SEL_MESH_AND) {288 if (x1<=tmpt->t[0]->pt.x<=x2 &&289 y1<=tmpt->t[0]->pt.y<=y2 ||290 x1<=tmpt->t[1]->pt.x<=x2 &&291 y1<=tmpt->t[1]->pt.y<=y2 ||292 x1<=tmpt->t[2]->pt.x<=x2 &&293 y1<=tmpt->t[2]->pt.y<=y2)294 tmpt->flags&=~TF_SEL;295 }296 }297 tmpt=tmpt->next;298 }299}300 301I64 MeshSelCnt(CMeshFrame *e)302{303 I64 res=0;304 CMeshEdVertex *tmpv=e->vertex_head.next;305 CMeshEdTri *tmpt=e->tri_head.next;306 while (tmpv!=&e->vertex_head) {307 if (tmpv->flags&VF_SEL)308 res++;309 tmpv=tmpv->next;310 }311 while (tmpt!=&e->tri_head) {312 if (tmpt->flags&TF_SEL)313 res++;314 tmpt=tmpt->next;315 }316 return res;317}318 319U0 MeshSwapAxes(CMeshFrame *e,I64 o1,I64 o2)320{321 Bool unsel;322 CMeshEdVertex *tmpv=e->vertex_head.next;323 if (!MeshSelCnt(e)) {324 MeshVertexSelAll(e,TRUE);325 unsel=TRUE;326 } else327 unsel=FALSE;328 while (tmpv!=&e->vertex_head) {329 if (tmpv->flags&VF_SEL)330 SwapU32((&tmpv->p)(U8 *)+o1,(&tmpv->p)(U8 *)+o2);331 tmpv=tmpv->next;332 }333 if (unsel)334 MeshVertexSelAll(e,FALSE);335}336 337U0 MeshInvertAxis(CMeshFrame *e,I64 o)338{339 Bool unsel;340 CMeshEdVertex *tmpv=e->vertex_head.next;341 if (!MeshSelCnt(e)) {342 MeshVertexSelAll(e,TRUE);343 unsel=TRUE;344 } else345 unsel=FALSE;346 while (tmpv!=&e->vertex_head) {347 if (tmpv->flags&VF_SEL)348 *((&tmpv->p)(U8 *)+o)(I32 *)=-*((&tmpv->p)(U8 *)+o)(I32 *);349 tmpv=tmpv->next;350 }351 if (unsel)352 MeshVertexSelAll(e,FALSE);353}354 355U0 MeshTransformSel(CMeshFrame *e)356{357 Bool unsel;358 I64 r[16],x,y,z;359 CMeshEdVertex *tmpv=e->vertex_head.next;360 if (PopUpTransform(r)) {361 if (!MeshSelCnt(e)) {362 MeshVertexSelAll(e,TRUE);363 unsel=TRUE;364 } else365 unsel=FALSE;366 while (tmpv!=&e->vertex_head) {367 if (tmpv->flags&VF_SEL) {368 x=tmpv->p.x; y=tmpv->p.y; z=tmpv->p.z;369 Mat4x4MulXYZ(r,&x,&y,&z);370 tmpv->p.x=x; tmpv->p.y=y; tmpv->p.z=z;371 }372 tmpv=tmpv->next;373 }374 if (unsel)375 MeshVertexSelAll(e,FALSE);376 }377}378 379U0 MeshColorTris(CMeshFrame *e)380{381 Bool unsel;382 CMeshEdTri *tmpt=e->tri_head.next;383 if (!MeshSelCnt(e)) {384 MeshTriSelAll(e,TRUE);385 unsel=TRUE;386 } else387 unsel=FALSE;388 while (tmpt!=&e->tri_head) {389 if (tmpt->flags & TF_SEL)390 tmpt->mt.color=e->cur_color;391 tmpt=tmpt->next;392 }393 if (unsel)394 MeshTriSelAll(e,FALSE);395}396 397U0 MeshRevTris(CMeshFrame *e)398{399 Bool unsel;400 CMeshEdTri *tmpt=e->tri_head.next;401 if (!MeshSelCnt(e)) {402 MeshTriSelAll(e,TRUE);403 unsel=TRUE;404 } else405 unsel=FALSE;406 while (tmpt!=&e->tri_head) {407 if (tmpt->flags & TF_SEL)408 SwapI64(&tmpt->t[1],&tmpt->t[2]);409 tmpt=tmpt->next;410 }411 if (unsel)412 MeshTriSelAll(e,FALSE);413}414 415U0 MeshRecalcCxCy(CTask *task,CMeshFrame *e)416{417 e->cx=RoundI64(task->pix_width/2 -task->horz_scroll.pos,e->cur_snap);418 e->cy=RoundI64(task->pix_height/2-task->vert_scroll.pos,e->cur_snap);419}420 421U0 MeshCurSnap(CMeshFrame *e)422{423 I64 x1,y1,z1,x2,y2,z2;424 if (e->w2s) {425 x1=e->cur_snap<<16; y1=0; z1=0;426 Mat4x4MulXYZ(e->w2s,&x1,&y1,&z1);427 x2=0; y2=e->cur_snap<<16; z2=0;428 Mat4x4MulXYZ(e->w2s,&x2,&y2,&z2);429 ms_grid.x=Max(1,MaxI64(x1,x2)>>16);430 ms_grid.y=Max(1,MaxI64(y1,y2)>>16);431 ms_grid.z=Min(ms_grid.x,ms_grid.y);432 }433}434 435U0 MeshScaleZoom(CMeshFrame *e,F64 scale)436{437 CTask *task=Fs;438 I64 x=ms.pos.x-task->pix_left-task->scroll_x-task->pix_width/2,439 y=ms.pos.y-task->pix_top-task->scroll_y-task->pix_height/2;440 task->horz_scroll.pos*=scale;441 task->vert_scroll.pos*=scale;442 task->horz_scroll.pos+=scale*x-x;443 task->vert_scroll.pos+=scale*y-y;444 e->view_scale*=scale;445 MeshRecalcCxCy(task,e);446 MeshCurSnap(e);447}448 449U0 MPDrawIt(CMeshFrame *e)450{//Multiprocessing draw it, called by each core.451 452 //Makes a copy of e->dc so we can change dc->color member and stuff.453 CDC *dc=DCAlias(e->dc,e->dc->win_task);454 455 CMeshEdTri *tmpt=e->tri_head.next;456 I64 i,*old_r=dc->r;457 458 //DCAlias() allocs a new identity rotation matrix.459 //We want e->dc's rotation matrix.460 dc->r=e->dc->r;461 dc->depth_buf=e->depth_buf;462 MemCpy(&dc->ls,&e->dc->ls,sizeof(CD3I32));463 464 //... and translation (shift) vals.465 dc->x=e->dc->x;466 dc->y=e->dc->y;467 dc->z=e->dc->z;468 dc->flags|=DCF_TRANSFORMATION;469 470 if (e->grid_on)471//Draw grid with different cores.472 for (i=-500+25*Gs->num;i<=500;i+=25*mp_cnt) {473 if (i) {474 dc->color=DKGRAY;475 GrLine3(dc,i,-500,0,i,500,0);476 dc->color=LTGRAY;477 GrLine3(dc,-500,i,0,500,i,0);478 }479 }480 if (!Gs->num) {481 dc->color=RED; //Y-Axis red482 GrLine3(dc,0,0,0,0,500,0);483 dc->color=ROPF_DITHER+RED; //Y-Axis red484 GrLine3(dc,0,-500,0,0,0,0);485 486 dc->color=YELLOW; //X-Axis yellow487 GrLine3(dc,0,0,0,500,0,0);488 dc->color=ROPF_DITHER+YELLOW; //X-Axis yellow489 GrLine3(dc,-500,0,0,0,0,0);490 491 dc->color=GREEN; //Z-Axis green492 GrLine3(dc,0,0,0,0,0,500);493 dc->color=ROPF_DITHER+GREEN; //Z-Axis green494 GrLine3(dc,0,0,-500,0,0,0);495 }496 497 while (tmpt!=&e->tri_head) {498 if (tmpt->cpu_num==Gs->num) {499 if (tmpt->flags & TF_SEL) {500 if (Blink)501 dc->color=ROPF_DITHER+WHITE<<16+RED;502 else503 dc->color=ROPF_DITHER+RED<<16+WHITE;504 GrFillTri0(dc,&tmpt->t[0]->pt,&tmpt->t[1]->pt,&tmpt->t[2]->pt);505 } else {506 (*dc->lighting)(dc,&tmpt->t[0]->pt,&tmpt->t[1]->pt,507 &tmpt->t[2]->pt,tmpt->mt.color);508 GrFillTri0(dc,&tmpt->t[0]->pt,&tmpt->t[1]->pt,&tmpt->t[2]->pt);509 }510 }511 tmpt=tmpt->next;512 }513 dc->r=old_r;514 515 //e->dc's depth buf was copied but we don't want it freed during DCDel().516 dc->depth_buf=NULL;517 518 DCDel(dc);519 LBtr(&e->mp_not_done_flags,Gs->num);520}521 522I64 *MeshW2S(CMeshFrame *e,CTask *task)523{//World to scrn coordinate transform matrix.524 CCtrl *c=CtrlFindUnique(task,CTRLT_VIEWING_ANGLES);525 CViewAngles *s=c->state;526 I64 *r=Mat4x4IdentNew(task);527 Mat4x4Scale(r,e->view_scale);528 Mat4x4RotZ(r,s->az);529 Mat4x4RotY(r,s->ay);530 if (e->flip_y)531 Mat4x4RotX(r,s->ax);532 else533 Mat4x4RotX(r,s->ax+pi);534 return r;535}536 537I64 *MeshS2W(CMeshFrame *e,CTask *task)538{//Scrn to world coordinate transform matrix.539 CCtrl *c=CtrlFindUnique(task,CTRLT_VIEWING_ANGLES);540 CViewAngles *s=c->state;541 I64 *r=Mat4x4IdentNew(task);542 if (e->flip_y)543 Mat4x4RotX(r,-s->ax);544 else545 Mat4x4RotX(r,-(s->ax+pi));546 Mat4x4RotY(r,-s->ay);547 Mat4x4RotZ(r,-s->az);548 Mat4x4Scale(r,1/e->view_scale);549 return r;550}551 552I64 *MeshSetW2S(CMeshFrame *e,CTask *task)553{554 Free(e->w2s);555 e->w2s=MeshW2S(e,task);556 Free(e->s2w);557 e->s2w=MeshS2W(e,task);558//returned matrix is assigned to dc->r and will be freed by DCDel().559 return Mat4x4New(e->w2s,task);560}561 562U0 MeshCursorW(CMeshFrame *e,CTask *task,I64 *_x,I64 *_y,I64 *_z)563{564 I64 x_shadow,y_shadow,z_shadow,565 xc=ms.pos.x-task->pix_left-task->scroll_x-e->cx,566 yc=ms.pos.y-task->pix_top-task->scroll_y-e->cy,zc=0,567 x=0,y=0,z=e->ms_z,568 i,x2,y2,z2;569 Mat4x4MulXYZ(e->w2s,&x,&y,&z); //scrn of Z vect570 571 //Converges onto a solution for zc, an unknown.572 for (i=0;i<128;i++) {573 x_shadow=xc-x; //Shadow of mouse cursor on xy plane574 y_shadow=yc-y;575 z_shadow=zc-z;576 Mat4x4MulXYZ(e->s2w,&x_shadow,&y_shadow,&z_shadow);577 x2=0; y2=0; z2=-z_shadow;578 Mat4x4MulXYZ(e->w2s,&x2,&y2,&z2);579 zc+=Round(Sqrt(x2*x2+y2*y2+z2*z2))*SignI64(z2);580 }581 582 x=xc-x;583 y=yc-y;584 z=zc-z;585 Mat4x4MulXYZ(e->s2w,&x,&y,&z);586 x=RoundI64(x,e->cur_snap);587 y=RoundI64(y,e->cur_snap);588 z=RoundI64(e->ms_z,e->cur_snap);589 *_x=x; *_y=y; *_z=z;590}591 592CMeshEdVertex sys_clip_vertex_head;593CMeshEdTri sys_clip_tri_head;594 595U0 MeshClipInit()596{597 QueInit(&sys_clip_vertex_head);598 QueInit(&sys_clip_tri_head);599}600 601U0 MeshClipRst()602{603 QueDel(&sys_clip_vertex_head,TRUE);604 QueDel(&sys_clip_tri_head,TRUE);605 MeshClipInit;606}607 608U0 MeshClipCopy(CMeshFrame *e)609{610 CMeshEdVertex *tmpv=e->vertex_head.next,*tmpv2;611 CMeshEdTri *tmpt=e->tri_head.next,*tmpt2;612 613 MeshClipRst;614 while (tmpv!=&e->vertex_head) {615 if (tmpv->flags&VF_SEL) {616 tmpv->copy=tmpv2=ACAlloc(sizeof(CMeshEdVertex));617 MemCpy(&tmpv2->p,&tmpv->p,sizeof(CD3I32));618 QueIns(tmpv2,sys_clip_vertex_head.last);619 tmpv->flags|=VF_COPIED;620 tmpv->flags&=~VF_SEL;621 } else {622 tmpv->copy=NULL;623 tmpv->flags&=~(VF_COPIED|VF_SEL);624 }625 tmpv=tmpv->next;626 }627 while (tmpt!=&e->tri_head) {628 if (tmpt->flags&TF_SEL &&629 tmpt->t[0]->copy && tmpt->t[1]->copy && tmpt->t[2]->copy) {630 tmpt2=ACAlloc(sizeof(CMeshEdTri));631 tmpt2->t[0]=tmpt->t[0]->copy;632 tmpt2->t[1]=tmpt->t[1]->copy;633 tmpt2->t[2]=tmpt->t[2]->copy;634 tmpt2->mt.color=tmpt->mt.color;635 QueIns(tmpt2,sys_clip_tri_head.last);636 tmpt->flags|=TF_COPIED;637 tmpt->flags&=~TF_SEL;638 } else639 tmpt->flags&=~(TF_COPIED|TF_SEL);640 tmpt=tmpt->next;641 }642}643 644U0 MeshClipCut(CMeshFrame *e)645{646 CMeshEdVertex *tmpv=e->vertex_head.next,*tmpv1;647 CMeshEdTri *tmpt=e->tri_head.next,*tmpt1;648 MeshClipCopy(e);649 while (tmpt!=&e->tri_head) {650 tmpt1=tmpt->next;651 if (tmpt->flags&TF_COPIED)652 MeshTriDel(e,tmpt);653 tmpt=tmpt1;654 }655 while (tmpv!=&e->vertex_head) {656 tmpv1=tmpv->next;657 if (tmpv->flags&VF_COPIED)658 MeshVertexDel(e,tmpv);659 tmpv=tmpv1;660 }661}662 663U0 MeshClipDel(CMeshFrame *e)664{//Technically not clip665 CMeshEdVertex *tmpv=e->vertex_head.next,*tmpv1;666 CMeshEdTri *tmpt=e->tri_head.next,*tmpt1;667 while (tmpt!=&e->tri_head) {668 tmpt1=tmpt->next;669 if (tmpt->flags&TF_SEL)670 MeshTriDel(e,tmpt);671 tmpt=tmpt1;672 }673 while (tmpv!=&e->vertex_head) {674 tmpv1=tmpv->next;675 if (tmpv->flags&VF_SEL)676 MeshVertexDel(e,tmpv);677 tmpv=tmpv1;678 }679}680 681U0 MeshClipPaste(CMeshFrame *e)682{683 CMeshEdVertex *tmpv2=sys_clip_vertex_head.next,*tmpv;684 CMeshEdTri *tmpt2=sys_clip_tri_head.next,*tmpt;685 686 MeshVertexSelAll(e,FALSE);687 MeshTriSelAll(e,FALSE);688 while (tmpv2!=&sys_clip_vertex_head) {689 tmpv2->copy=tmpv=CAlloc(sizeof(CMeshEdVertex));690 MemCpy(&tmpv->p,&tmpv2->p,sizeof(CD3I32));691 QueIns(tmpv,e->vertex_head.last);692 tmpv->flags|=VF_SEL;693 tmpv2=tmpv2->next;694 }695 696 while (tmpt2!=&sys_clip_tri_head) {697 tmpt=MeshTriNew(e,tmpt2->mt.color,tmpt2->t[0]->copy,698 tmpt2->t[1]->copy,tmpt2->t[2]->copy);699 tmpt->flags|=TF_SEL;700 tmpt2=tmpt2->next;701 }702}703 704MeshClipInit;705 706U0 DrawIt(CTask *task,CDC *dc)707{708 CMeshFrame *e=FramePtr("CMeshFrame",task);709 CCtrl *c=CtrlFindUnique(task,CTRLT_VIEWING_ANGLES);710 F64 d;711 I64 i,x,y,z;712 CMeshEdVertex *tmpv;713 714 task->horz_scroll.min=-(MESH_WORKSPACE_SIZE-task->pix_width)/2;715 task->horz_scroll.max= (MESH_WORKSPACE_SIZE-task->pix_width)/2;716 task->vert_scroll.min=-(MESH_WORKSPACE_SIZE-task->pix_height)/2;717 task->vert_scroll.max= (MESH_WORKSPACE_SIZE-task->pix_height)/2;718 TaskDerivedValsUpdate(task);719 MeshRecalcCxCy(task,e);720 721 dc->flags|=DCF_TRANSFORMATION;722 723 Free(dc->r); //Set rotmat doesn't free old dc->r matrix.724 DCMat4x4Set(dc,MeshSetW2S(e,task));725 726 dc->x=e->cx;727 dc->y=e->cy;728//z-vals less than zero are in front of scrn and not drawn.729 //we want to shift all Z-vals into a drawable range.730 //GR_Z_ALL is set to half of the Z-range which is an I32.731 dc->z=GR_Z_ALL;732 733 //Light source set to mouse.734 MeshCursorW(e,task,&x,&y,&z);735 dc->ls.x=x;736 dc->ls.y=y;737 dc->ls.z=z;738 d=1<<16/D3I32Norm(&dc->ls); //Light source normalized to 65536.739 dc->ls.x*=d;740 dc->ls.y*=d;741 dc->ls.z*=d;742 743 DCDepthBufAlloc(dc);744 745 tmpv=e->vertex_head.next;746 while (tmpv!=&e->vertex_head) {747 x=tmpv->p.x; y=tmpv->p.y; z=tmpv->p.z;748 (*dc->transform)(dc,&x,&y,&z);749 tmpv->pt.x=x; tmpv->pt.y=y; tmpv->pt.z=z;750 tmpv=tmpv->next;751 }752 753 e->mp_not_done_flags=1<<mp_cnt-1; //Issue jobs to all cores.754 e->dc=dc;755 e->depth_buf=dc->depth_buf;756 for (i=0;i<mp_cnt;i++)757 JobQue(&MPDrawIt,e,i);758 759 tmpv=e->vertex_head.next;760 while (tmpv!=&e->vertex_head) {761 x=tmpv->pt.x; y=tmpv->pt.y; z=tmpv->pt.z;762 if (e->vertex_on) {763 if (Blink(10)) //This blinks at 10 Hz.764 dc->color=ROPF_DITHER+BLACK<<16+WHITE;765 else766 dc->color=ROPF_DITHER+WHITE<<16+BLACK;767 GrLine(dc,x-3,y-3,x+3,y+3);768 GrLine(dc,x-3,y+3,x+3,y-3);769 }770 if (tmpv->flags&VF_SEL) {771 if (e->ed_mode=='t') {772 if (Blink(10)) //This blinks at 10 Hz.773 dc->color=ROPF_DITHER+e->cur_color.c0.color<<16+774 e->cur_color.c0.color^8;775 else776 dc->color=ROPF_DITHER+(e->cur_color.c0.color^8)<<16+777 e->cur_color.c0.color;778 } else {779 if (Blink)780 dc->color=ROPF_DITHER+RED<<16+WHITE;781 else782 dc->color=ROPF_DITHER+WHITE<<16+RED;783 }784 GrCircle(dc,x,y,3);785 }786 tmpv=tmpv->next;787 }788 789 if (CtrlInside(c,ms.presnap.x,ms.presnap.y)||winmgr.show_menu) {790 GridInit;791 task->win_inhibit=WIF_SELF_DOC;792 } else {793 MeshCurSnap(e);794 task->win_inhibit=WIG_TASK_DFT|WIF_SELF_DOC-WIF_SELF_FOCUS-WIF_SELF_BORDER795 -WIF_SELF_CTRLS-WIF_FOCUS_TASK_MENU-WIF_SELF_GRAB_SCROLL;796 }797 798 MeshCursorW(e,task,&x,&y,&z);799 if (z<0)800 dc->color=ROP_XOR+RED^TRANSPARENT;801 else802 dc->color=ROP_XOR+TRANSPARENT;803 GrPrint(dc,0,0,"%6.3f%% (%d,%d,%d)",e->view_scale*100,x,y,z);804 dc->thick=1;805 dc->color&=0xF;806 if (Blink(10))807 dc->color^=0xF;808 GrLine3(dc,x,y,z,x,y,0);809 810 if (e->sel_rect) {811 dc->flags&=~DCF_TRANSFORMATION;812 dc->thick=1;813 if (Blink)814 dc->color=ROPF_DITHER+RED<<16+WHITE;815 else816 dc->color=ROPF_DITHER+WHITE<<16+RED;817 GrBorder(dc,e->x1,e->y1,e->x2,e->y2);818 }819//Wait for all cores to complete.820 while (e->mp_not_done_flags)821 Yield;822}823 824U0 MeshInit(CMeshFrame *e,Bool flip_y)825{826 MemSet(e,0,sizeof(CMeshFrame));827 QueInit(&e->vertex_head);828 QueInit(&e->tri_head);829 e->ed_mode='v';830 e->grid_on=TRUE;831 e->vertex_on=TRUE;832 e->ms_z=0;833 e->thickness=25;834 e->closed=TRUE;835 e->view_scale=1.0;836 e->w2s=NULL;837 e->s2w=NULL;838 e->cur_color=RED;839 e->cur_snap=5;840 e->flip_y=flip_y;841 e->sel_rect=FALSE;842 e->cur_tri=NULL;843 e->cur_vertex=NULL;844 e->chain_pred=NULL;845}846 847U0 MeshLoad(CMeshFrame *e,U8 *src)848{849 I64 i,j,x,y,z;850 CColorROPU32 color;851 CMeshEdVertex *tmpv,*va[3];852 853 QueInit(&e->vertex_head);854 QueInit(&e->tri_head);855 856 e->vertex_cnt =*src(I32 *)++;857 e->tri_cnt=*src(I32 *)++;858 for (i=0;i<e->vertex_cnt;i++) {859 x=*src(I32 *)++;860 y=*src(I32 *)++;861 z=*src(I32 *)++;862 tmpv=MeshVertexNew(e,x,y,z);863 tmpv->num=i;864 }865 for (i=0;i<e->tri_cnt;i++) {866 color=*src(I32 *)++;867 for (j=0;j<3;j++)868 va[j]=MeshVertexFindNum(e,*src(I32 *)++);869 MeshTriNew(e,color,va[0],va[1],va[2]);870 }871}872 873I64 MeshSize(CMeshFrame *e)874{875 I64 i;876 CMeshEdVertex *tmpv=e->vertex_head.next;877 CMeshEdTri *tmpt=e->tri_head.next;878 879 e->vertex_cnt=0;880 while (tmpv!=&e->vertex_head) {881 tmpv->num=e->vertex_cnt++;882 tmpv=tmpv->next;883 }884 885 e->tri_cnt=0;886 while (tmpt!=&e->tri_head) {887 e->tri_cnt++;888 for (i=0;i<3;i++)889 tmpt->mt.nums[i]=tmpt->t[i]->num;890 tmpt=tmpt->next;891 }892 return sizeof(I32)*2+893 (offset(CMeshEdVertex.end)-offset(CMeshEdVertex.start))*e->vertex_cnt+894 (offset(CMeshEdTri.end)-offset(CMeshEdTri.start))*e->tri_cnt;895}896 897I32 *MeshSave(CMeshFrame *e,I64 *_size=NULL)898{899 I64 size=MeshSize(e);900 U8 *res=MAlloc(size),*dst=res;901 CMeshEdVertex *tmpv=e->vertex_head.next;902 CMeshEdTri *tmpt=e->tri_head.next;903 904 *dst(I32 *)++=e->vertex_cnt;905 *dst(I32 *)++=e->tri_cnt;906 907 e->vertex_cnt=0;908 while (tmpv!=&e->vertex_head) {909 MemCpy(dst,&tmpv->start,offset(CMeshEdVertex.end)910 -offset(CMeshEdVertex.start));911 dst+=offset(CMeshEdVertex.end)-offset(CMeshEdVertex.start);912 tmpv=tmpv->next;913 }914 915 e->tri_cnt=0;916 while (tmpt!=&e->tri_head) {917 MemCpy(dst,&tmpt->start,offset(CMeshEdTri.end)-offset(CMeshEdTri.start));918 dst+=offset(CMeshEdTri.end)-offset(CMeshEdTri.start);919 tmpt=tmpt->next;920 }921 if (_size) *_size=size;922 return res;923}924 925U0 MeshCleanUp(CMeshFrame *e)926{927 QueDel(&e->vertex_head,TRUE);928 QueDel(&e->tri_head,TRUE);929 Free(e->w2s);930 Free(e->s2w);931}932 933U0 MeshUpdateMenu(CMeshFrame *e)934{935 CMenuEntry *tmpse;936 if (tmpse=MenuEntryFind(Fs->cur_menu,"View/Grid"))937 tmpse->checked=ToBool(e->grid_on);938 if (tmpse=MenuEntryFind(Fs->cur_menu,"View/Vertex"))939 tmpse->checked=ToBool(e->vertex_on);940 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/PlaceVertex"))941 tmpse->checked=ToBool(e->ed_mode=='v');942 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/MoveVertex"))943 tmpse->checked=ToBool(e->ed_mode=='m');944 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/MoveVertexZ"))945 tmpse->checked=ToBool(e->ed_mode=='M');946 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/Triangle"))947 tmpse->checked=ToBool(e->ed_mode=='t');948 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/Polygon"))949 tmpse->checked=ToBool(e->ed_mode=='n');950 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/Fence"))951 tmpse->checked=ToBool(e->ed_mode=='f');952 if (tmpse=MenuEntryFind(Fs->cur_menu,"Mode/Prism"))953 tmpse->checked=ToBool(e->ed_mode=='p');954 if (tmpse=MenuEntryFind(Fs->cur_menu,"View/FlipY"))955 tmpse->checked=ToBool(e->flip_y);956}957 958I32 *SpriteMeshEd(I32 *head=NULL,I64 *_size=NULL,Bool flip_y=FALSE)959{/*Fmt for mesh:960{961I32 vertex_cnt;962I32 tri_cnt;963CD3I32 vertices[];964CMeshTri tris[];965}966 967If head points to a mesh, it will load it.968 969Returns a newly malloced mesh or NULL.970 971See ::/Demo/Graphics/SpritePlot3D.HC.972*/973 CCtrl *c=CtrlFindUnique(Fs,CTRLT_VIEWING_ANGLES);974 CViewAngles *s,*old_s;975 I64 i,msg_code,sel_mode,arg1,arg2,make_tri_vertex_num=0,x,y,z;976 CD3I32 p0a,p0b;977 CMeshEdVertex *va[3],*tmpv;978 Bool adjusting_z=FALSE,moving,save_and_exit;979 CMeshFrame e;980 981 if (c) {982 old_s=MAlloc(sizeof(CViewAngles));983 MemCpy(old_s,c->state,sizeof(CViewAngles));984 } else {985 c=ViewAnglesNew;986 old_s=NULL;987 }988 989 s=c->state;990 s->sx=0;991 s->sy=0;992 s->sz=0;993 s->cx=YELLOW;994 s->cy=RED;995 s->cz=GREEN;996 997 MenuPush(998 "File {"999 " Abort(,CH_SHIFT_ESC);"1000 " Exit(,CH_ESC);"1001 "}"1002 "Edit {"1003 " Delete(,,SC_DELETE);"1004 " DelLast(,CH_BACKSPACE);"1005 " Cut(,CH_CTRLX);"1006 " Copy(,CH_CTRLC);"1007 " Paste(,CH_CTRLV);"1008 " SelectAll(,'A');"1009 " UnSelectAll(,'U');"1010 " SelectRect(,'a');"1011 " UnSelectRect(,'u');"1012 " OrSelectRect(,'o');"1013 " JumpToZ(,'j');"1014 " ResetColor(,'C');"1015 " ReverseTri(,'r');"1016 "}"1017 "Mode {"1018 " PlaceVertex(,'v');"1019 " MoveVertex(,'m');"1020 " MoveVertexZ(,'M');"1021 " Triangle(,'t');"1022 " Polygon(,'n');"1023 " Fence(,'f');"1024 " Prism(,'p');"1025 "}"1026 "Settings {"1027 " Color(,'c');"1028 " Snap(,'s');"1029 "}"1030 "View {"1031 " ZoomIn(,'z');"1032 " ZoomOut(,'Z');"1033 " NullAngles(,'N');"1034 " FlipY(,'y');"1035 " Grid(,'g');"1036 " Vertex(,'V');"1037 " ToggleBorder(,CH_CTRLB);"1038 "}"1039 "Transforms {"1040 " Transform(,'T');"1041 " SwapXY(,'1');"1042 " SwapXZ(,'2');"1043 " SwapYZ(,'3');"1044 " InvertX(,'4');"1045 " InvertY(,'5');"1046 " InvertZ(,'6');"1047 " ReverseTri(,'R');"1048 "}");1049 1050 SettingsPush; //See SettingsPush1051 AutoComplete;1052 RegOneTimePopUp(ARf_MESH_ED,1053 "$GREEN$Right Mouse$FG$: Hold and move to shift cursor z\n"1054 "$GREEN$'j'$FG$: Jump cursor Z to nearest vertex's Z\n"1055 "$GREEN$'v'$FG$: Place Vertex Mode\n"1056 "$GREEN$'m'$FG$: Move Vertex Mode\n"1057 "$GREEN$'M'$FG$: Move Vertex Z\n"1058 "$GREEN$'t'$FG$: Form Triangle Mode\n"1059 "$GREEN$'n'$FG$: Polygon Mode\n"1060 "$GREEN$'f'$FG$: Fence Mode\n"1061 "$GREEN$'p'$FG$: Prism Mode\n"1062 "$GREEN$'c'$FG$: Set color\n"1063 "$GREEN$'s'$FG$: Set snap\n"1064 "\nSee menu at top of scrn for more.\n");1065 1066 Fs->win_inhibit=WIG_TASK_DFT|WIF_SELF_DOC-WIF_SELF_FOCUS-WIF_SELF_BORDER1067 -WIF_SELF_CTRLS-WIF_FOCUS_TASK_MENU-WIF_SELF_GRAB_SCROLL;1068 Fs->horz_scroll.pos=0;1069 Fs->vert_scroll.pos=0;1070 MeshInit(&e,flip_y);1071 if (head)1072 MeshLoad(&e,head);1073 FramePtrAdd("CMeshFrame",&e);1074 Fs->draw_it=&DrawIt;1075 MeshCurSnap(&e);1076 MeshRecalcCxCy(Fs,&e);1077 1078 try {//In case of <CTRL-ALT-c>1079 while (TRUE) {1080 MeshUpdateMenu(&e);1081 msg_code=GetMsg(&arg1,&arg2,1082 1<<MSG_MS_MOVE|1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1083 1<<MSG_MS_L_UP|1<<MSG_MS_R_DOWN|1<<MSG_MS_R_UP);1084me_restart:1085 switch (msg_code) {1086 case MSG_KEY_DOWN:1087 switch (arg1) {1088 case 0:1089 switch (arg2.u8[0]) {1090 case SC_DELETE:1091 if (arg2&SCF_SHIFT)1092 goto me_clip_cut;1093 else {1094 if (MeshSelCnt(&e))1095 MeshClipDel(&e);1096 else if (e.ed_mode!='t')1097 MeshVertexDel(&e,MeshVertexFindScrPt(&e,1098 ms.presnap.x-Fs->pix_left-Fs->scroll_x,1099 ms.presnap.y-Fs->pix_top-Fs->scroll_y));1100 MeshVertexSelAll(&e,FALSE);1101 MeshTriSelAll(&e,FALSE);1102 make_tri_vertex_num=0;1103 }1104 break;1105 case SC_INS:1106 if (arg2&SCF_CTRL)1107 goto me_clip_copy;1108 else if (arg2&SCF_SHIFT)1109 goto me_clip_paste;1110 }1111 break;1112 case CH_BACKSPACE:1113 switch (e.ed_mode) {1114 case 'n':1115 case 'f':1116 case 'p':1117 case 'v':1118 MeshVertexDel(&e,e.cur_vertex);1119 break;1120 case 't':1121 if (make_tri_vertex_num) {1122 MeshVertexSelAll(&e,FALSE);1123 MeshTriSelAll(&e,FALSE);1124 make_tri_vertex_num=0;1125 } else1126 MeshTriDel(&e,e.cur_tri);1127 break;1128 }1129 break;1130 case 'f':1131 case 'p':1132 e.thickness=PopUpGetI64("Thickness (%d):",e.thickness);1133 case 'n':1134 if (arg1=='n' || arg1=='p')1135 e.closed=TRUE;1136 else1137 e.closed=PopUpNoYes("Closed?\n");1138me_chain:1139 e.chain_pred=e.vertex_head.last;1140 case 't':1141 MeshVertexSelAll(&e,FALSE);1142 MeshTriSelAll(&e,FALSE);1143 case 'v':1144 case 'm':1145 case 'M':1146 adjusting_z=FALSE;1147 moving=FALSE;1148 e.ed_mode=arg1;1149 make_tri_vertex_num=0;1150 Snd;1151 break;1152 case 'T':1153 MeshTransformSel(&e);1154 break;1155 case 'A':1156 MeshTriSelAll(&e,TRUE);1157 if (e.ed_mode!='t')1158 MeshVertexSelAll(&e,TRUE);1159 else1160 MeshVertexSelAll(&e,FALSE);1161 make_tri_vertex_num=0;1162 break;1163 case 'U':1164 MeshTriSelAll(&e,FALSE);1165 MeshVertexSelAll(&e,FALSE);1166 make_tri_vertex_num=0;1167 break;1168 case 'a':1169 case 'u':1170 case 'o':1171 if (arg1=='a')1172 sel_mode=SEL_MESH_EQU;1173 else if (arg1=='u')1174 sel_mode=SEL_MESH_AND;1175 else1176 sel_mode=SEL_MESH_OR;1177 if ((msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1178 1<<MSG_MS_L_UP|1<<MSG_MS_R_DOWN|1<<MSG_MS_R_UP))1179 !=MSG_MS_L_DOWN) {1180 Beep; Beep;1181 goto me_restart;1182 }1183 e.x1=arg1; e.y1=arg2;1184 e.x2=arg1; e.y2=arg2;1185 e.sel_rect=TRUE;1186 while (TRUE) {1187 msg_code=GetMsg(&arg1,&arg2,1<<MSG_MS_MOVE|1<<MSG_KEY_DOWN|1188 1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|1<<MSG_MS_R_DOWN|1189 1<<MSG_MS_R_UP);1190 if (msg_code==MSG_MS_MOVE) {1191 e.x2=arg1; e.y2=arg2;1192 } else if (msg_code==MSG_MS_L_UP) {1193 e.x2=arg1; e.y2=arg2;1194 break;1195 } else {1196 e.sel_rect=FALSE;1197 Beep; Beep;1198 goto me_restart;1199 }1200 }