home *** CD-ROM | disk | FTP | other *** search
/ 3D Games - Real-time Rend…ng & Software Technology / 3D Games - Real-time Rendering & Software Technology.iso / flysdk / util / max / expflybsp / scene_max.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-15  |  10.9 KB  |  521 lines

  1. #include "expflybsp.h"
  2. #include "../../../lib/Fly3D.h"
  3. #include "scene_max.h"
  4. #include "enum_scene.h"
  5.  
  6. #define SMALLF 0.001f
  7.  
  8. extern int lightradius,bspmode,planemode,maxdepth,savelog,cartoonlight;
  9.  
  10. void scene_max::build_bsptree()
  11. {
  12.     int i,j;
  13.  
  14.     bsp=new bsp_node_max;
  15.  
  16.     for( j=0,i=0;i<nfaces;i++ )
  17.         if (faces[i].d0>0)
  18.             {
  19.             faces[i].indx=1;
  20.             faces[i].d0=-vec_dot(*faces[i].vert[0],faces[i].normal);
  21.             }
  22.         else
  23.             {
  24.             faces[i].indx=0;
  25.             j++;
  26.             }
  27.  
  28.     static_mesh *o=new static_mesh;
  29.     o->objmesh->nf=nfaces-j;
  30.     o->objmesh->faces=new face *[o->objmesh->nf];
  31.     for( j=0,i=0;i<nfaces;i++ )
  32.         if (faces[i].indx)
  33.             o->objmesh->faces[j++]=&faces[i];
  34.     bsp->elem=o;
  35.  
  36.     ((bsp_node_max *)bsp)->planeflags=new char[o->objmesh->nf];
  37.     memset(((bsp_node_max *)bsp)->planeflags,1,o->objmesh->nf);
  38.  
  39.     for( i=0;i<o->objmesh->nf;i++ )
  40.         ((bsp_node_max *)bsp)->add_plane(o->objmesh->faces[i]->normal,o->objmesh->faces[i]->d0);
  41.  
  42.     if (bspmode==0)
  43.         ((bsp_node_max *)bsp)->split_faces_aligned();
  44.     else 
  45.         ((bsp_node_max *)bsp)->split_axis_aligned(maxdepth);
  46. }
  47.  
  48. void scene_max::save_map(char *name)
  49. {
  50.     FILE *fp;
  51.     char *pic[512];
  52.     int npic=0,i,j;
  53.  
  54.     for( i=0;i<nmatlib;i++ )
  55.         if (matlib[i].map_texture1.filename[0]==0)
  56.             matlib[i].map_texture1.piclibindx=-1;
  57.         else
  58.             {
  59.             for( j=0;j<npic;j++ )
  60.                 if (!stricmp(pic[j],matlib[i].map_texture1.filename))
  61.                     break;
  62.             if (j==npic)
  63.                 {
  64.                 pic[j]=new char[strlen(matlib[i].map_texture1.filename)+1];
  65.                 strcpy(pic[j],matlib[i].map_texture1.filename);
  66.                 npic++;
  67.                 }
  68.             matlib[i].map_texture1.piclibindx=j;
  69.             }
  70.  
  71.     fp=fopen(name,"wt");
  72.  
  73.     fprintf(fp,"%i\n",npic);
  74.     for( i=0;i<npic;i++ )
  75.         fprintf(fp,"%s\n",pic[i]);
  76.     
  77.     for( i=0;i<nfaces;i++ )
  78.         if (faces[i].texpic!=-1)
  79.             faces[i].texpic=matlib[faces[i].texpic].map_texture1.piclibindx;
  80.  
  81.     fclose(fp);
  82.  
  83.     for( i=0;i<npic;i++ )
  84.         delete pic[i];
  85. }
  86.  
  87. void bsp_node_max::split_faces_aligned()
  88. {
  89.     if (nplanes==0)
  90.         return;
  91.  
  92.     int i,p,j;
  93.  
  94.     p=find_split_plane();
  95.     if (p==-1) 
  96.         return;    
  97.     
  98.     static_mesh *o=(static_mesh *)elem;
  99.     side=-1;
  100.  
  101.     child[0]=new bsp_node_max;    
  102.     child[1]=new bsp_node_max;
  103.     child[0]->elem=new static_mesh;
  104.     child[1]->elem=new static_mesh;
  105.  
  106.     float d1,d2,d3;
  107.  
  108.     for( i=0;i<o->objmesh->nf;i++ )        
  109.         {
  110.         d1=distance(*o->objmesh->faces[i]->vert[0]);
  111.         d2=distance(*o->objmesh->faces[i]->vert[1]);
  112.         d3=distance(*o->objmesh->faces[i]->vert[2]);
  113.  
  114.         j=find_plane(o->objmesh->faces[i]->normal,o->objmesh->faces[i]->d0);
  115.         if (j==p)
  116.             ((bsp_node_max *)child[0])->add_face(o->objmesh->faces[i],0);
  117.         else
  118.         if (d1>-SMALLF && d2>-SMALLF && d3>-SMALLF) 
  119.             ((bsp_node_max *)child[0])->add_face(o->objmesh->faces[i],planeflags[i]);
  120.         else 
  121.         if (d1<SMALLF && d2<SMALLF && d3<SMALLF)
  122.             ((bsp_node_max *)child[1])->add_face(o->objmesh->faces[i],planeflags[i]);
  123.         else 
  124.             { 
  125.             ((bsp_node_max *)child[0])->add_face(o->objmesh->faces[i],planeflags[i]);
  126.             ((bsp_node_max *)child[1])->add_face(o->objmesh->faces[i],planeflags[i]);
  127.             }
  128.         }
  129.  
  130.     delete o->objmesh->faces;
  131.     o->objmesh->faces=0;
  132.     delete elem;
  133.     elem=0;
  134.     if (planes) delete planes;
  135.     nplanes=0;
  136.     planes=0;
  137.     if (planeflags) delete planeflags;
  138.     planeflags=0;
  139.  
  140.     if (((static_mesh *)child[0]->elem)->objmesh->nf>0)
  141.     {
  142.         ((bsp_node_max *)child[0])->side=0;
  143.         ((bsp_node_max *)child[0])->split_faces_aligned();
  144.     }
  145.     else
  146.     {
  147.         delete child[0]->elem;
  148.         child[0]->elem=0;
  149.         delete child[0];
  150.         child[0]=0;
  151.     }
  152.     
  153. //    if (((static_mesh *)child[1]->elem)->objmesh->nf>0)
  154.     if (((bsp_node_max *)child[1])->nplanes)
  155.     {
  156.         ((bsp_node_max *)child[1])->side=1;
  157.         ((bsp_node_max *)child[1])->split_faces_aligned();
  158.     }
  159.     else
  160.     {
  161.         delete child[1]->elem;
  162.         child[1]->elem=0;
  163.         delete child[1];
  164.         child[1]=0;
  165.     }
  166. }
  167.  
  168. int bsp_node_max::find_split_plane()
  169. {
  170.     int i,k=-1;
  171.     int n,dif,bestdif=100000,n1,n2,n3;
  172.     float d1,d2,d3;
  173.     static_mesh *o=(static_mesh *)elem;
  174.     if (o==0) return -1;
  175.  
  176.     for( i=0;i<nplanes;i++ )
  177.         {
  178.         normal=planes[i].normal;
  179.         d0=planes[i].d0;
  180.  
  181.         n1=n2=n3=0;
  182.         for( n=0;n<o->objmesh->nf;n++ )
  183.             {
  184.             d1=distance(*o->objmesh->faces[n]->vert[0]);
  185.             d2=distance(*o->objmesh->faces[n]->vert[1]);
  186.             d3=distance(*o->objmesh->faces[n]->vert[2]);
  187.  
  188.             if (d1>-SMALLF && d2>-SMALLF && d3>-SMALLF)
  189.                 n1++;
  190.             else 
  191.             if (d1<SMALLF && d2<SMALLF && d3<SMALLF)
  192.                 n2++;
  193.             else n3++;
  194.             }
  195.  
  196.         dif=abs(n1-n2)+n3*2;
  197.         if ((dif==bestdif && (rand()%1))||
  198.             dif<bestdif)
  199.             {
  200.             bestdif=dif;
  201.             k=i;
  202.             }
  203.         }
  204.  
  205.     if (k==-1)
  206.         return -1;
  207.  
  208.     normal=planes[k].normal;
  209.     d0=planes[k].d0;
  210.     return k;
  211. }
  212.  
  213. void bsp_node_max::add_face(face *f,int planeflag)
  214. {
  215.     static_mesh *o=(static_mesh *)elem;
  216.     if (o==0) 
  217.         return;
  218.     
  219.     face **tmp1;
  220.     tmp1=new face *[o->objmesh->nf+1];
  221.     memcpy(tmp1,o->objmesh->faces,sizeof(face *)*o->objmesh->nf);
  222.     if (o->objmesh->faces) 
  223.         delete o->objmesh->faces;
  224.     o->objmesh->faces=tmp1;
  225.     o->objmesh->faces[o->objmesh->nf]=f;
  226.  
  227.     char *tmp2;
  228.     tmp2=new char[o->objmesh->nf+1];
  229.     memcpy(tmp2,planeflags,o->objmesh->nf);
  230.     if (planeflags)
  231.         delete planeflags;
  232.     planeflags=tmp2;
  233.     planeflags[o->objmesh->nf]=planeflag;
  234.  
  235.     if (planeflag)
  236.         add_plane(f->normal,f->d0);
  237.  
  238.     o->objmesh->nf++;
  239. }
  240.  
  241. int bsp_node_max::find_plane(vector& normal,float d0)
  242. {
  243.     int i;
  244.     for( i=0;i<nplanes;i++ )
  245.         if (fabs(d0-planes[i].d0)<0.1 &&
  246.             vec_dot(normal,planes[i].normal)>0.99f)
  247.             break;
  248.     if (i==nplanes)
  249.         return -1;
  250.     else return i;
  251. }
  252.  
  253. int bsp_node_max::add_plane(vector& normal,float d0)
  254. {
  255.     int i=find_plane(normal,d0);
  256.  
  257.     if (i>=0)
  258.         return i;
  259.  
  260.     plane *p=new plane[nplanes+1];
  261.     memcpy(p,planes,sizeof(plane)*nplanes);
  262.     if (planes) delete planes;
  263.     planes=p;
  264.     planes[nplanes].normal=normal;
  265.     planes[nplanes].d0=d0;
  266.     return nplanes++;
  267. }
  268.  
  269. void bsp_node_max::split_axis_aligned(int depth)
  270. {
  271.     if (--depth==0)
  272.         return;
  273.  
  274.     int i,k=-1;
  275.     int n,dif,bestdif=100000,n1,n2,n3;
  276.     float d1,d2,d3;
  277.     static_mesh *o=(static_mesh *)elem;
  278.     if (o==0) return;
  279.  
  280.     calc_bbox();
  281.     vector pos(0,0,0);
  282.     for( n=0;n<o->objmesh->nf;n++ )
  283.         pos+=(*o->objmesh->faces[n]->vert[0]+
  284.             *o->objmesh->faces[n]->vert[1]+
  285.             *o->objmesh->faces[n]->vert[2])/3.0f;
  286.     pos/=(float)o->objmesh->nf;
  287.  
  288.     for( i=0;i<planemode;i++ )
  289.     {
  290.         normal.vec(0,0,0);
  291.         (&normal.x)[i]=1;
  292.         d0=-vec_dot(pos,normal);
  293.  
  294.         n1=n2=n3=0;
  295.         for( n=0;n<o->objmesh->nf;n++ )
  296.             {
  297.             d1=distance(*o->objmesh->faces[n]->vert[0]);
  298.             d2=distance(*o->objmesh->faces[n]->vert[1]);
  299.             d3=distance(*o->objmesh->faces[n]->vert[2]);
  300.  
  301.             if (d1>-SMALLF && d2>-SMALLF && d3>-SMALLF)
  302.                 n1++;
  303.             else 
  304.             if (d1<SMALLF && d2<SMALLF && d3<SMALLF)
  305.                 n2++;
  306.             else n3++;
  307.             }
  308.  
  309.         dif=abs(n1-n2)+n3*2;
  310.         if (dif<bestdif || (dif==bestdif && (rand()&1)))
  311.             {
  312.             bestdif=dif;
  313.             k=i;
  314.             }
  315.     }
  316.  
  317.     if (k==-1) return;
  318.  
  319.     normal.vec(0,0,0);
  320.     (&normal.x)[k]=1;
  321.     d0=-vec_dot(pos,normal);
  322.     side=-1;
  323.     child[0]=new bsp_node_max;    
  324.     child[1]=new bsp_node_max;
  325.     child[0]->elem=new static_mesh;
  326.     child[1]->elem=new static_mesh;
  327.  
  328.     for( i=0;i<o->objmesh->nf;i++ )        
  329.         {
  330.         d1=distance(*o->objmesh->faces[i]->vert[0]);
  331.         d2=distance(*o->objmesh->faces[i]->vert[1]);
  332.         d3=distance(*o->objmesh->faces[i]->vert[2]);
  333.  
  334.         if (d1<SMALLF && d2<SMALLF && d3<SMALLF)
  335.             ((bsp_node_max *)child[1])->add_face(o->objmesh->faces[i],0);
  336.         else 
  337.         if (d1>-SMALLF && d2>-SMALLF && d3>-SMALLF) 
  338.             ((bsp_node_max *)child[0])->add_face(o->objmesh->faces[i],0);
  339.         else 
  340.             { 
  341.             ((bsp_node_max *)child[0])->add_face(o->objmesh->faces[i],0);
  342.             ((bsp_node_max *)child[1])->add_face(o->objmesh->faces[i],0);
  343.             }
  344.         }
  345.  
  346.     delete o->objmesh->faces;
  347.     o->objmesh->faces=0;
  348.     delete elem;
  349.     elem=0;
  350.  
  351.     ((bsp_node_max *)child[0])->side=0;
  352.     ((bsp_node_max *)child[1])->side=1;
  353.  
  354.     ((bsp_node_max *)child[0])->split_axis_aligned(depth);
  355.     ((bsp_node_max *)child[1])->split_axis_aligned(depth);
  356. }
  357.  
  358. void scene_max::compute_scene_normals()
  359. {
  360.     int i, k;
  361.     vector v1, v2;
  362.  
  363.     for( i=0;i<nfaces;i++ )
  364.         for( k=0;k<3;k++ )
  365.             faces[i].vert[k]=&vert[(int)faces[i].vert[k]];
  366.     
  367.     for(i=0; i<nfaces; i++)
  368.     {
  369.         v1=*faces[i].vert[1]-*faces[i].vert[0];
  370.         v2=*faces[i].vert[2]-*faces[i].vert[0];
  371.         faces[i].normal.cross(v1,v2);
  372.         faces[i].d0=faces[i].normal.length();
  373.         faces[i].normal.normalize();
  374.     }
  375.     
  376.     compute_normals();
  377. }
  378.  
  379. void scene_max::save(char *file)
  380. {
  381.     if (bsp)
  382.     {
  383.     if (bsp->child[0]!=0 || bsp->child[1]!=0)
  384.         {
  385.         strcpy(strrchr(file,'.'),".tex");
  386.         save_map(file);
  387.         
  388.         strcpy(strrchr(file,'.'),".bsp");
  389.         save_bsp(file);
  390.  
  391.         if (savelog)
  392.             {
  393.             strcpy(strrchr(file,'.'),".bsplog.txt");
  394.             FILE *fp=fopen(file,"wt");
  395.             int tot=0;
  396.             fprintf(fp,"depth\tnfaces\tside\n");
  397.             ((bsp_node_max *)bsp)->print(fp,tot,0);
  398.             fprintf(fp,"\nTotal: %i %i\n",nfaces,tot);
  399.             fclose(fp);
  400.             }
  401.         }
  402.  
  403.     ((bsp_node_max *)bsp)->free_faces();
  404.     }
  405. }
  406.  
  407. void bsp_node_max::free_faces()
  408. {
  409.     if (elem)
  410.     {
  411.         static_mesh *o=(static_mesh *)elem;
  412.         delete o->objmesh->faces;
  413.         o->objmesh->faces=0;
  414.         delete elem;
  415.         elem=0;
  416.     }
  417.     if (child[0])
  418.         ((bsp_node_max *)child[0])->free_faces();
  419.     if (child[1])
  420.         ((bsp_node_max *)child[1])->free_faces();
  421. }
  422.  
  423. void bsp_node_max::print(FILE *fp,int& tot,int depth)
  424. {
  425.     static_mesh *o=(static_mesh *)elem;
  426.  
  427.     if (side!=-1)
  428.         {
  429.         fprintf(fp,"%i\t%i\t%i\n",depth,o->objmesh->nf,side);
  430.         tot+=o->objmesh->nf;
  431.         }
  432.     else
  433.         {
  434.         if (child[0])
  435.             ((bsp_node_max *)child[0])->print(fp,tot,depth+1);
  436.         if (child[1])
  437.             ((bsp_node_max *)child[1])->print(fp,tot,depth+1);
  438.         }
  439. }
  440.  
  441. void bsp_node_max::calc_bbox()
  442. {
  443.     int i,j;
  444.     static_mesh *o=(static_mesh *)elem;
  445.     bbox.reset();
  446.     if (o)
  447.         for( i=0;i<o->objmesh->nf;i++ )
  448.             for( j=0;j<3;j++ )
  449.                 bbox.add_point(*o->objmesh->faces[i]->vert[j]);
  450. }
  451.  
  452. void scene_max::compute_light()
  453. {
  454.     if (nlights)
  455.     {
  456.         int i,j;
  457.         float dot;
  458.         if (cartoonlight)
  459.         {
  460.             vector lightdir;
  461.             float *uv=new float[nvert];
  462.             memset(uv,0,sizeof(float)*nvert);
  463.             for( i=0;i<nlights;i++ )
  464.             for( j=0;j<nvert;j++ )
  465.                 {
  466.                 lightdir=lightlib[i].pos-vert[j];
  467.                 lightdir.normalize();
  468.                 dot=vec_dot(lightdir,vertnormal[j]);
  469.                 if (dot>0)
  470.                     uv[j]+=dot;
  471.                 if (vertcolor)
  472.                     vertcolor[j]*=lightlib[i].color;
  473.                 }
  474.             for( i=0;i<nfaces;i++ )
  475.                 for( j=0;j<3;j++ )
  476.                 {
  477.                     faces[i].uv[j][0]=uv[faces[i].vert[j]-vert];
  478.                     faces[i].uv[j][1]=0.0f;
  479.                 }
  480.             delete uv;
  481.         }
  482.         else
  483.         {
  484.             if (vertcolor==0)
  485.             {
  486.                 vertcolor=new vector[nvert];
  487.                 for( i=0;i<nvert;i++ )
  488.                     vertcolor[i].vec(1,1,1);
  489.             }
  490.             vector *col=new vector[nvert];
  491.             memset(col,0,sizeof(vector)*nvert);
  492.             for( i=0;i<nlights;i++ )
  493.             {
  494.                 vector lightdir=lightlib[i].pos-vert[i];
  495.                 lightdir.normalize();
  496.                 for( j=0;j<nvert;j++ )
  497.                 {
  498.                     dot=vec_dot(vertnormal[j],lightdir);
  499.                     if (dot>=0)
  500.                         col[j]+=vertcolor[j]*lightlib[i].color*
  501.                                 vec_dot(vertnormal[j],lightdir);
  502.                 }
  503.             }
  504.             delete vertcolor;
  505.             vertcolor=col;
  506.         }
  507.     }
  508. }
  509.  
  510. void scene_max::enum_leaf(bsp_node *n)
  511. {
  512.     if (n->child[0]==0 && n->child[1]==0)
  513.     {
  514.         n->leaf=nleaf++;
  515.         return;
  516.     }
  517.     if (n->child[0])
  518.         enum_leaf(n->child[0]);
  519.     if (n->child[1])
  520.         enum_leaf(n->child[1]);
  521. }