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