001 #ifndef PRIMITIVES 002 #define PRIMITIVES 21 003 #include "GarbageCollector"; 004 class CD6 { 005 F64 x,y,z; 006 F64 x2,y2,z2; 007 I64 color; 008 }; 009 class CFontMeshTmp { 010 I64 line_cnt,color; 011 F64 depth; 012 CD6 **to; 013 }; 014 CD6 **PrimitiveAllocFlat(I64 cnt) { 015 CD6 **ret=GCCAlloc((cnt+1)*8+cnt*sizeof(CD6)),**oret=ret,*flat; 016 flat=oret+cnt+1; 017 while(--cnt>=0) { 018 ret[cnt]=&flat[cnt]; 019 ret[cnt]->color=-1; 020 } 021 return oret; 022 } 023 #include "TrueType"; 024 U0 Plotty(CFontMeshTmp *tmp,F64 x,F64 y,F64 x2,F64 y2) { 025 I64 lc=tmp->line_cnt++; 026 CD6 *to=NULL; 027 if(tmp->to) { 028 to=tmp->to[lc]; 029 to->x=x,to->x2=x2; 030 to->y=y,to->y2=y2; 031 to->color=tmp->color; 032 to->z=0,to->z2=0; 033 } 034 lc=tmp->line_cnt++; 035 if(tmp->to) { 036 to=tmp->to[lc]; 037 to->color=tmp->color; 038 to->x=x,to->x2=x2; 039 to->y=y,to->y2=y2; 040 to->z=tmp->depth,to->z2=tmp->depth; 041 } 042 lc=tmp->line_cnt++; 043 if(tmp->to) { 044 to=tmp->to[lc]; 045 to->color=tmp->color; 046 to->x=x,to->x2=x; 047 to->y=y,to->y2=y; 048 to->z=0,to->z2=tmp->depth; 049 } 050 051 } 052 CD6 **PrimitiveText3D(U8 *str,F64 depth=10,F64 scale=16.,I64 color=YELLOW) { 053 I64 l=StrLen(str),i,j; 054 CFontMeshTmp tmp; 055 tmp.to=NULL; 056 tmp.depth=depth; 057 tmp.color=color; 058 CGlAdvance ga; 059 I64 x=0,max_y=0,y=0; 060 I64 lh=0; 061 I64 *widths=CAlloc(8*(StrOcc(str,'\n')+1)); 062 I64 line=0; 063 for(j=0;j!=2;++j) { 064 line=0; 065 tmp.line_cnt=0; 066 x=widths[0]; 067 for(i=0;i!=l;++i) { 068 ga=0; 069 if(str[i]!=' '&&str[i]!='\n') { 070 ga=TTF_RenderChr(x,y,,str[i],scale,&Plotty,&tmp); 071 x+=ga.x/2; //??? 072 lh=ga.y/2; 073 } else if(str[i]==' ') 074 x+=scale/4.; 075 else if(str[i]=='\n') { 076 y+=lh; 077 widths[line++]=-x/2; //Cetner Text 078 x=widths[line]; 079 } 080 max_y=MaxI64(max_y,lh+y); 081 } 082 if(j==0) { 083 tmp.to=PrimitiveAllocFlat(tmp.line_cnt); 084 widths[line]=-x/2; //Center TExt 085 y=-max_y/4; 086 } 087 } 088 Free(widths); 089 return tmp.to; 090 } 091 //Points towards Z 092 CD6 **PrimitiveCylinder3D(F64 rad,F64 depth,F64 interval=pi/8) { 093 I64 steps=(2*pi)/interval,total=steps*3,s; 094 CD6 **flat=PrimitiveAllocFlat(total),*cur,*cur2; 095 F64 a; 096 for(s=0;s!=steps;s++) { 097 cur=flat[s]; 098 a=interval*s; 099 cur->x=rad*Cos(a); 100 cur->y=rad*Sin(a); 101 cur->z=0; 102 cur->x2=rad*Cos(a+interval); 103 cur->y2=rad*Sin(a+interval); 104 cur->z2=0; 105 106 cur2=flat[s+steps]; 107 MemCpy(cur2,cur,sizeof(CD6)); 108 cur2->z=depth; 109 cur2->z2=depth; 110 111 cur2=flat[s+steps+steps]; 112 cur2->x=rad*Cos(a); 113 cur2->y=rad*Sin(a); 114 cur2->z=0; 115 cur2->x2=cur2->x; 116 cur2->y2=cur2->y; 117 cur2->z2=depth; 118 } 119 return flat; 120 } 121 122 CD6 **PrimitiveSphere3D(F64 rad,F64 interval=pi/8) { 123 I64 steps=(2*pi)/interval,total=steps*steps*2; 124 I64 s1,s2; 125 I64 mat[16]; 126 I64 x,y,z; 127 CD6 **flat=PrimitiveAllocFlat(total),*cur,*cur2; 128 for(s1=0;s1<steps;++s1) { 129 for(s2=0;s2<steps;++s2) { 130 Mat4x4IdentEqu(mat); 131 x=rad,y=0;z=0; 132 Mat4x4RotZ(mat,s1*interval); 133 Mat4x4RotY(mat,s2*interval); 134 Mat4x4MulXYZ(mat,&x,&y,&z); 135 cur=flat[s2+s1*steps*2]; 136 cur->x=x; 137 cur->y=y; 138 cur->z=z; 139 } 140 for(s2=0;s2<steps;s2++) { 141 cur=flat[s2+s1*steps*2]; 142 cur2=flat[(1+s2)%steps+s1*steps*2]; 143 cur->x2=cur2->x; 144 cur->y2=cur2->y; 145 cur->z2=cur2->z; 146 } 147 for(s2=0;s2<steps;++s2) { 148 Mat4x4IdentEqu(mat); 149 x=rad,y=0;z=0; 150 Mat4x4RotZ(mat,s2*interval); 151 Mat4x4RotY(mat,s1*interval); 152 Mat4x4MulXYZ(mat,&x,&y,&z); 153 cur=flat[s2+s1*steps*2+steps]; 154 cur->x=x; 155 cur->y=y; 156 cur->z=z; 157 } 158 for(s2=0;s2<steps;s2++) { 159 cur=flat[s2+s1*steps*2+steps]; 160 cur2=flat[(1+s2)%steps+s1*steps*2+steps]; 161 cur->x2=cur2->x; 162 cur->y2=cur2->y; 163 cur->z2=cur2->z; 164 } 165 } 166 return flat; 167 } 168 169 CD6 **PrimitiveCone3D(F64 rad,F64 height,F64 interval=pi/4) { 170 I64 steps=2*pi/interval,total=steps*2; 171 I64 s; 172 F64 a; 173 CD6 **flat=PrimitiveAllocFlat(total),*cur; 174 for(s=0;s<steps;++s) { 175 a=s*interval; 176 cur=flat[s*2]; 177 cur->x=Cos(a)*rad; 178 cur->y=Sin(a)*rad; 179 cur->z=0; 180 cur->x2=Cos(a+interval)*rad; 181 cur->y2=Sin(a+interval)*rad; 182 cur->z2=0; 183 184 cur=flat[s*2+1]; 185 cur->x2=0; 186 cur->y2=0; 187 cur->z2=height; 188 189 cur->x=Cos(a)*rad; 190 cur->y=Sin(a)*rad; 191 cur->z=0; 192 } 193 return flat; 194 } 195 196 CD6 **PrimitiveRect3D(F64 w,F64 h,F64 depth) { 197 I64 idx; 198 CD6 **flat=PrimitiveAllocFlat(8+4); 199 CD6 *cur,*cur2; 200 201 cur=flat[0]; 202 cur->x=-w/2; 203 cur->y=-h/2; 204 cur->z=-depth/2; 205 cur=flat[1]; 206 cur->x=w/2; 207 cur->y=-h/2; 208 cur->z=-depth/2; 209 cur=flat[2]; 210 cur->x=w/2; 211 cur->y=h/2; 212 cur->z=-depth/2; 213 cur=flat[3]; 214 cur->x=-w/2; 215 cur->y=h/2; 216 cur->z=-depth/2; 217 218 for(idx=0;idx!=4;idx++) { 219 cur=flat[idx]; 220 MemCpy(&flat[(1+idx)&3]->x2,&cur->x,sizeof(CD3)); 221 } 222 223 cur=flat[4]; 224 cur->x=-w/2; 225 cur->y=-h/2; 226 cur->z=depth/2; 227 cur=flat[5]; 228 cur->x=w/2; 229 cur->y=-h/2; 230 cur->z=depth/2; 231 cur=flat[6]; 232 cur->x=w/2; 233 cur->y=h/2; 234 cur->z=depth/2; 235 cur=flat[7]; 236 cur->x=-w/2; 237 cur->y=h/2; 238 cur->z=depth/2; 239 240 for(idx=0;idx!=4;idx++) { 241 cur=flat[4+idx]; 242 MemCpy(&flat[4+(idx+1)&3]->x2,&cur->x,sizeof(CD3)); 243 } 244 245 for(idx=0;idx!=4;idx++) { 246 cur=flat[idx]; 247 cur2=flat[idx+4]; 248 MemCpy(&flat[idx+8]->x,&cur->x,sizeof(CD3)); 249 MemCpy(&flat[idx+8]->x2,&cur2->x,sizeof(CD3)); 250 } 251 return flat; 252 } 253 Bool ClipStep(CD3I64 *a,I64 x,I64 y,I64 z) { 254 CDC *dc=a->z; 255 CD3I64 *to=a->y; 256 I64 ox=x,oy=y,oz=z; 257 if(!(dc->flags&DCF_TRANSFORMATION)) { 258 if(z<=0) 259 goto fail; 260 } else { 261 dc->transform(dc,&x,&y,&z); 262 if(z<=0) 263 goto fail; 264 } 265 to->x=ox; 266 to->y=oy; 267 to->z=oz; 268 return TRUE; 269 fail:; 270 return FALSE; 271 } 272 class CMeshClipTmp { 273 CD3 *xyz; 274 CD3 *whd; 275 CD3 end; 276 }; 277 Bool MeshClipStep(CMeshClipTmp *t,I64 x,I64 y,I64 z) { 278 CD3 *xyz=t->xyz; 279 CD3 *whd=t->whd; 280 if(0.<=x-xyz->x<whd->x) 281 if(0.<=y-xyz->y<whd->y) 282 if(0.<=z-xyz->z<whd->z) { 283 return FALSE; 284 } 285 t->end.x=x,t->end.y=y,t->end.z=z; 286 return TRUE; 287 } 288 CD6 *ClipCD6Mesh(CD6 **mesh,CD3 *xyz,CD3 *whd) { 289 CD6 *cur,**ret,*to; 290 CMeshClipTmp tmp; 291 tmp.xyz=xyz,tmp.whd=whd; 292 Bool front,end; 293 I64 total=0,idx=0; 294 while(cur=mesh[idx]) { 295 front=MeshClipStep(&tmp,cur->x,cur->y,cur->z); 296 end=MeshClipStep(&tmp,cur->x2,cur->y2,cur->z2); 297 if(!front&&!end) { 298 } else 299 ++total; 300 ++idx; 301 } 302 ret=PrimitiveAllocFlat(total); 303 idx=0,total=0; 304 while(cur=mesh[idx]) { 305 front=MeshClipStep(&tmp,cur->x,cur->y,cur->z); 306 end=MeshClipStep(&tmp,cur->x2,cur->y2,cur->z2); 307 if(front&&end) { 308 to=ret[total++]; 309 MemCpy(to,cur,sizeof CD6); 310 } else if(front&&!end) { 311 Line(&tmp,cur->x,cur->y,cur->z,cur->x2,cur->y2,cur->z2,&MeshClipStep); 312 to=ret[total++]; 313 MemCpy(to,cur,sizeof CD6); 314 to->x=tmp.end.x; 315 to->y=tmp.end.y; 316 to->z=tmp.end.z; 317 } else if(!front&&end) { 318 Line(&tmp,cur->x2,cur->y2,cur->z2,cur->x,cur->y,cur->z,&MeshClipStep); 319 to=ret[total++]; 320 MemCpy(to,cur,sizeof CD6); 321 to->x2=tmp.end.x; 322 to->y2=tmp.end.y; 323 to->z2=tmp.end.z; 324 } 325 ++idx; 326 } 327 return ret; 328 } 329 U0 ClipLineDumb(CD3I64 *a,CD3I64 *b,CDC *dumb) { 330 CD3I64 pair; 331 I64 step=5; 332 pair.x=a; 333 pair.y=b; 334 pair.z=dumb; 335 Line(&pair,a->x,a->y,a->z,b->x,b->y,b->z,&ClipStep,step); 336 pair.x=b; 337 pair.y=a; 338 Line(&pair,b->x,b->y,b->z,a->x,a->y,a->z,&ClipStep,step); 339 340 } 341 CD6 *CD6NewTransform(CD6 **a,I64 *mat) { 342 I64 la,r=0; 343 I64 x,y,z; 344 for(la=0;a[la];++la); 345 CD6 **flat=PrimitiveAllocFlat(la),*dst,*src; 346 for(la=0;src=a[la];++la) { 347 dst=flat[r++]; 348 MemCpy(dst,src,sizeof(CD6)); 349 if(mat) { 350 x=dst->x,y=dst->y,z=dst->z; 351 Mat4x4MulXYZ(mat,&x,&y,&z); 352 dst->x=x,dst->y=y,dst->z=z; 353 354 x=dst->x2,y=dst->y2,z=dst->z2; 355 Mat4x4MulXYZ(mat,&x,&y,&z); 356 dst->x2=x,dst->y2=y,dst->z2=z; 357 } 358 } 359 return flat; 360 } 361 U0 CD6SetColor(CD6 **a,I64 color) { 362 while(*a) { 363 (*a)->color=color; 364 ++a; 365 } 366 } 367 CD6 *CD6Merge(CD6 **a,CD6 **b,I64 *bmat) { 368 I64 la,lb,r=0; 369 I64 x,y,z; 370 for(la=0;a[la];++la); 371 for(lb=0;b[lb];++lb); 372 CD6 **flat=PrimitiveAllocFlat(la+lb),*dst,*src; 373 for(la=0;src=a[la];++la) { 374 dst=flat[r++]; 375 MemCpy(dst,src,sizeof(CD6)); 376 } 377 for(la=0;src=b[la];++la) { 378 dst=flat[r++]; 379 MemCpy(dst,src,sizeof(CD6)); 380 if(bmat) { 381 x=dst->x,y=dst->y,z=dst->z; 382 Mat4x4MulXYZ(bmat,&x,&y,&z); 383 dst->x=x,dst->y=y,dst->z=z; 384 385 x=dst->x2,y=dst->y2,z=dst->z2; 386 Mat4x4MulXYZ(bmat,&x,&y,&z); 387 dst->x2=x,dst->y2=y,dst->z2=z; 388 } 389 } 390 return flat; 391 } 392 U0 CD6Draw(CD6 **flat,F64 x,F64 y,F64 z,CDC *dc,I64 *obj_mat=NULL) { 393 I64 idx; 394 CD3I64 new,new2,dumb,dumb2; 395 CD6 *have; 396 I64 ocolor=dc->color; 397 for(idx=0;have=flat[idx];idx++) { 398 have=flat[idx]; 399 if(have->color<0) 400 dc->color=ocolor; 401 else 402 dc->color=have->color; 403 new.x=have->x+x; 404 new.y=have->y+y; 405 new.z=have->z+z; 406 new2.x=have->x2+x; 407 new2.y=have->y2+y; 408 new2.z=have->z2+z; 409 if(obj_mat) { 410 Mat4x4MulXYZ(obj_mat,&new.x,&new.y,&new.z); 411 Mat4x4MulXYZ(obj_mat,&new2.x,&new2.y,&new2.z); 412 } 413 //Check if point(s) are behind camera 414 if(dc->flags&DCF_TRANSFORMATION) { 415 dumb.x=new.x; 416 dumb.y=new.y; 417 dumb.z=new.z; 418 dc->transform(dc,&dumb.x,&dumb.y,&dumb.z); 419 dumb2.x=new2.x; 420 dumb2.y=new2.y; 421 dumb2.z=new2.z; 422 dc->transform(dc,&dumb2.x,&dumb2.y,&dumb2.z); 423 if(dumb.z<=0&&dumb2.z<=0) 424 goto skip; 425 else if(dumb.z<=0||dumb2.z<=0) 426 ClipLineDumb(&new,&new2,dc); 427 } 428 GrLine3(dc,new.x,new.y,new.z,new2.x,new2.y,new2.z); 429 skip:; 430 } 431 dc->color=ocolor; 432 } 433 F64 CD6Width(CD6 **flat) { 434 CD6 *cur; 435 F64 max=I32_MIN,min=I32_MAX; 436 I64 idx; 437 for(idx=0;cur=flat[idx];++idx) { 438 max=Max(cur->x,max); 439 min=Min(cur->x,min); 440 } 441 if(min>max) 442 return 0; 443 return max-min; 444 } 445 F64 CD6Depth(CD6 **flat) { 446 CD6 *cur; 447 F64 max=I32_MIN,min=I32_MAX; 448 I64 idx; 449 for(idx=0;cur=flat[idx];++idx) { 450 max=Max(cur->z,max); 451 min=Min(cur->z,min); 452 } 453 if(min>max) 454 return 0; 455 return max-min; 456 } 457 F64 CD6Height(CD6 **flat) { 458 CD6 *cur; 459 F64 max=I32_MIN,min=I32_MAX; 460 I64 idx; 461 for(idx=0;cur=flat[idx];++idx) { 462 max=Max(cur->y,max); 463 min=Min(cur->y,min); 464 } 465 if(min>max) 466 return 0; 467 return max-min; 468 } 469 U0 WorldTransform(CDC *dc,I64 *x,I64 *y,I64 *z) 470 { 471 I64 zz; 472 Mat4x4MulXYZ(dc->r,x,y,z); 473 zz=*z; 474 if (zz>0) { 475 *x = dc->x + *x * 200./zz; //Foreshortening 476 *y = dc->y + *y * 200./zz; 477 } else { 478 *x = dc->x + *x; 479 *y = dc->y + *y; 480 } 481 } 482 //Accounts for translation 21 483 U0 Mat4x4PointTo(I64 *mat,F64 x,F64 y,F64 z) { 484 F64 ox,oy,oz,d; 485 F64 angle,angle2; 486 ox=mat[0*4+3]/ToF64(1<<32); 487 oy=mat[1*4+3]/ToF64(1<<32); 488 oz=mat[2*4+3]/ToF64(1<<32); 489 x=x-ox; 490 y=y-oy; 491 z=z-oz; 492 493 angle=Arg(z,x); 494 angle2=Arg(Sqrt(z*z+x*x),-y); //Why negative? 495 Mat4x4RotX(mat,angle2); 496 Mat4x4RotY(mat,angle); 497 498 Mat4x4TranslationEqu(mat,ox,oy,oz); 499 } 500 #if __CMD_LINE__ 501 CD3 void_xyz={-50,-50,-50},void_whd={50,200,100}; 502 I64 mat[16]; 503 Mat4x4IdentEqu(mat); 504 Mat4x4RotY(mat,pi/4); 505 Mat4x4TranslationEqu(mat,-50,50,10); 506 CDC *dumb=DCNew(300,300); 507 DCFill(dumb,LTCYAN); 508 dumb->x=150; 509 dumb->y=150; 510 dumb->color=RED; 511 dumb->flags|=DCF_TRANSFORMATION; 512 dumb->transform=&WorldTransform; 513 dumb->thick=2; 514 Mat4x4IdentEqu(dumb->r); 515 Mat4x4TranslationEqu(dumb->r,0,0,200); 516 //CD6Draw(PrimitiveRect3D(50,50,50),1,0,150,dumb); 517 CD6Draw(PrimitiveRect3D(50,50,50),00,0,000,dumb,mat); 518 CD6Draw(PrimitiveSphere3D(25),00,0,000,dumb,mat); 519 Mat4x4IdentEqu(mat); 520 Mat4x4TranslationEqu(mat,120,-75,50); 521 Mat4x4PointTo(mat,-50,50,10); 522 CD6Draw(PrimitiveCone3D(25,100),00,0,000,dumb,mat); 523 Mat4x4IdentEqu(mat); 524 Mat4x4TranslationEqu(mat,-170,-150,500); 525 Mat4x4PointTo(mat,-50,50,10); 526 CD6Draw(PrimitiveCone3D(25,100),00,0,000,dumb,mat); 527 Mat4x4IdentEqu(mat); 528 Mat4x4RotY(mat,pi/3); 529 CD6Draw(PrimitiveCylinder3D(100,150,pi/8),0,0,0,dumb,mat); 530 Mat4x4IdentEqu(mat); 531 CD6Draw(ClipCD6Mesh(PrimitiveText3D("Holy\nShit\nshit\nis\ntasty",10,50,RED),&void_xyz,&void_whd),0,0,0,dumb,mat); 532 GrBlot(,0,0,dumb); 533 PressAKey; 534 DCFill; 535 #endif 536 #endif