home *** CD-ROM | disk | FTP | other *** search
/ 3D Games - Real-time Rend…ng & Software Technology / 3D Games - Real-time Rendering & Software Technology.iso / flysdk / frontend / flyLight / lightEngine.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-15  |  12.1 KB  |  571 lines

  1. #include "../../lib/Fly3D.h"
  2. #include "lightengine.h"
  3. #include "Commctrl.h"
  4. #include <malloc.h>
  5. #include <search.h>
  6. #include <assert.h>
  7.  
  8. #define LIGHT_FACTOR 5000
  9. #define ANGLE_THRESHOLD 0.99f
  10. #define PLANE_THRESHOLD 0.1f
  11.  
  12. extern int lightvalue, mapsize;
  13. extern int ambient,connectivity;
  14. extern HDC hdc;
  15. extern float lightradius,lmpixelsize;
  16. extern HWND hWndHC,hWndProgress,hWndStatus;
  17. void HC_CreateWindow();
  18.  
  19. static_mesh *lightEngine::get_object(bsp_node *n)
  20. {
  21.     bsp_object *e=n->elem;
  22.     while(e)
  23.         {
  24.         if (e->type==TYPE_STATIC_MESH)
  25.             break;
  26.         e=e->next_elem;
  27.         }
  28.     return (static_mesh *)e;
  29. }
  30.  
  31. void lightEngine::light(char *f)
  32. {
  33.     char str[256],file[256];
  34.     strcpy(file,f);
  35.     strlwr(file);
  36.  
  37.     GetPrivateProfileString("fly","bspfile","",bspfile,255,f);
  38.     strcpy(flydatapath,f);
  39.     if (strrchr(flydatapath,'/'))
  40.         *(strrchr(flydatapath,'/')+1)=0;
  41.     else if (strrchr(flydatapath,'\\'))
  42.         *(strrchr(flydatapath,'\\')+1)=0;
  43.  
  44.     SetWindowText(hWndStatus,"Loading bsp...");
  45.     strcpy(str,flydatapath);
  46.     strcat(str,bspfile);
  47.     strcat(str,".bsp");
  48.     load_bsp(str);
  49.     if (bsp)
  50.     {
  51.     SetWindowText(hWndStatus,"Sorting bsp faces...");
  52.     sort_faces(bsp);
  53.  
  54.     SetWindowText(hWndStatus,"Saving bsp ...");
  55.     save_bsp(str);
  56.  
  57.     SetWindowText(hWndStatus,"Creating lightmaps...");
  58.     create_lightmaps();
  59.     
  60.     SetWindowText(hWndStatus,"Saving lightmaps...");
  61.     strcpy(str,flydatapath);
  62.     strcat(str,bspfile);
  63.     strcat(str,".lmp");
  64.     save_lightmaps(str);
  65.     
  66.     sprintf(str, "%i", ambient);
  67.     WritePrivateProfileString("fly", "amblight", str, f);
  68.     sprintf(str, "%f", lmpixelsize);
  69.     WritePrivateProfileString("fly", "lmpxsize", str, f);
  70.     sprintf(str, "%i", shadows);
  71.     WritePrivateProfileString("fly", "shadows", str, f);
  72.     sprintf(str, "%i", mapsize);
  73.     WritePrivateProfileString("fly", "mapsize", str, f);
  74.  
  75.     strcpy(str,flyengine->flysdkpath);
  76.     strcat(str,"data\\");
  77.     int len=strlen(str);
  78.     if (strncmp(file,str,len)==0)
  79.         {
  80.         SetWindowText(hWndStatus,"Loading level...");
  81.         open_fly_file(&file[len]);
  82.         }
  83.     if (flyfile[0]!=0)
  84.     {
  85.     SetWindowText(hWndStatus,"Lighting level...");
  86.     light_lightmaps();
  87.  
  88.     SetWindowText(hWndStatus,"Saving lightmaps ...");
  89.     strcpy(str,flydatapath);
  90.     strcat(str,bspfile);
  91.     strcat(str,".lmp");
  92.     save_lightmaps(str);
  93.  
  94.     SetWindowText(hWndStatus,"Saving level script ...");
  95.     strcpy(str,flyfile);
  96.     save_fly_file(str);
  97.  
  98.     SetWindowText(hWndStatus,"Done.");
  99.     }
  100.     else
  101.     SetWindowText(hWndStatus,"Error loading level.");
  102.     }
  103.     else
  104.         SetWindowText(hWndStatus,"Error loading bsp.");
  105.     SendMessage(hWndProgress,PBM_SETPOS,0,0);
  106. }
  107.  
  108. void lightEngine::clear_lightmaps(unsigned char pixel_light)
  109. {
  110.     int i;
  111.     for( i=0;i<nlmpic;i++ )
  112.         memset(lmpic[i]->bmp,0,lmpic[i]->bytesxy);
  113.  
  114.     for( i=0;i<nlm;i++ )
  115.     {
  116.         memset(lm[i]->bmp,pixel_light,lm[i]->bytesxy);
  117.         lm[i]->save(lmpic[lm[i]->pic]);
  118.     }
  119. }
  120.  
  121. int lightEngine::compute_facelist(int facenum,int *facelist)
  122. {
  123.     int i,j,n=0,p=1;
  124.     for( i=0;i<nfaces;i++ )
  125.         if (faces[i].indx &&
  126.             faces[i].lm==-1 &&
  127.             faces[i].texpic!=-1 &&
  128.             fabs(faces[i].d0-faces[facenum].d0)<PLANE_THRESHOLD &&
  129.             vec_dot(faces[i].normal,faces[facenum].normal)>ANGLE_THRESHOLD)
  130.             facelist[n++]=i;
  131.  
  132.     if (connectivity==0)
  133.         return n;
  134.  
  135.     for( i=0;i<n;i++ )
  136.         {
  137.         if (i>=p || p>=n)
  138.             break;
  139.         for( j=p;j<n;j++ )
  140.             {
  141.             if (faces[facelist[j]].vert[0]==faces[facelist[i]].vert[0] ||
  142.                 faces[facelist[j]].vert[0]==faces[facelist[i]].vert[1] ||
  143.                 faces[facelist[j]].vert[0]==faces[facelist[i]].vert[2] ||
  144.                 faces[facelist[j]].vert[1]==faces[facelist[i]].vert[0] ||
  145.                 faces[facelist[j]].vert[1]==faces[facelist[i]].vert[1] ||
  146.                 faces[facelist[j]].vert[1]==faces[facelist[i]].vert[2] ||
  147.                 faces[facelist[j]].vert[2]==faces[facelist[i]].vert[0] ||
  148.                 faces[facelist[j]].vert[2]==faces[facelist[i]].vert[1] ||
  149.                 faces[facelist[j]].vert[2]==faces[facelist[i]].vert[2])
  150.                     {
  151.                     int swap=facelist[p];
  152.                     facelist[p]=facelist[j];
  153.                     facelist[j]=swap;
  154.                     p++;
  155.                     }
  156.             }
  157.         }
  158.  
  159.     return p;
  160. }
  161.  
  162. boundbox lightEngine::compute_bbox(int *facelist,int nf)
  163. {
  164.     int i,j;
  165.     boundbox bb;
  166.  
  167.     bb.reset();
  168.  
  169.     for( i=0;i<nf;i++ )
  170.         for( j=0;j<3;j++ )
  171.             bb.add_point(*faces[facelist[i]].vert[j]);
  172.  
  173.     return bb;
  174. }
  175.  
  176. void lightEngine::compute_lightmaps()
  177. {
  178.     if (nfaces==0)
  179.         return;
  180.  
  181.     int i,j,l,nf;
  182.     boundbox bb;
  183.  
  184.     for( i=0;i<nfaces;i++ )
  185.         faces[i].lm=-1;
  186.  
  187.     SetWindowText(hWndStatus,"Computing lightmaps ...");
  188.     SendMessage(hWndProgress,PBM_SETRANGE,0,MAKELPARAM(0,nfaces));
  189.     SendMessage(hWndProgress,PBM_SETPOS,0,0);
  190.  
  191.     int *facelist=new int[nfaces];
  192.     
  193.     for( i=0;i<nfaces;i++,SendMessage(hWndProgress,PBM_SETPOS,i,0) )
  194.         if (faces[i].indx &&
  195.              faces[i].lm==-1 &&
  196.              faces[i].texpic!=-1)
  197.         {
  198.             nf=compute_facelist(i,facelist);
  199.             bb=compute_bbox(facelist,nf);
  200.             l=compute_lightmap_uv(bb,facelist,nf);
  201.             for( j=0;j<nf;j++ )
  202.                 faces[facelist[j]].lm=l;
  203.  
  204.         }
  205.  
  206.     delete facelist;
  207.  
  208.     retb r;
  209.  
  210.     struct reta *rl=new struct reta[nlm];
  211.  
  212.     for(i=0;i<nlm; i++)
  213.     {
  214.         rl[i].sizex=lm[i]->sizex;
  215.         rl[i].sizey=lm[i]->sizey;
  216.         r.add(&rl[i]);
  217.     }
  218.  
  219.     nlmpic=r.calc(mapsize, mapsize);
  220.  
  221.     for(i=0; i<nlm; i++)
  222.     {
  223.         lm[i]->offsetx=rl[i].offsetx;
  224.         lm[i]->offsety=rl[i].offsety;
  225.         lm[i]->pic=rl[i].offsetz;
  226.     }
  227.  
  228.     delete rl;
  229.  
  230.     for(i=0; i<nlmpic; i++) lmpic[i]=new light_map_pic(mapsize, mapsize);
  231.  
  232.     for(i=0; i<nfaces; i++)
  233.     {
  234.         l=faces[i].lm;
  235.         if(l!=-1)
  236.             for(j=0; j<3; j++)
  237.             {
  238.                 faces[i].lmuv[j][0]=(faces[i].lmuv[j][0]*lm[l]->sizex+lm[l]->offsetx)/mapsize;
  239.                 faces[i].lmuv[j][1]=(faces[i].lmuv[j][1]*lm[l]->sizey+lm[l]->offsety)/mapsize;
  240.             }
  241.     }
  242.  
  243.     for(i=0;i<nlm; i++)
  244.         lm[i]->set_base(&faces[lm[i]->facenum],lmpic[lm[i]->pic]);
  245.  
  246. }
  247.  
  248. int lightEngine::compute_lightmap_uv(boundbox bb,int *facelist,int nf)
  249. {
  250.     int ui,vi,i,j;
  251.     vector v,diag;
  252.     float uv;
  253.     int l;
  254.     int sizex, sizey;
  255.  
  256.     diag=faces[facelist[0]].normal;
  257.  
  258.     i=(fabs(diag[0])>fabs(diag[1]))?0:1;
  259.     i=(fabs(diag[i])>fabs(diag[2]))?i:2;
  260.  
  261.     if (i==0)
  262.         { ui=1;    vi=2; }
  263.     else if (i==1)
  264.         { ui=0;    vi=2; }
  265.     else { ui=0; vi=1; }
  266.  
  267.     diag=bb.max-bb.min;
  268.  
  269.     l=nlm++;
  270.     sizex=(int)(diag[ui]/lmpixelsize);
  271.     sizey=(int)(diag[vi]/lmpixelsize);
  272.  
  273.     lm[l]=new light_map(-1, -1, 0, 0, sizex<=mapsize?sizex:mapsize, sizey<=mapsize?sizey:mapsize);
  274.     
  275.     for( i=0;i<nf;i++ )
  276.         for( j=0;j<3;j++ )
  277.         {
  278.         v=*faces[facelist[i]].vert[j] - bb.min;
  279.         
  280.         uv=v[ui]/diag[ui];
  281.         if (lm[l]->sizex>1)
  282.             uv=uv*(lm[l]->sizex-1)/lm[l]->sizex+1.0f/(lm[l]->sizex*2);
  283.         
  284.         faces[facelist[i]].lmuv[j][0]=uv;
  285.  
  286.         uv=v[vi]/diag[vi];
  287.         if (lm[l]->sizey>1)
  288.             uv=uv*(lm[l]->sizey-1)/lm[l]->sizey+1.0f/(lm[l]->sizey*2);
  289.  
  290.         faces[facelist[i]].lmuv[j][1]=uv;
  291.         }
  292.     
  293.     lm[l]->facenum=facelist[0];
  294.  
  295.     return l;
  296. }
  297.  
  298. void lightEngine::apply_light(bsp_node *n,vector& pos,vector& color,float rad)
  299. {
  300.     if (n->child[0]==0 && n->child[1]==0)
  301.         {
  302.         static_mesh *o=get_object(n);
  303.         if (o)
  304.             {
  305.             int i;
  306.             for( i=0;i<o->objmesh->nf;i++ )
  307.                 if (o->objmesh->faces[i]->lm!=-1)
  308.                 {
  309.                 if (lm[o->objmesh->faces[i]->lm]->lastupdate==0)
  310.                     lm[o->objmesh->faces[i]->lm]->illum(pos,color,rad,shadows);
  311.                 lm[o->objmesh->faces[i]->lm]->lastupdate=1;
  312.                 }
  313.             }
  314.         return;
  315.         }
  316.  
  317.     static float dist;
  318.     dist=n->distance(pos);
  319.     if (fabs(dist)<rad)
  320.         {
  321.         if (n->child[0])
  322.             apply_light(n->child[0],pos,color,rad);
  323.         if (n->child[1])
  324.             apply_light(n->child[1],pos,color,rad);
  325.         }
  326.     else
  327.     if (dist>0)
  328.         if (n->child[0])
  329.             apply_light(n->child[0],pos,color,rad);
  330.         else ;
  331.     else if (n->child[1])
  332.             apply_light(n->child[1],pos,color,rad);
  333. }
  334.  
  335. void lightEngine::mark_used_bsp_faces(bsp_node *n)
  336. {
  337.     if (n->child[0]==0 && n->child[1]==0)
  338.         {
  339.         static_mesh *o=get_object(n);
  340.         if (o)
  341.             {
  342.             int i;
  343.             for( i=0;i<o->objmesh->nf;i++ )
  344.                 o->objmesh->faces[i]->indx=1;
  345.             }
  346.         }
  347.     else 
  348.     {
  349.         if (n->child[0])
  350.             mark_used_bsp_faces(n->child[0]);
  351.         if (n->child[1])
  352.             mark_used_bsp_faces(n->child[1]);
  353.     }
  354. }
  355.  
  356. void lightEngine::create_lightmaps()
  357. {
  358.     SendMessage(hWndProgress,PBM_SETPOS,0,0);
  359.     SetWindowText(hWndStatus,"Creating ligthmaps ...");
  360.  
  361.     int i;
  362.     for( i=0;i<nfaces;i++ )
  363.         faces[i].indx=0;
  364.     mark_used_bsp_faces(bsp);
  365.  
  366.     compute_lightmaps();
  367.     clear_lightmaps(ambient);
  368. }
  369.  
  370. void lightEngine::light_lightmaps()
  371. {
  372.     int i,j,k,n;
  373.     vector v1,v2,c,pos,color;
  374.  
  375.     int nlmp=0;
  376.     for( i=0;i<nlm;i++ )
  377.         nlmp+=lm[i]->sizex*lm[i]->sizey;
  378.  
  379.     SendMessage(hWndProgress,PBM_SETRANGE,0,MAKELPARAM(0,nfaces));
  380.     SendMessage(hWndProgress,PBM_SETPOS,0,0);
  381.     char str[256];
  382.     sprintf(str,"Rendering level lights ( %i lm / %i pixels ) ...",nlm,nlmp);
  383.     SetWindowText(hWndStatus,str);
  384.  
  385.     for( i=0;i<nfaces;i++,SendMessage(hWndProgress,PBM_SETPOS,i,0) )
  386.         if (faces[i].indx)
  387.         if (faces[i].emmradius)
  388.         {
  389.             color=faces[i].color;
  390.             if (lightvalue!=-1)
  391.                 {
  392.                 color.normalize();
  393.                 color*=lightvalue/255.0f;
  394.                 }
  395.  
  396.             v1=*faces[i].vert[1]-*faces[i].vert[0];
  397.             v2=*faces[i].vert[2]-*faces[i].vert[0];
  398.             c.cross(v1,v2);
  399.         
  400.             n=(int)(c.length()/LIGHT_FACTOR)+1;
  401.  
  402.             for( k=0;k<n;k++ )
  403.             {
  404.                 for( j=0;j<nlm;j++ )
  405.                     lm[j]->lastupdate=0;
  406.                 float r1=(rand()%10000)/10000.0f;
  407.                 float r2=(rand()%10000)/10000.0f;
  408.                 pos = 
  409.                     *faces[i].vert[0] + v1*r1 + v2*r2 +
  410.                     faces[i].normal*10;
  411.                 if (lightradius)
  412.                     apply_light(bsp,pos,color,(float)lightradius);
  413.                 else apply_light(bsp,pos,color,faces[i].emmradius);
  414.             }
  415.         }
  416.     bsp_object *obj=active_obj0;
  417.     i=0;
  418.     while(obj)
  419.     {
  420.         i++;
  421.         obj=(bsp_object *)obj->next_obj;
  422.     }
  423.     sprintf(str,"Rendering object lights ( %i lm / %i pixels ) ...",nlm,nlmp);
  424.     SendMessage(hWndProgress,PBM_SETRANGE,0,MAKELPARAM(0,i));
  425.     SendMessage(hWndProgress,PBM_SETPOS,0,0);
  426.     obj=active_obj0;
  427.     i=0;
  428.     while(obj)
  429.     {
  430.         obj->message(vector(0,0,0),0,FLYOBJM_STATICILLUM,0,0);
  431.         SendMessage(hWndProgress,PBM_SETPOS,++i,0);
  432.         obj=(bsp_object *)obj->next_obj;
  433.     }
  434.  
  435.     for( i=0;i<nlm;i++ )
  436.         lm[i]->save(lmpic[lm[i]->pic]);
  437. }
  438.  
  439. void lightEngine::sort_faces(bsp_node *n)
  440. {
  441.     if (n->child[0]==0 && n->child[1]==0)
  442.         {
  443.         static_mesh *o=get_object(n);
  444.         if (o)
  445.             {
  446.             int i=0,j;
  447.             while(i<o->objmesh->nf)
  448.                 {
  449.                 for( j=i+1;j<o->objmesh->nf;j++ )
  450.                     if (o->objmesh->faces[i]->texpic==o->objmesh->faces[j]->texpic)
  451.                     {
  452.                         face *f=o->objmesh->faces[j];
  453.                         o->objmesh->faces[j]=o->objmesh->faces[i+1];
  454.                         o->objmesh->faces[i+1]=f;
  455.                         i++;
  456.                     }
  457.                 i++;
  458.                 }
  459.             }
  460.         return;
  461.         }
  462.  
  463.     if (n->child[0])
  464.         sort_faces(n->child[0]);
  465.     if (n->child[1])
  466.         sort_faces(n->child[1]);
  467. }
  468.  
  469. int ordenar_por_area_desc(const void *elem1, const void *elem2)
  470. {
  471.     struct reta *r1, *r2;
  472.  
  473.     r1=*(struct reta **)elem1;
  474.     r2=*(struct reta **)elem2;
  475.  
  476.     return r2->sizex*r2->sizey-r1->sizex*r1->sizey;
  477. }
  478.  
  479. retb::retb()
  480. {
  481.     nl=0;
  482.     l=(struct reta **)malloc(0);
  483. }
  484.  
  485. retb::~retb()
  486. {
  487.     free(l);
  488. }
  489.  
  490. void retb::add(struct reta *r)
  491. {
  492.     l=(struct reta **)realloc(l, (++nl)*sizeof(struct reta *));
  493.     l[nl-1]=r;
  494. }
  495.  
  496. int retb::calc(int max_sx, int max_sy)
  497. {
  498.     struct reta r;
  499.  
  500.     r.sizex=max_sx;
  501.     r.sizey=max_sy;
  502.     r.offsetx=0;
  503.     r.offsety=0;
  504.     r.offsetz=0;
  505.  
  506.     for(int i=0; i<nl; i++) l[i]->offsetz=-1;
  507.  
  508.     qsort((void *)l, (size_t)nl, sizeof(struct reta *), ordenar_por_area_desc);
  509.  
  510.     while(arrumar(&r)) r.offsetz++;
  511.  
  512.     return r.offsetz;
  513. }
  514.  
  515. bool retb::arrumar(struct reta *rp)
  516. {
  517.     int i, dsx, dsy;
  518.     struct reta r[2];
  519.     
  520.     if((i=procura(rp->sizex, rp->sizey))==nl) return false; 
  521.  
  522.     l[i]->offsetx=rp->offsetx;
  523.     l[i]->offsety=rp->offsety;
  524.     l[i]->offsetz=rp->offsetz;
  525.  
  526.     dsx=rp->sizex-l[i]->sizex;
  527.     dsy=rp->sizey-l[i]->sizey;
  528.  
  529.     if(dsx*rp->sizey>dsy*rp->sizex)
  530.     {
  531.         r[0].sizex=dsx;
  532.         r[0].sizey=rp->sizey;
  533.         r[0].offsetx=rp->offsetx+l[i]->sizex;
  534.         r[0].offsety=rp->offsety;
  535.         r[0].offsetz=rp->offsetz;
  536.         r[1].sizex=l[i]->sizex;
  537.         r[1].sizey=dsy;
  538.         r[1].offsetx=rp->offsetx;
  539.         r[1].offsety=rp->offsety+l[i]->sizey;
  540.         r[1].offsetz=rp->offsetz;
  541.     }
  542.     else
  543.     {
  544.         r[0].sizex=rp->sizex;
  545.         r[0].sizey=dsy;
  546.         r[0].offsetx=rp->offsetx;
  547.         r[0].offsety=rp->offsety+l[i]->sizey;
  548.         r[0].offsetz=rp->offsetz;
  549.         r[1].sizex=dsx;
  550.         r[1].sizey=l[i]->sizey;
  551.         r[1].offsetx=rp->offsetx+l[i]->sizex;
  552.         r[1].offsety=rp->offsety;
  553.         r[1].offsetz=rp->offsetz;
  554.     }
  555.  
  556.     for(i=0; i<2; i++) arrumar(&r[i]);
  557.  
  558.     return true;
  559. }
  560.  
  561. int retb::procura(int sx, int sy)
  562. {
  563.     int i;
  564.  
  565.     for(i=0;i<nl;i++)
  566.         if(l[i]->offsetz==-1 &&
  567.             l[i]->sizex<=sx && l[i]->sizey<=sy)
  568.             break;
  569.  
  570.     return i;
  571. }