Blender V2.61 - r43446

renderdatabase.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): 2004-2006, Blender Foundation, full recode
00022  *
00023  * ***** END GPL/BL DUAL LICENSE BLOCK *****
00024  */
00025 
00031 /*
00032  * Storage, retrieval and query of render specific data.
00033  *
00034  * All data from a Blender scene is converted by the renderconverter/
00035  * into a special format that is used by the render module to make
00036  * images out of. These functions interface to the render-specific
00037  * database.  
00038  *
00039  * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
00040  * entries each.
00041  *
00042  * The index of an entry is >>8 (the highest 24 * bits), to find an
00043  * offset in a 256-entry block.
00044  *
00045  * - If the 256-entry block entry has an entry in the
00046  * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in
00047  * that block is allocated to this entry.
00048  *
00049  * - If the entry has no block allocated for it yet, memory is
00050  * allocated.
00051  *
00052  * The pointer to the correct entry is returned. Memory is guarateed
00053  * to exist (as long as the malloc does not break). Since guarded
00054  * allocation is used, memory _must_ be available. Otherwise, an
00055  * exit(0) would occur.
00056  * 
00057  */
00058 
00059 #include <limits.h>
00060 #include <math.h>
00061 #include <string.h>
00062 
00063 #include "MEM_guardedalloc.h"
00064 
00065 
00066 #include "BLI_math.h"
00067 #include "BLI_blenlib.h"
00068 #include "BLI_utildefines.h"
00069 #include "BLI_ghash.h"
00070 #include "BLI_memarena.h"
00071 
00072 #include "DNA_material_types.h" 
00073 #include "DNA_mesh_types.h" 
00074 #include "DNA_meshdata_types.h" 
00075 #include "DNA_texture_types.h" 
00076 
00077 #include "BKE_customdata.h"
00078 #include "BKE_texture.h" 
00079 #include "BKE_DerivedMesh.h"
00080 
00081 #include "RE_render_ext.h"  /* externtex */
00082 
00083 #include "rayobject.h"
00084 #include "renderpipeline.h"
00085 #include "render_types.h"
00086 #include "renderdatabase.h"
00087 #include "texture.h"
00088 #include "strand.h"
00089 #include "zbuf.h"
00090 
00091 /* ------------------------------------------------------------------------- */
00092 
00093 /* More dynamic allocation of options for render vertices and faces, so we dont
00094    have to reserve this space inside vertices.
00095    Important; vertices and faces, should have been created already (to get tables
00096    checked) that's a reason why the calls demand VertRen/VlakRen * as arg, not
00097    the index */
00098 
00099 /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
00100 
00101 #define RE_STICKY_ELEMS     2
00102 #define RE_STRESS_ELEMS     1
00103 #define RE_RAD_ELEMS        4
00104 #define RE_STRAND_ELEMS     1
00105 #define RE_TANGENT_ELEMS    3
00106 #define RE_STRESS_ELEMS     1
00107 #define RE_WINSPEED_ELEMS   4
00108 #define RE_MTFACE_ELEMS     1
00109 #define RE_MCOL_ELEMS       4
00110 #define RE_UV_ELEMS         2
00111 #define RE_SURFNOR_ELEMS    3
00112 #define RE_RADFACE_ELEMS    1
00113 #define RE_SIMPLIFY_ELEMS   2
00114 #define RE_FACE_ELEMS       1
00115 #define RE_NMAP_TANGENT_ELEMS   16
00116 
00117 float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
00118 {
00119     float *sticky;
00120     int nr= ver->index>>8;
00121     
00122     sticky= obr->vertnodes[nr].sticky;
00123     if(sticky==NULL) {
00124         if(verify) 
00125             sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
00126         else
00127             return NULL;
00128     }
00129     return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
00130 }
00131 
00132 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
00133 {
00134     float *stress;
00135     int nr= ver->index>>8;
00136     
00137     stress= obr->vertnodes[nr].stress;
00138     if(stress==NULL) {
00139         if(verify) 
00140             stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
00141         else
00142             return NULL;
00143     }
00144     return stress + (ver->index & 255)*RE_STRESS_ELEMS;
00145 }
00146 
00147 /* this one callocs! */
00148 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
00149 {
00150     float *rad;
00151     int nr= ver->index>>8;
00152     
00153     rad= obr->vertnodes[nr].rad;
00154     if(rad==NULL) {
00155         if(verify) 
00156             rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
00157         else
00158             return NULL;
00159     }
00160     return rad + (ver->index & 255)*RE_RAD_ELEMS;
00161 }
00162 
00163 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
00164 {
00165     float *strand;
00166     int nr= ver->index>>8;
00167     
00168     strand= obr->vertnodes[nr].strand;
00169     if(strand==NULL) {
00170         if(verify) 
00171             strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
00172         else
00173             return NULL;
00174     }
00175     return strand + (ver->index & 255)*RE_STRAND_ELEMS;
00176 }
00177 
00178 /* needs calloc */
00179 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
00180 {
00181     float *tangent;
00182     int nr= ver->index>>8;
00183     
00184     tangent= obr->vertnodes[nr].tangent;
00185     if(tangent==NULL) {
00186         if(verify) 
00187             tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
00188         else
00189             return NULL;
00190     }
00191     return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
00192 }
00193 
00194 /* needs calloc! not all renderverts have them */
00195 /* also winspeed is exception, it is stored per instance */
00196 float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
00197 {
00198     float *winspeed;
00199     int totvector;
00200     
00201     winspeed= obi->vectors;
00202     if(winspeed==NULL) {
00203         if(verify) {
00204             totvector= obi->obr->totvert + obi->obr->totstrand;
00205             winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
00206         }
00207         else
00208             return NULL;
00209     }
00210     return winspeed + ver->index*RE_WINSPEED_ELEMS;
00211 }
00212 
00213 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
00214 {
00215     VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
00216     float *fp1, *fp2;
00217     int index= v1->index;
00218     
00219     *v1= *ver;
00220     v1->index= index;
00221     
00222     fp1= RE_vertren_get_sticky(obr, ver, 0);
00223     if(fp1) {
00224         fp2= RE_vertren_get_sticky(obr, v1, 1);
00225         memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
00226     }
00227     fp1= RE_vertren_get_stress(obr, ver, 0);
00228     if(fp1) {
00229         fp2= RE_vertren_get_stress(obr, v1, 1);
00230         memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
00231     }
00232     fp1= RE_vertren_get_rad(obr, ver, 0);
00233     if(fp1) {
00234         fp2= RE_vertren_get_rad(obr, v1, 1);
00235         memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
00236     }
00237     fp1= RE_vertren_get_strand(obr, ver, 0);
00238     if(fp1) {
00239         fp2= RE_vertren_get_strand(obr, v1, 1);
00240         memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
00241     }
00242     fp1= RE_vertren_get_tangent(obr, ver, 0);
00243     if(fp1) {
00244         fp2= RE_vertren_get_tangent(obr, v1, 1);
00245         memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
00246     }
00247     return v1;
00248 }
00249 
00250 VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
00251 {
00252     VertTableNode *temp;
00253     VertRen *v;
00254     int a;
00255 
00256     if(nr<0) {
00257         printf("error in findOrAddVert: %d\n",nr);
00258         return NULL;
00259     }
00260     a= nr>>8;
00261     
00262     if (a>=obr->vertnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
00263         temp= obr->vertnodes;
00264         
00265         obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE) , "vertnodes");
00266         if(temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode));
00267         memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
00268         
00269         obr->vertnodeslen+=TABLEINITSIZE; 
00270         if(temp) MEM_freeN(temp);   
00271     }
00272     
00273     v= obr->vertnodes[a].vert;
00274     if(v==NULL) {
00275         int i;
00276         
00277         v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
00278         obr->vertnodes[a].vert= v;
00279         
00280         for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
00281             v[a].index= i;
00282         }
00283     }
00284     v+= (nr & 255);
00285     return v;
00286 }
00287 
00288 /* ------------------------------------------------------------------------ */
00289 
00290 MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
00291 {
00292     VlakTableNode *node;
00293     int nr= vlr->index>>8, vlakindex= (vlr->index&255);
00294     int index= (n<<8) + vlakindex;
00295 
00296     node= &obr->vlaknodes[nr];
00297 
00298     if(verify) {
00299         if(n>=node->totmtface) {
00300             MTFace *mtface= node->mtface;
00301             int size= (n+1)*256;
00302 
00303             node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
00304 
00305             if(mtface) {
00306                 size= node->totmtface*256;
00307                 memcpy(node->mtface, mtface, size*sizeof(MTFace));
00308                 MEM_freeN(mtface);
00309             }
00310 
00311             node->totmtface= n+1;
00312         }
00313     }
00314     else {
00315         if(n>=node->totmtface)
00316             return NULL;
00317 
00318         if(name) *name= obr->mtface[n];
00319     }
00320 
00321     return node->mtface + index;
00322 }
00323 
00324 MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
00325 {
00326     VlakTableNode *node;
00327     int nr= vlr->index>>8, vlakindex= (vlr->index&255);
00328     int index= (n<<8) + vlakindex;
00329 
00330     node= &obr->vlaknodes[nr];
00331 
00332     if(verify) {
00333         if(n>=node->totmcol) {
00334             MCol *mcol= node->mcol;
00335             int size= (n+1)*256;
00336 
00337             node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
00338 
00339             if(mcol) {
00340                 size= node->totmcol*256;
00341                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
00342                 MEM_freeN(mcol);
00343             }
00344 
00345             node->totmcol= n+1;
00346         }
00347     }
00348     else {
00349         if(n>=node->totmcol)
00350             return NULL;
00351 
00352         if(name) *name= obr->mcol[n];
00353     }
00354 
00355     return node->mcol + index*RE_MCOL_ELEMS;
00356 }
00357 
00358 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
00359 {
00360     float *surfnor;
00361     int nr= vlak->index>>8;
00362     
00363     surfnor= obr->vlaknodes[nr].surfnor;
00364     if(surfnor==NULL) {
00365         if(verify) 
00366             surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
00367         else
00368             return NULL;
00369     }
00370     return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
00371 }
00372 
00373 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
00374 {
00375     float *tangent;
00376     int nr= vlak->index>>8;
00377 
00378     tangent= obr->vlaknodes[nr].tangent;
00379     if(tangent==NULL) {
00380         if(verify) 
00381             tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
00382         else
00383             return NULL;
00384     }
00385     return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
00386 }
00387 
00388 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
00389 {
00390     RadFace **radface;
00391     int nr= vlak->index>>8;
00392     
00393     radface= obr->vlaknodes[nr].radface;
00394     if(radface==NULL) {
00395         if(verify) 
00396             radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
00397         else
00398             return NULL;
00399     }
00400     return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
00401 }
00402 
00403 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
00404 {
00405     VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
00406     MTFace *mtface, *mtface1;
00407     MCol *mcol, *mcol1;
00408     float *surfnor, *surfnor1, *tangent, *tangent1;
00409     RadFace **radface, **radface1;
00410     int i, index = vlr1->index;
00411     char *name;
00412 
00413     *vlr1= *vlr;
00414     vlr1->index= index;
00415 
00416     for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
00417         mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
00418         memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
00419     }
00420 
00421     for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
00422         mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
00423         memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
00424     }
00425 
00426     surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
00427     if(surfnor) {
00428         surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
00429         copy_v3_v3(surfnor1, surfnor);
00430     }
00431 
00432     tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
00433     if(tangent) {
00434         tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
00435         memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
00436     }
00437 
00438     radface= RE_vlakren_get_radface(obr, vlr, 0);
00439     if(radface) {
00440         radface1= RE_vlakren_get_radface(obr, vlr1, 1);
00441         *radface1= *radface;
00442     }
00443 
00444     return vlr1;
00445 }
00446 
00447 void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float *nor)
00448 {
00449     float (*nmat)[3]= obi->nmat;
00450 
00451     if(obi->flag & R_TRANSFORMED) {
00452         mul_v3_m3v3(nor, nmat, vlr->n);
00453         normalize_v3(nor);
00454     }
00455     else {
00456         copy_v3_v3(nor, vlr->n);
00457     }
00458 }
00459 
00460 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
00461 {
00462     /* CustomData layer names are stored per object here, because the
00463        DerivedMesh which stores the layers is freed */
00464     
00465     CustomDataLayer *layer;
00466     int numtf = 0, numcol = 0, i, mtfn, mcn;
00467 
00468     if (CustomData_has_layer(data, CD_MTFACE)) {
00469         numtf= CustomData_number_of_layers(data, CD_MTFACE);
00470         obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
00471     }
00472 
00473     if (CustomData_has_layer(data, CD_MCOL)) {
00474         numcol= CustomData_number_of_layers(data, CD_MCOL);
00475         obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
00476     }
00477 
00478     for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
00479         layer= &data->layers[i];
00480 
00481         if (layer->type == CD_MTFACE) {
00482             BLI_strncpy(obr->mtface[mtfn++], layer->name, sizeof(layer->name));
00483             obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
00484             obr->bakemtface= layer->active;
00485         }
00486         else if (layer->type == CD_MCOL) {
00487             BLI_strncpy(obr->mcol[mcn++], layer->name, sizeof(layer->name));
00488             obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
00489         }
00490     }
00491 }
00492 
00493 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
00494 {
00495     VlakTableNode *temp;
00496     VlakRen *v;
00497     int a;
00498 
00499     if(nr<0) {
00500         printf("error in findOrAddVlak: %d\n",nr);
00501         return obr->vlaknodes[0].vlak;
00502     }
00503     a= nr>>8;
00504     
00505     if (a>=obr->vlaknodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
00506         temp= obr->vlaknodes;
00507         
00508         obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
00509         if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
00510         memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
00511 
00512         obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
00513         if(temp) MEM_freeN(temp);   
00514     }
00515 
00516     v= obr->vlaknodes[a].vlak;
00517     
00518     if(v==NULL) {
00519         int i;
00520 
00521         v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
00522         obr->vlaknodes[a].vlak= v;
00523 
00524         for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
00525             v[a].index= i;
00526     }
00527     v+= (nr & 255);
00528     return v;
00529 }
00530 
00531 /* ------------------------------------------------------------------------ */
00532 
00533 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
00534 {
00535     float *surfnor;
00536     int nr= strand->index>>8;
00537     
00538     surfnor= obr->strandnodes[nr].surfnor;
00539     if(surfnor==NULL) {
00540         if(verify) 
00541             surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
00542         else
00543             return NULL;
00544     }
00545     return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
00546 }
00547 
00548 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
00549 {
00550     StrandTableNode *node;
00551     int nr= strand->index>>8, strandindex= (strand->index&255);
00552     int index= (n<<8) + strandindex;
00553 
00554     node= &obr->strandnodes[nr];
00555 
00556     if(verify) {
00557         if(n>=node->totuv) {
00558             float *uv= node->uv;
00559             int size= (n+1)*256;
00560 
00561             node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
00562 
00563             if(uv) {
00564                 size= node->totuv*256;
00565                 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
00566                 MEM_freeN(uv);
00567             }
00568 
00569             node->totuv= n+1;
00570         }
00571     }
00572     else {
00573         if(n>=node->totuv)
00574             return NULL;
00575 
00576         if(name) *name= obr->mtface[n];
00577     }
00578 
00579     return node->uv + index*RE_UV_ELEMS;
00580 }
00581 
00582 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
00583 {
00584     StrandTableNode *node;
00585     int nr= strand->index>>8, strandindex= (strand->index&255);
00586     int index= (n<<8) + strandindex;
00587 
00588     node= &obr->strandnodes[nr];
00589 
00590     if(verify) {
00591         if(n>=node->totmcol) {
00592             MCol *mcol= node->mcol;
00593             int size= (n+1)*256;
00594 
00595             node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
00596 
00597             if(mcol) {
00598                 size= node->totmcol*256;
00599                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
00600                 MEM_freeN(mcol);
00601             }
00602 
00603             node->totmcol= n+1;
00604         }
00605     }
00606     else {
00607         if(n>=node->totmcol)
00608             return NULL;
00609 
00610         if(name) *name= obr->mcol[n];
00611     }
00612 
00613     return node->mcol + index*RE_MCOL_ELEMS;
00614 }
00615 
00616 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
00617 {
00618     float *simplify;
00619     int nr= strand->index>>8;
00620     
00621     simplify= obr->strandnodes[nr].simplify;
00622     if(simplify==NULL) {
00623         if(verify) 
00624             simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
00625         else
00626             return NULL;
00627     }
00628     return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
00629 }
00630 
00631 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
00632 {
00633     int *face;
00634     int nr= strand->index>>8;
00635     
00636     face= obr->strandnodes[nr].face;
00637     if(face==NULL) {
00638         if(verify) 
00639             face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
00640         else
00641             return NULL;
00642     }
00643     return face + (strand->index & 255)*RE_FACE_ELEMS;
00644 }
00645 
00646 /* winspeed is exception, it is stored per instance */
00647 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
00648 {
00649     float *winspeed;
00650     int totvector;
00651     
00652     winspeed= obi->vectors;
00653     if(winspeed==NULL) {
00654         if(verify) {
00655             totvector= obi->obr->totvert + obi->obr->totstrand;
00656             winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
00657         }
00658         else
00659             return NULL;
00660     }
00661     return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
00662 }
00663 
00664 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
00665 {
00666     StrandTableNode *temp;
00667     StrandRen *v;
00668     int a;
00669 
00670     if(nr<0) {
00671         printf("error in findOrAddStrand: %d\n",nr);
00672         return obr->strandnodes[0].strand;
00673     }
00674     a= nr>>8;
00675     
00676     if (a>=obr->strandnodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
00677         temp= obr->strandnodes;
00678         
00679         obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes");
00680         if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
00681         memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
00682 
00683         obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
00684         if(temp) MEM_freeN(temp);   
00685     }
00686 
00687     v= obr->strandnodes[a].strand;
00688     
00689     if(v==NULL) {
00690         int i;
00691 
00692         v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
00693         obr->strandnodes[a].strand= v;
00694 
00695         for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
00696             v[a].index= i;
00697     }
00698     v+= (nr & 255);
00699     return v;
00700 }
00701 
00702 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
00703 {
00704     StrandBuffer *strandbuf;
00705 
00706     strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
00707     strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
00708     strandbuf->totvert= totvert;
00709     strandbuf->obr= obr;
00710 
00711     obr->strandbuf= strandbuf;
00712 
00713     return strandbuf;
00714 }
00715 
00716 /* ------------------------------------------------------------------------ */
00717 
00718 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
00719 {
00720     ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
00721     
00722     BLI_addtail(&re->objecttable, obr);
00723     obr->ob= ob;
00724     obr->par= par;
00725     obr->index= index;
00726     obr->psysindex= psysindex;
00727     obr->lay= lay;
00728 
00729     return obr;
00730 }
00731 
00732 void free_renderdata_vertnodes(VertTableNode *vertnodes)
00733 {
00734     int a;
00735     
00736     if(vertnodes==NULL) return;
00737     
00738     for(a=0; vertnodes[a].vert; a++) {
00739         MEM_freeN(vertnodes[a].vert);
00740         
00741         if(vertnodes[a].rad)
00742             MEM_freeN(vertnodes[a].rad);
00743         if(vertnodes[a].sticky)
00744             MEM_freeN(vertnodes[a].sticky);
00745         if(vertnodes[a].strand)
00746             MEM_freeN(vertnodes[a].strand);
00747         if(vertnodes[a].tangent)
00748             MEM_freeN(vertnodes[a].tangent);
00749         if(vertnodes[a].stress)
00750             MEM_freeN(vertnodes[a].stress);
00751         if(vertnodes[a].winspeed)
00752             MEM_freeN(vertnodes[a].winspeed);
00753     }
00754     
00755     MEM_freeN(vertnodes);
00756 }
00757 
00758 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
00759 {
00760     int a;
00761     
00762     if(vlaknodes==NULL) return;
00763     
00764     for(a=0; vlaknodes[a].vlak; a++) {
00765         MEM_freeN(vlaknodes[a].vlak);
00766         
00767         if(vlaknodes[a].mtface)
00768             MEM_freeN(vlaknodes[a].mtface);
00769         if(vlaknodes[a].mcol)
00770             MEM_freeN(vlaknodes[a].mcol);
00771         if(vlaknodes[a].surfnor)
00772             MEM_freeN(vlaknodes[a].surfnor);
00773         if(vlaknodes[a].tangent)
00774             MEM_freeN(vlaknodes[a].tangent);
00775         if(vlaknodes[a].radface)
00776             MEM_freeN(vlaknodes[a].radface);
00777     }
00778     
00779     MEM_freeN(vlaknodes);
00780 }
00781 
00782 static void free_renderdata_strandnodes(StrandTableNode *strandnodes)
00783 {
00784     int a;
00785     
00786     if(strandnodes==NULL) return;
00787     
00788     for(a=0; strandnodes[a].strand; a++) {
00789         MEM_freeN(strandnodes[a].strand);
00790         
00791         if(strandnodes[a].uv)
00792             MEM_freeN(strandnodes[a].uv);
00793         if(strandnodes[a].mcol)
00794             MEM_freeN(strandnodes[a].mcol);
00795         if(strandnodes[a].winspeed)
00796             MEM_freeN(strandnodes[a].winspeed);
00797         if(strandnodes[a].surfnor)
00798             MEM_freeN(strandnodes[a].surfnor);
00799         if(strandnodes[a].simplify)
00800             MEM_freeN(strandnodes[a].simplify);
00801         if(strandnodes[a].face)
00802             MEM_freeN(strandnodes[a].face);
00803     }
00804     
00805     MEM_freeN(strandnodes);
00806 }
00807 
00808 void free_renderdata_tables(Render *re)
00809 {
00810     ObjectInstanceRen *obi;
00811     ObjectRen *obr;
00812     StrandBuffer *strandbuf;
00813     int a=0;
00814     
00815     for(obr=re->objecttable.first; obr; obr=obr->next) {
00816         if(obr->vertnodes) {
00817             free_renderdata_vertnodes(obr->vertnodes);
00818             obr->vertnodes= NULL;
00819             obr->vertnodeslen= 0;
00820         }
00821 
00822         if(obr->vlaknodes) {
00823             free_renderdata_vlaknodes(obr->vlaknodes);
00824             obr->vlaknodes= NULL;
00825             obr->vlaknodeslen= 0;
00826             obr->totvlak= 0;
00827         }
00828 
00829         if(obr->bloha) {
00830             for(a=0; obr->bloha[a]; a++)
00831                 MEM_freeN(obr->bloha[a]);
00832 
00833             MEM_freeN(obr->bloha);
00834             obr->bloha= NULL;
00835             obr->blohalen= 0;
00836         }
00837 
00838         if(obr->strandnodes) {
00839             free_renderdata_strandnodes(obr->strandnodes);
00840             obr->strandnodes= NULL;
00841             obr->strandnodeslen= 0;
00842         }
00843 
00844         strandbuf= obr->strandbuf;
00845         if(strandbuf) {
00846             if(strandbuf->vert) MEM_freeN(strandbuf->vert);
00847             if(strandbuf->bound) MEM_freeN(strandbuf->bound);
00848             MEM_freeN(strandbuf);
00849         }
00850 
00851         if(obr->mtface)
00852             MEM_freeN(obr->mtface);
00853         if(obr->mcol)
00854             MEM_freeN(obr->mcol);
00855             
00856         if(obr->rayfaces)
00857         {
00858             MEM_freeN(obr->rayfaces);
00859             obr->rayfaces = NULL;
00860         }
00861         if(obr->rayprimitives)
00862         {
00863             MEM_freeN(obr->rayprimitives);
00864             obr->rayprimitives = NULL;
00865         }
00866         if(obr->raytree)
00867         {
00868             RE_rayobject_free(obr->raytree);
00869             obr->raytree = NULL;
00870         }
00871     }
00872 
00873     if(re->objectinstance) {
00874         for(obi=re->instancetable.first; obi; obi=obi->next)
00875         {
00876             if(obi->vectors)
00877                 MEM_freeN(obi->vectors);
00878 
00879             if(obi->raytree)
00880                 RE_rayobject_free(obi->raytree);
00881         }
00882 
00883         MEM_freeN(re->objectinstance);
00884         re->objectinstance= NULL;
00885         re->totinstance= 0;
00886         re->instancetable.first= re->instancetable.last= NULL;
00887     }
00888 
00889     if(re->sortedhalos) {
00890         MEM_freeN(re->sortedhalos);
00891         re->sortedhalos= NULL;
00892     }
00893 
00894     BLI_freelistN(&re->customdata_names);
00895     BLI_freelistN(&re->objecttable);
00896     BLI_freelistN(&re->instancetable);
00897 }
00898 
00899 /* ------------------------------------------------------------------------ */
00900 
00901 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
00902 {
00903     HaloRen *h, **temp;
00904     int a;
00905 
00906     if(nr<0) {
00907         printf("error in findOrAddHalo: %d\n",nr);
00908         return NULL;
00909     }
00910     a= nr>>8;
00911     
00912     if (a>=obr->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
00913         //printf("Allocating %i more halo groups.  %i total.\n", 
00914         //  TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
00915         temp=obr->bloha;
00916         
00917         obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
00918         if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
00919         memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
00920         obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
00921         if(temp) MEM_freeN(temp);   
00922     }
00923     
00924     h= obr->bloha[a];
00925     if(h==NULL) {
00926         h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
00927         obr->bloha[a]= h;
00928     }
00929     h+= (nr & 255);
00930     return h;
00931 }
00932 
00933 /* ------------------------------------------------------------------------- */
00934 
00935 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   float *vec1, 
00936                   float *orco,   float hasize,   float vectsize, int seed)
00937 {
00938     HaloRen *har;
00939     MTex *mtex;
00940     float tin, tr, tg, tb, ta;
00941     float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
00942 
00943     if(hasize==0.0f) return NULL;
00944 
00945     projectverto(vec, re->winmat, hoco);
00946     if(hoco[3]==0.0f) return NULL;
00947     if(vec1) {
00948         projectverto(vec1, re->winmat, hoco1);
00949         if(hoco1[3]==0.0f) return NULL;
00950     }
00951 
00952     har= RE_findOrAddHalo(obr, obr->tothalo++);
00953     copy_v3_v3(har->co, vec);
00954     har->hasize= hasize;
00955 
00956     /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
00957     /* we do it here for sorting of halos */
00958     zn= hoco[3];
00959     har->xs= 0.5f*re->winx*(hoco[0]/zn);
00960     har->ys= 0.5f*re->winy*(hoco[1]/zn);
00961     har->zs= 0x7FFFFF*(hoco[2]/zn);
00962     
00963     har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
00964     
00965     /* halovect */
00966     if(vec1) {
00967 
00968         har->type |= HA_VECT;
00969 
00970         xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
00971         yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
00972         if(xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
00973         else zn= atan2(yn, xn);
00974 
00975         har->sin= sin(zn);
00976         har->cos= cos(zn);
00977         zn= len_v3v3(vec1, vec);
00978 
00979         har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
00980         
00981         sub_v3_v3v3(har->no, vec, vec1);
00982         normalize_v3(har->no);
00983     }
00984 
00985     if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
00986 
00987     har->alfa= ma->alpha;
00988     har->r= ma->r;
00989     har->g= ma->g;
00990     har->b= ma->b;
00991     har->add= (255.0f*ma->add);
00992     har->mat= ma;
00993     har->hard= ma->har;
00994     har->seed= seed % 256;
00995 
00996     if(ma->mode & MA_STAR) har->starpoints= ma->starc;
00997     if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
00998     if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
00999     if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
01000 
01001 
01002     if(ma->mtex[0]) {
01003 
01004         if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
01005         else if(har->mat->septex & (1<<0)); /* only 1 level textures */
01006         else {
01007 
01008             mtex= ma->mtex[0];
01009             copy_v3_v3(texvec, vec);
01010 
01011             if(mtex->texco & TEXCO_NORM) {
01012                 ;
01013             }
01014             else if(mtex->texco & TEXCO_OBJECT) {
01015                 /* texvec[0]+= imatbase->ivec[0]; */
01016                 /* texvec[1]+= imatbase->ivec[1]; */
01017                 /* texvec[2]+= imatbase->ivec[2]; */
01018                 /* mul_m3_v3(imatbase->imat, texvec); */
01019             }
01020             else {
01021                 if(orco) {
01022                     copy_v3_v3(texvec, orco);
01023                 }
01024             }
01025 
01026             externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
01027 
01028             yn= tin*mtex->colfac;
01029             //zn= tin*mtex->alphafac;
01030 
01031             if(mtex->mapto & MAP_COL) {
01032                 zn= 1.0f-yn;
01033                 har->r= (yn*tr+ zn*ma->r);
01034                 har->g= (yn*tg+ zn*ma->g);
01035                 har->b= (yn*tb+ zn*ma->b);
01036             }
01037             if(mtex->texco & TEXCO_UV) {
01038                 har->alfa= tin;
01039             }
01040             if(mtex->mapto & MAP_ALPHA)
01041                 har->alfa= tin;
01042         }
01043     }
01044 
01045     return har;
01046 }
01047 
01048 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
01049                   float *orco, float *uvco, float hasize, float vectsize, int seed, float *pa_co)
01050 {
01051     HaloRen *har;
01052     MTex *mtex;
01053     float tin, tr, tg, tb, ta;
01054     float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
01055     int i, hasrgb;
01056 
01057     if(hasize==0.0f) return NULL;
01058 
01059     projectverto(vec, re->winmat, hoco);
01060     if(hoco[3]==0.0f) return NULL;
01061     if(vec1) {
01062         projectverto(vec1, re->winmat, hoco1);
01063         if(hoco1[3]==0.0f) return NULL;
01064     }
01065 
01066     har= RE_findOrAddHalo(obr, obr->tothalo++);
01067     copy_v3_v3(har->co, vec);
01068     har->hasize= hasize;
01069 
01070     /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
01071     /* we do it here for sorting of halos */
01072     zn= hoco[3];
01073     har->xs= 0.5f*re->winx*(hoco[0]/zn);
01074     har->ys= 0.5f*re->winy*(hoco[1]/zn);
01075     har->zs= 0x7FFFFF*(hoco[2]/zn);
01076     
01077     har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
01078     
01079     /* halovect */
01080     if(vec1) {
01081 
01082         har->type |= HA_VECT;
01083 
01084         xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
01085         yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
01086         if(xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
01087         else zn= atan2(yn, xn);
01088 
01089         har->sin= sin(zn);
01090         har->cos= cos(zn);
01091         zn= len_v3v3(vec1, vec)*0.5f;
01092 
01093         har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
01094         
01095         sub_v3_v3v3(har->no, vec, vec1);
01096         normalize_v3(har->no);
01097     }
01098 
01099     if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
01100 
01101     har->alfa= ma->alpha;
01102     har->r= ma->r;
01103     har->g= ma->g;
01104     har->b= ma->b;
01105     har->add= (255.0f*ma->add);
01106     har->mat= ma;
01107     har->hard= ma->har;
01108     har->seed= seed % 256;
01109 
01110     if(ma->mode & MA_STAR) har->starpoints= ma->starc;
01111     if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
01112     if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
01113     if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
01114 
01115     if((ma->mode & MA_HALOTEX) && ma->mtex[0])
01116         har->tex= 1;
01117     
01118     for(i=0; i<MAX_MTEX; i++)
01119         if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
01120             mtex= ma->mtex[i];
01121             copy_v3_v3(texvec, vec);
01122 
01123             if(mtex->texco & TEXCO_NORM) {
01124                 ;
01125             }
01126             else if(mtex->texco & TEXCO_OBJECT) {
01127                 if(mtex->object)
01128                     mul_m4_v3(mtex->object->imat_ren,texvec);
01129             }
01130             else if(mtex->texco & TEXCO_GLOB){
01131                 copy_v3_v3(texvec,vec);
01132             }
01133             else if(mtex->texco & TEXCO_UV && uvco){
01134                 int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
01135                 if(uv_index<0)
01136                     uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
01137 
01138                 uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
01139 
01140                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
01141                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
01142                 texvec[2]=0.0f;
01143             }
01144             else if(mtex->texco & TEXCO_PARTICLE) {
01145                 /* particle coordinates in range [0,1] */
01146                 texvec[0] = 2.f * pa_co[0] - 1.f;
01147                 texvec[1] = 2.f * pa_co[1] - 1.f;
01148                 texvec[2] = pa_co[2];
01149             }
01150             else if(orco) {
01151                 copy_v3_v3(texvec, orco);
01152             }
01153 
01154             hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
01155 
01156             //yn= tin*mtex->colfac;
01157             //zn= tin*mtex->alphafac;
01158             if(mtex->mapto & MAP_COL) {
01159                 tex[0]=tr;
01160                 tex[1]=tg;
01161                 tex[2]=tb;
01162                 out[0]=har->r;
01163                 out[1]=har->g;
01164                 out[2]=har->b;
01165 
01166                 texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
01167             //  zn= 1.0-yn;
01168                 //har->r= (yn*tr+ zn*ma->r);
01169                 //har->g= (yn*tg+ zn*ma->g);
01170                 //har->b= (yn*tb+ zn*ma->b);
01171                 har->r= in[0];
01172                 har->g= in[1];
01173                 har->b= in[2];
01174             }
01175 
01176             /* alpha returned, so let's use it instead of intensity */
01177             if(hasrgb)
01178                 tin = ta;
01179 
01180             if(mtex->mapto & MAP_ALPHA)
01181                 har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->alphafac,mtex->blendtype);
01182             if(mtex->mapto & MAP_HAR)
01183                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var,((float)har->hard)/127.0f,tin,mtex->hardfac,mtex->blendtype);
01184             if(mtex->mapto & MAP_RAYMIRR)
01185                 har->hasize = 100.0f*texture_value_blend(mtex->def_var,har->hasize/100.0f,tin,mtex->raymirrfac,mtex->blendtype);
01186             if(mtex->mapto & MAP_TRANSLU) {
01187                 float add = texture_value_blend(mtex->def_var,(float)har->add/255.0f,tin,mtex->translfac,mtex->blendtype);
01188                 CLAMP(add, 0.f, 1.f);
01189                 har->add = 255.0f*add;
01190             }
01191             /* now what on earth is this good for?? */
01192             //if(mtex->texco & 16) {
01193             //  har->alfa= tin;
01194             //}
01195         }
01196 
01197     return har;
01198 }
01199 
01200 /* -------------------------- operations on entire database ----------------------- */
01201 
01202 /* ugly function for halos in panorama */
01203 static int panotestclip(Render *re, int do_pano, float *v)
01204 {
01205     /* to be used for halos en infos */
01206     float abs4;
01207     short c=0;
01208 
01209     if(do_pano==0) return testclip(v);
01210 
01211     abs4= fabs(v[3]);
01212 
01213     if(v[2]< -abs4) c=16;       /* this used to be " if(v[2]<0) ", see clippz() */
01214     else if(v[2]> abs4) c+= 32;
01215 
01216     if( v[1]>abs4) c+=4;
01217     else if( v[1]< -abs4) c+=8;
01218 
01219     abs4*= re->xparts;
01220     if( v[0]>abs4) c+=2;
01221     else if( v[0]< -abs4) c+=1;
01222 
01223     return c;
01224 }
01225 
01226 /*
01227   This adds the hcs coordinates to vertices. It iterates over all
01228   vertices, halos and faces. After the conversion, we clip in hcs.
01229 
01230   Elsewhere, all primites are converted to vertices. 
01231   Called in 
01232   - envmapping (envmap.c)
01233   - shadow buffering (shadbuf.c)
01234 */
01235 
01236 void project_renderdata(Render *re, void (*projectfunc)(const float *, float mat[][4], float *),  int do_pano, float xoffs, int UNUSED(do_buckets))
01237 {
01238     ObjectRen *obr;
01239     HaloRen *har = NULL;
01240     float zn, vec[3], hoco[4];
01241     int a;
01242 
01243     if(do_pano) {
01244         float panophi= xoffs;
01245         
01246         re->panosi= sin(panophi);
01247         re->panoco= cos(panophi);
01248     }
01249 
01250     for(obr=re->objecttable.first; obr; obr=obr->next) {
01251         /* calculate view coordinates (and zbuffer value) */
01252         for(a=0; a<obr->tothalo; a++) {
01253             if((a & 255)==0) har= obr->bloha[a>>8];
01254             else har++;
01255 
01256             if(do_pano) {
01257                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
01258                 vec[1]= har->co[1];
01259                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
01260             }
01261             else {
01262                 copy_v3_v3(vec, har->co);
01263             }
01264 
01265             projectfunc(vec, re->winmat, hoco);
01266             
01267             /* we clip halos less critical, but not for the Z */
01268             hoco[0]*= 0.5f;
01269             hoco[1]*= 0.5f;
01270             
01271             if( panotestclip(re, do_pano, hoco) ) {
01272                 har->miny= har->maxy= -10000;   /* that way render clips it */
01273             }
01274             else if(hoco[3]<0.0f) {
01275                 har->miny= har->maxy= -10000;   /* render clips it */
01276             }
01277             else /* do the projection...*/
01278             {
01279                 /* bring back hocos */
01280                 hoco[0]*= 2.0f;
01281                 hoco[1]*= 2.0f;
01282                 
01283                 zn= hoco[3];
01284                 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
01285                 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
01286             
01287                 /* this should be the zbuffer coordinate */
01288                 har->zs= 0x7FFFFF*(hoco[2]/zn);
01289                 /* taking this from the face clip functions? seems ok... */
01290                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
01291                 
01292                 vec[0]+= har->hasize;
01293                 projectfunc(vec, re->winmat, hoco);
01294                 vec[0]-= har->hasize;
01295                 zn= hoco[3];
01296                 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
01297             
01298                 /* this clip is not really OK, to prevent stars to become too large */
01299                 if(har->type & HA_ONLYSKY) {
01300                     if(har->rad>3.0f) har->rad= 3.0f;
01301                 }
01302             
01303                 har->radsq= har->rad*har->rad;
01304             
01305                 har->miny= har->ys - har->rad/re->ycor;
01306                 har->maxy= har->ys + har->rad/re->ycor;
01307             
01308                 /* the Zd value is still not really correct for pano */
01309             
01310                 vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
01311                 projectfunc(vec, re->winmat, hoco);
01312                 zn= hoco[3];
01313                 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
01314                 har->zd= CLAMPIS(zn, 0, INT_MAX);
01315             
01316             }
01317             
01318         }
01319     }
01320 }
01321 
01322 /* ------------------------------------------------------------------------- */
01323 
01324 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
01325 {
01326     ObjectInstanceRen *obi;
01327     float mat3[3][3];
01328 
01329     obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
01330     obi->obr= obr;
01331     obi->ob= ob;
01332     obi->par= par;
01333     obi->index= index;
01334     obi->psysindex= psysindex;
01335     obi->lay= lay;
01336 
01337     if(mat) {
01338         copy_m4_m4(obi->mat, mat);
01339         copy_m3_m4(mat3, mat);
01340         invert_m3_m3(obi->nmat, mat3);
01341         transpose_m3(obi->nmat);
01342         obi->flag |= R_DUPLI_TRANSFORMED;
01343     }
01344 
01345     BLI_addtail(&re->instancetable, obi);
01346 
01347     return obi;
01348 }
01349 
01350 void RE_makeRenderInstances(Render *re)
01351 {
01352     ObjectInstanceRen *obi, *oldobi;
01353     ListBase newlist;
01354     int tot;
01355 
01356     /* convert list of object instances to an array for index based lookup */
01357     tot= BLI_countlist(&re->instancetable);
01358     re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
01359     re->totinstance= tot;
01360     newlist.first= newlist.last= NULL;
01361 
01362     obi= re->objectinstance;
01363     for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
01364         *obi= *oldobi;
01365 
01366         if(obi->obr) {
01367             obi->prev= obi->next= NULL;
01368             BLI_addtail(&newlist, obi);
01369             obi++;
01370         }
01371         else
01372             re->totinstance--;
01373     }
01374 
01375     BLI_freelistN(&re->instancetable);
01376     re->instancetable= newlist;
01377 }
01378 
01379 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
01380 {
01381     float mat[4][4], vec[4];
01382     int a, fl, flag= -1;
01383 
01384     copy_m4_m4(mat, winmat);
01385 
01386     for(a=0; a<8; a++) {
01387         vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
01388         vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
01389         vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
01390         vec[3]= 1.0;
01391         mul_m4_v4(mat, vec);
01392 
01393         fl= 0;
01394         if(bounds) {
01395             if(vec[0] < bounds[0]*vec[3]) fl |= 1;
01396             else if(vec[0] > bounds[1]*vec[3]) fl |= 2;
01397             
01398             if(vec[1] > bounds[3]*vec[3]) fl |= 4;
01399             else if(vec[1]< bounds[2]*vec[3]) fl |= 8;
01400         }
01401         else {
01402             if(vec[0] < -vec[3]) fl |= 1;
01403             else if(vec[0] > vec[3]) fl |= 2;
01404             
01405             if(vec[1] > vec[3]) fl |= 4;
01406             else if(vec[1] < -vec[3]) fl |= 8;
01407         }
01408         if(vec[2] < -vec[3]) fl |= 16;
01409         else if(vec[2] > vec[3]) fl |= 32;
01410 
01411         flag &= fl;
01412         if(flag==0) return 0;
01413     }
01414 
01415     return flag;
01416 }
01417