home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / vexsrc / makeobj.cpp < prev    next >
C/C++ Source or Header  |  1995-03-29  |  13KB  |  607 lines

  1. /*****************************************************************************
  2.                                   ATTENTION!
  3.                            this source is VOTEWARE,
  4.               you may only use it to the conditions listed below:
  5.  
  6.   -You may modify it, or use parts of it in your own source as long as
  7.     this header stays on top of all files containing this source.
  8.   -You must give proper credit to the author, Niklas Beisert / pascal.
  9.   -You may not use it in commercial productions without the written
  10.     permission of the author.
  11.   -AND MOST IMPORTANT: you have to buy an Assembly '94 CD-ROM
  12.     by Sound Solutions (if you don't have it already) and vote for VEX-InTrO
  13.     in the PC-64k-Intro-Compo! (if you have already sent your voting card,
  14.     buy another one and fill it out CORRECTLY!!!)
  15. *****************************************************************************/
  16.  
  17.  
  18.  
  19. // compile an object, make a bsp-tree (binary space partitioning tree)
  20.  
  21. #include <math.h>
  22. #include <dir.h>
  23. #include <fstream.h>
  24. #include <io.h>
  25. #include <fcntl.h>
  26. #include <sys\stat.h>
  27.  
  28. #define MAXVERT 10
  29.  
  30. struct plane
  31. {
  32.   short b;
  33.   short m;
  34.   short f;
  35.   unsigned char opt;
  36.   unsigned char disp;
  37.   unsigned char c0;
  38.   unsigned char cn;
  39.   short textnum;
  40.   short mid;
  41.   short norm;
  42.   short vertnum;
  43.   short v[MAXVERT+1];
  44.   union
  45.   {
  46.     struct
  47.     {
  48.       short n;
  49.       unsigned char c0;
  50.       unsigned char cn;
  51.     } col[MAXVERT+1];
  52.     struct
  53.     {
  54.       unsigned short x;
  55.       unsigned short y;
  56.     } tex[MAXVERT+1];
  57.   };
  58. };
  59.  
  60. #define OPT_FRONT 1
  61. #define OPT_BACK 2
  62.  
  63. #define DISP_NORM 0
  64. #define DISP_SHADED 1
  65. #define DISP_SMOOTH 1
  66. #define DISP_ROUNDED 2
  67. #define DISP_MIRROR 3
  68. #define DISP_ORPUT 4
  69. #define DISP_TEXT 5
  70. #define DISP_TEXTX 6
  71.  
  72. #define MIN 0.00001
  73.  
  74. struct vector
  75. {
  76.   double v[3];
  77.   vector() { v[0]=v[1]=v[2]=0; }
  78.   double& operator [](int i) { return v[i]; }
  79.   double operator [](int i) const { return v[i]; }
  80. };
  81.  
  82. int operator ==(const vector &v1, const vector &v2)
  83. {
  84.   if (fabs(v1[0]-v2[0])>MIN)
  85.     return 0;
  86.   if (fabs(v1[1]-v2[1])>MIN)
  87.     return 0;
  88.   if (fabs(v1[2]-v2[2])>MIN)
  89.     return 0;
  90.   return 1;
  91. }
  92.  
  93. double operator *(const vector &v1, const vector &v2)
  94. {
  95.   return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
  96. }
  97.  
  98. vector operator *(const vector &v, double d)
  99. {
  100.   vector vr=v;
  101.   vr[0]*=d;
  102.   vr[1]*=d;
  103.   vr[2]*=d;
  104.   return vr;
  105. }
  106.  
  107. vector& operator /=(vector &v, double d)
  108. {
  109.   v[0]/=d;
  110.   v[1]/=d;
  111.   v[2]/=d;
  112.   return v;
  113. }
  114.  
  115. vector operator +(const vector &v1, const vector &v2)
  116. {
  117.   vector v;
  118.   v[0]=v1[0]+v2[0];
  119.   v[1]=v1[1]+v2[1];
  120.   v[2]=v1[2]+v2[2];
  121.   return v;
  122. }
  123.  
  124. vector operator -(const vector &v1, const vector &v2)
  125. {
  126.   vector v;
  127.   v[0]=v1[0]-v2[0];
  128.   v[1]=v1[1]-v2[1];
  129.   v[2]=v1[2]-v2[2];
  130.   return v;
  131. }
  132.  
  133. vector& operator +=(vector &v1, const vector &v2)
  134. {
  135.   v1[0]+=v2[0];
  136.   v1[1]+=v2[1];
  137.   v1[2]+=v2[2];
  138.   return v1;
  139. }
  140.  
  141. vector norm(const vector& v)
  142. {
  143.   return vector(v)/=sqrt(v*v);
  144. }
  145.  
  146. vector vecxmul(const vector &v1, const vector &v2)
  147. {
  148.   vector v;
  149.   v[0]=v1[1]*v2[2]-v1[2]*v2[1];
  150.   v[1]=v1[2]*v2[0]-v1[0]*v2[2];
  151.   v[2]=v1[0]*v2[1]-v1[1]*v2[0];
  152.   return v;
  153. }
  154.  
  155. #define MAXVERTS 256
  156. #define MAXNORMS 256
  157. #define MAXPLANES 256
  158.  
  159. vector* verts;
  160. vector* norms;
  161. plane* planes;
  162. int planenum;
  163. int vertnum;
  164. int normnum;
  165.  
  166. // adds a point and checks for equal points
  167. int addvert(const vector& v)
  168. {
  169.   for (int j=0; j<vertnum; j++)
  170.     if (v==verts[j])
  171.       return j;
  172.   verts[vertnum]=v;
  173.   return vertnum++;
  174. }
  175.  
  176. // adds a vector and checks for equal points
  177. int addnorm(const vector& v)
  178. {
  179.   vector v2=norm(v);
  180.   for (int j=0; j<normnum; j++)
  181.     if (v2==norms[j])
  182.       return j;
  183.   norms[normnum]=v2;
  184.   return normnum++;
  185. }
  186.  
  187. void swapplanes(plane& p1, plane& p2)
  188. {
  189.   if (&p1==&p2)
  190.     return;
  191.   plane p;
  192.   memmove(&p, &p1, sizeof (plane));
  193.   memmove(&p1, &p2, sizeof (plane));
  194.   memmove(&p2, &p, sizeof (plane));
  195. }
  196.  
  197. // cuts the plane p2 by plane p1 into plane p2 and p3
  198. void splitplane(const plane& p1, plane& p2, plane& p3)
  199. {
  200.   int n=p2.vertnum;
  201.   vector& v=verts[p1.v[0]];
  202.   vector& nr=norms[p1.norm];
  203.   int ff, fb;
  204.   int l=((verts[p2.v[n-1]]-v)*nr)<-MIN;
  205.   for (int i=0; i<n; i++)
  206.   {
  207.     int c=((verts[p2.v[i]]-v)*nr)<-MIN;
  208.     if (c^l)
  209.       if (c)
  210.         fb=i;
  211.       else
  212.         ff=i;
  213.     l=c;
  214.   }
  215.   plane po=p2;
  216.   p3=po;
  217.   vector& v1=verts[po.v[fb]];
  218.   vector& v2=verts[po.v[(fb-1+n)%n]];
  219.   vector& v3=verts[po.v[ff]];
  220.   vector& v4=verts[po.v[(ff-1+n)%n]];
  221.   double a=(((v-v1)*nr)/((v2-v1)*nr));
  222.   double b=(((v-v3)*nr)/((v4-v3)*nr));
  223.  
  224.   int va=addvert(v1*(1-a)+v2*a);
  225.   int vb=addvert(v3*(1-b)+v4*b);
  226.  
  227.   p2.vertnum=(ff-fb+n)%n;
  228.   for (i=0; i<p2.vertnum; i++)
  229.     p2.v[i]=po.v[(fb+i)%n];
  230.   p2.v[p2.vertnum++]=vb;
  231.   p2.v[p2.vertnum++]=va;
  232.  
  233.   p3.vertnum=(fb-ff+n)%n;
  234.   for (i=0; i<p3.vertnum; i++)
  235.     p3.v[i]=po.v[(ff+i)%n];
  236.   p3.v[p3.vertnum++]=va;
  237.   p3.v[p3.vertnum++]=vb;
  238.  
  239.   switch (po.disp)
  240.   {
  241.   case DISP_SHADED:
  242.   {
  243.     int na=addnorm(norms[po.v[fb]]*(1-a)+norms[po.v[(fb-1+n)%n]]*a);
  244.     unsigned char c0a=po.col[fb].c0*(1-a)+po.col[(fb-1+n)%n].c0*a;
  245.     unsigned char cna=po.col[fb].cn*(1-a)+po.col[(fb-1+n)%n].cn*a;
  246.     int nb=addnorm(norms[po.v[ff]]*(1-b)+norms[po.v[(ff-1+n)%n]]*b);
  247.     unsigned char c0b=po.col[ff].c0*(1-b)+po.col[(ff-1+n)%n].c0*b;
  248.     unsigned char cnb=po.col[ff].cn*(1-b)+po.col[(ff-1+n)%n].cn*b;
  249.  
  250.     for (i=0; i<(p2.vertnum-2); i++)
  251.     {
  252.       p2.col[i].n=po.col[(fb+i)%n].n;
  253.       p2.col[i].c0=po.col[(fb+i)%n].c0;
  254.       p2.col[i].cn=po.col[(fb+i)%n].cn;
  255.     }
  256.     p2.col[i].n=nb;
  257.     p2.col[i].c0=c0b;
  258.     p2.col[i++].cn=cnb;
  259.     p2.col[i].n=na;
  260.     p2.col[i].c0=c0a;
  261.     p2.col[i].cn=cna;
  262.  
  263.     for (i=0; i<(p3.vertnum-2); i++)
  264.     {
  265.       p3.col[i].n=po.col[(ff+i)%n].n;
  266.       p3.col[i].c0=po.col[(ff+i)%n].c0;
  267.       p3.col[i].cn=po.col[(ff+i)%n].cn;
  268.     }
  269.     p3.col[i].n=na;
  270.     p3.col[i].c0=c0a;
  271.     p3.col[i++].cn=cna;
  272.     p3.col[i].n=nb;
  273.     p3.col[i].c0=c0b;
  274.     p3.col[i].cn=cnb;
  275.     break;
  276.   }
  277.   case DISP_TEXT:
  278.   case DISP_TEXTX:
  279.   {
  280.     short txa=po.tex[fb].x*(1-a)+po.tex[(fb-1+n)%n].x*a;
  281.     short tya=po.tex[fb].y*(1-a)+po.tex[(fb-1+n)%n].y*a;
  282.     short txb=po.tex[ff].x*(1-b)+po.tex[(ff-1+n)%n].x*b;
  283.     short tyb=po.tex[ff].y*(1-b)+po.tex[(ff-1+n)%n].y*b;
  284.  
  285.     for (i=0; i<(p2.vertnum-2); i++)
  286.     {
  287.       p2.tex[i].x=po.tex[(fb+i)%n].x;
  288.       p2.tex[i].y=po.tex[(fb+i)%n].y;
  289.     }
  290.     p2.tex[i].x=txb;
  291.     p2.tex[i++].y=tyb;
  292.     p2.tex[i].x=txa;
  293.     p2.tex[i].y=tya;
  294.  
  295.     for (i=0; i<(p3.vertnum-2); i++)
  296.     {
  297.       p3.tex[i].x=po.tex[(ff+i)%n].x;
  298.       p3.tex[i].y=po.tex[(ff+i)%n].y;
  299.     }
  300.     p3.tex[i].x=txa;
  301.     p3.tex[i++].y=tya;
  302.     p3.tex[i].x=txb;
  303.     p3.tex[i].y=tyb;
  304.     break;
  305.   }
  306.   }
  307. }
  308.  
  309. // is plane p2 before, behind or on both sides of plane p1
  310. int testplane(const plane& p1, const plane& p2)
  311. {
  312.   int r=0;
  313.   int n=p2.vertnum;
  314.   vector& v=verts[p1.v[0]];
  315.   vector& nr=norms[p1.norm];
  316.   for (int j=0; (j<n)&&(r!=3); j++)
  317.   {
  318.     double x=(verts[p2.v[j]]-v)*nr;
  319.     if (x<-MIN)
  320.       r|=1;
  321.     if (x>MIN)
  322.       r|=2;
  323.   }
  324.   return r;
  325. }
  326.  
  327. int checksplit(int p, int s, int e)
  328. {
  329.   for (int i=s; i<e; i++)
  330.     if (testplane(planes[p], planes[i])==3)
  331.       return 1;
  332.   return 0;
  333. }
  334.  
  335. // make a bsp tree from planes s to e recursively
  336. int splitplanes(int s, int e)
  337. {
  338.   planes[s].m=-1;
  339.   for (int i=s; i<e; i++)
  340.     if (!checksplit(i, s, e))
  341.       break;
  342.   if (i!=e)
  343.     swapplanes(planes[i], planes[s]);
  344.   int splits=0;
  345.   int ff=s+1;
  346.   for (i=s+1; i<(e+splits); i++)
  347.   {
  348.     int r=testplane(planes[s], planes[i]);
  349.     if (r==3)
  350.     {
  351.       swapplanes(planes[e+splits], planes[planenum++]);
  352.       splitplane(planes[s], planes[i], planes[e+splits]);
  353.       swapplanes(planes[i], planes[ff+splits++]);
  354.     }
  355.     if (!(r&2))
  356.       swapplanes(planes[i], planes[splits+ff++]);
  357.   }
  358.   if ((ff+splits)!=(s+1))
  359.   {
  360.     planes[s].b=s+1;
  361.     splits+=splitplanes(s+1, ff+splits);
  362.   }
  363.   else
  364.     planes[s].b=-1;
  365.   if (ff!=e)
  366.   {
  367.     planes[s].f=ff+splits;
  368.     splits+=splitplanes(ff+splits, e+splits);
  369.   }
  370.   else
  371.     planes[s].f=-1;
  372.   return splits;
  373. }
  374.  
  375. int readvert(istream& s)
  376. {
  377.   char c;
  378.   s >> c;
  379.   if (c=='<')
  380.   {
  381.     vector v;
  382.     s >> v[0] >> v[1] >> v[2];
  383.     s >> c;
  384.     return addvert(v);
  385.   }
  386.   else
  387.   {
  388.     s.putback(c);
  389.     int i;
  390.     s >> i;
  391.     return i;
  392.   }
  393. }
  394.  
  395. int readnorm(istream& s)
  396. {
  397.   char c;
  398.   s >> c;
  399.   if (c=='<')
  400.   {
  401.     vector v;
  402.     s >> v[0] >> v[1] >> v[2];
  403.     s >> c;
  404.     return addnorm(v);
  405.   }
  406.   else
  407.   {
  408.     s.putback(c);
  409.     int i;
  410.     s >> i;
  411.     return i;
  412.   }
  413. }
  414.  
  415. void main(int argn, char** argv)
  416. {
  417.   if (argn!=2)
  418.     return;
  419.  
  420.   verts=new vector[MAXVERTS];
  421.   norms=new vector[MAXNORMS];
  422.   planes=new plane[MAXPLANES];
  423.   if (!verts||!norms||!planes)
  424.     return;
  425.  
  426. // read
  427.  
  428.   ifstream ifile(argv[1]);
  429.   if (!ifile)
  430.     return;
  431.  
  432.   ifile >> vertnum;
  433.   for (int i=0; i<vertnum; i++)
  434.     for (int j=0; j<3; j++)
  435.       ifile >> verts[i][j];
  436.  
  437.   ifile >> normnum;
  438.   for (i=0; i<normnum; i++)
  439.     for (int j=0; j<3; j++)
  440.       ifile >> norms[i][j];
  441.  
  442.   ifile >> planenum;
  443.   for (i=0; i<planenum; i++)
  444.   {
  445.     plane &p=planes[i];
  446.     for (int j=0; j<MAXVERT; j++)
  447.     {
  448.       p.v[j]=-1;
  449.       p.col[j].n=-1;
  450.     }
  451.     planes[i].mid=-1;
  452.     int x;
  453.     ifile >> x;
  454.     p.opt=x;
  455.     ifile >> x;
  456.     p.disp=x;
  457.     ifile >> x;
  458.     p.c0=x;
  459.     ifile >> x;
  460.     p.cn=x;
  461.     if (p.opt&0x80)
  462.       p.mid=readvert(ifile);
  463.     short n;
  464.     ifile >> n;
  465.     p.vertnum=n;
  466.     for (j=0; j<n; j++)
  467.       p.v[j]=readvert(ifile);
  468.     p.norm=addnorm(vecxmul(verts[p.v[1]]-verts[p.v[0]], verts[p.v[2]]-verts[p.v[0]]));
  469.     if (!(p.opt&0x80))
  470.     {
  471.       if (p.disp==DISP_SMOOTH||p.disp==DISP_ROUNDED||p.disp==DISP_MIRROR||!p.cn)
  472.         p.mid=p.v[0];
  473.       else
  474.       {
  475.         vector v;
  476.         for (j=0; j<n; j++)
  477.           v+=verts[p.v[j]];
  478.         p.mid=addvert(v/=n);
  479.       }
  480.     }
  481.     p.opt&=~0x80;
  482.     switch(p.disp)
  483.     {
  484.     case DISP_SMOOTH:
  485.       for (j=0; j<n; j++)
  486.       {
  487.         p.col[j].n=p.norm;
  488.         p.col[j].c0=p.c0;
  489.         p.col[j].cn=p.cn;
  490.       }
  491.       p.disp=DISP_SHADED;
  492.       break;
  493.     case DISP_ROUNDED:
  494.       for (j=0; j<n; j++)
  495.       {
  496.         p.col[j].c0=p.c0;
  497.         p.col[j].cn=p.cn;
  498.       }
  499.       break;
  500.     case DISP_TEXT:
  501.     case DISP_TEXTX:
  502.       ifile >> p.textnum;
  503.       for (j=0; j<n; j++)
  504.       {
  505.         double tx, ty;
  506.         ifile >> tx >> ty;
  507.         p.tex[j].x=tx*65535;
  508.         p.tex[j].y=ty*65535;
  509.       }
  510.     }
  511.   }
  512.   ifile.close();
  513.  
  514. //calc
  515.  
  516.   for (i=0; i<planenum; i++)
  517.     if (planes[i].disp==DISP_ROUNDED)
  518.     {
  519.       for (int j=0; j<planes[i].vertnum; j++)
  520.       {
  521.         vector v;
  522.         for (int k=0; k<planenum; k++)
  523.           for (int l=0; l<planes[k].vertnum; l++)
  524.             if (planes[k].v[l]==planes[i].v[j])
  525.               v+=norms[planes[k].norm];
  526.         planes[i].col[j].n=addnorm(v);
  527.         planes[i].disp=DISP_SHADED;
  528.       }
  529.     }
  530.  
  531.   if (planenum)
  532.     splitplanes(0, planenum);
  533.  
  534.   double maxextent=0;
  535.   for (i=0; i<vertnum; i++)
  536.     if (verts[i]*verts[i]>maxextent)
  537.       maxextent=verts[i]*verts[i];
  538.   long maxext=sqrt(maxextent)*65536;
  539.  
  540. // write
  541.  
  542.   char path[MAXPATH];
  543.   char drive[MAXDRIVE];
  544.   char dir[MAXDIR];
  545.   char name[MAXFILE];
  546.   char ext[MAXEXT];
  547.  
  548.   fnsplit(argv[1], drive, dir, name, ext);
  549.   fnmerge(path, drive, dir, name, ".3do");
  550.  
  551.   int file=open(path, O_BINARY|O_WRONLY|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE);
  552.  
  553. //  write(file, "3do\x00", 4);
  554.  
  555.   write(file, &vertnum, 2);
  556.   write(file, &normnum, 2);
  557.   write(file, &planenum, 2);
  558.   write(file, &maxext, 4);
  559.  
  560.   for (i=0; i<vertnum; i++)
  561.     for (int j=0; j<3; j++)
  562.     {
  563.       long p=verts[i][j]*65536;
  564.       write(file, &p, 4);
  565.     }
  566.  
  567.   for (i=0; i<normnum; i++)
  568.     for (int j=0; j<3; j++)
  569.     {
  570.       long p=norms[i][j]*65536;
  571.       write(file, &p, 4);
  572.     }
  573.  
  574. //  int rootplane=planenum?0:-1;
  575. //  write(file, &rootplane, 2);
  576.  
  577.   for (i=0; i<planenum; i++)
  578.   {
  579.     write(file, &planes[i].b, 2);
  580.     write(file, &planes[i].m, 2);
  581.     write(file, &planes[i].f, 2);
  582.     write(file, &planes[i].opt, 1);
  583.     write(file, &planes[i].disp, 1);
  584.     write(file, &planes[i].c0, 1);
  585.     write(file, &planes[i].cn, 1);
  586.     write(file, &planes[i].mid, 2);
  587.     write(file, &planes[i].norm, 2);
  588.     write(file, &planes[i].vertnum, 2);
  589.     write(file, &planes[i].v, 2*planes[i].vertnum);
  590.     switch (planes[i].disp)
  591.     {
  592.     case DISP_SMOOTH:
  593.       write(file, &planes[i].col, 4*planes[i].vertnum);
  594.       break;
  595.     case DISP_TEXT:
  596.     case DISP_TEXTX:
  597.       write(file, &planes[i].textnum, 2);
  598.       write(file, &planes[i].tex, 4*planes[i].vertnum);
  599.       break;
  600.     }
  601.   }
  602.  
  603.   close(file);
  604.  
  605.   cout << argv[1] << " compiled: " << vertnum << " points, " << normnum << " norms, " << planenum << " planes.\n";
  606. }
  607.