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