4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): 2004-2006, Blender Foundation, full recode
25 * ***** END GPL/BL DUAL LICENSE BLOCK *****
29 * Storage, retrieval and query of render specific data.
31 * All data from a Blender scene is converted by the renderconverter/
32 * into a special format that is used by the render module to make
33 * images out of. These functions interface to the render-specific
36 * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
39 * The index of an entry is >>8 (the highest 24 * bits), to find an
40 * offset in a 256-entry block.
42 * - If the 256-entry block entry has an entry in the
43 * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in
44 * that block is allocated to this entry.
46 * - If the entry has no block allocated for it yet, memory is
49 * The pointer to the correct entry is returned. Memory is guarateed
50 * to exist (as long as the malloc does not break). Since guarded
51 * allocation is used, memory _must_ be available. Otherwise, an
52 * exit(0) would occur.
60 #include "MEM_guardedalloc.h"
61 #include "BKE_utildefines.h"
63 #include "BLI_arithb.h"
64 #include "BLI_blenlib.h"
65 #include "BLI_ghash.h"
66 #include "BLI_memarena.h"
68 #include "DNA_material_types.h"
69 #include "DNA_mesh_types.h"
70 #include "DNA_meshdata_types.h"
71 #include "DNA_texture_types.h"
73 #include "BKE_customdata.h"
74 #include "BKE_texture.h"
75 #include "BKE_DerivedMesh.h"
77 #include "RE_render_ext.h" /* externtex */
79 #include "renderpipeline.h"
80 #include "render_types.h"
81 #include "renderdatabase.h"
86 /* ------------------------------------------------------------------------- */
88 /* More dynamic allocation of options for render vertices and faces, so we dont
89 have to reserve this space inside vertices.
90 Important; vertices and faces, should have been created already (to get tables
91 checked) that's a reason why the calls demand VertRen/VlakRen * as arg, not
94 /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
96 #define RE_STICKY_ELEMS 2
97 #define RE_STRESS_ELEMS 1
98 #define RE_RAD_ELEMS 4
99 #define RE_STRAND_ELEMS 1
100 #define RE_TANGENT_ELEMS 3
101 #define RE_STRESS_ELEMS 1
102 #define RE_WINSPEED_ELEMS 4
103 #define RE_MTFACE_ELEMS 1
104 #define RE_MCOL_ELEMS 4
105 #define RE_UV_ELEMS 2
106 #define RE_SURFNOR_ELEMS 3
107 #define RE_RADFACE_ELEMS 1
108 #define RE_SIMPLIFY_ELEMS 2
109 #define RE_FACE_ELEMS 1
110 #define RE_NMAP_TANGENT_ELEMS 12
112 float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
115 int nr= ver->index>>8;
117 sticky= obr->vertnodes[nr].sticky;
120 sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
124 return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
127 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
130 int nr= ver->index>>8;
132 stress= obr->vertnodes[nr].stress;
135 stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
139 return stress + (ver->index & 255)*RE_STRESS_ELEMS;
142 /* this one callocs! */
143 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
146 int nr= ver->index>>8;
148 rad= obr->vertnodes[nr].rad;
151 rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
155 return rad + (ver->index & 255)*RE_RAD_ELEMS;
158 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
161 int nr= ver->index>>8;
163 strand= obr->vertnodes[nr].strand;
166 strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
170 return strand + (ver->index & 255)*RE_STRAND_ELEMS;
174 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
177 int nr= ver->index>>8;
179 tangent= obr->vertnodes[nr].tangent;
182 tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
186 return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
189 /* needs calloc! not all renderverts have them */
190 /* also winspeed is exception, it is stored per instance */
191 float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
196 winspeed= obi->vectors;
199 totvector= obi->obr->totvert + obi->obr->totstrand;
200 winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
205 return winspeed + ver->index*RE_WINSPEED_ELEMS;
208 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
210 VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
212 int index= v1->index;
217 fp1= RE_vertren_get_sticky(obr, ver, 0);
219 fp2= RE_vertren_get_sticky(obr, v1, 1);
220 memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
222 fp1= RE_vertren_get_stress(obr, ver, 0);
224 fp2= RE_vertren_get_stress(obr, v1, 1);
225 memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
227 fp1= RE_vertren_get_rad(obr, ver, 0);
229 fp2= RE_vertren_get_rad(obr, v1, 1);
230 memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
232 fp1= RE_vertren_get_strand(obr, ver, 0);
234 fp2= RE_vertren_get_strand(obr, v1, 1);
235 memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
237 fp1= RE_vertren_get_tangent(obr, ver, 0);
239 fp2= RE_vertren_get_tangent(obr, v1, 1);
240 memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
245 VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
252 printf("error in findOrAddVert: %d\n",nr);
257 if (a>=obr->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */
258 temp= obr->vertnodes;
260 obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE) , "vertnodes");
261 if(temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode));
262 memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
264 obr->vertnodeslen+=TABLEINITSIZE;
265 if(temp) MEM_freeN(temp);
268 v= obr->vertnodes[a].vert;
272 v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
273 obr->vertnodes[a].vert= v;
275 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
283 /* ------------------------------------------------------------------------ */
285 MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
288 int nr= vlr->index>>8, vlakindex= (vlr->index&255);
289 int index= (n<<8) + vlakindex;
291 node= &obr->vlaknodes[nr];
294 if(n>=node->totmtface) {
295 MTFace *mtface= node->mtface;
296 int size= size= (n+1)*256;
298 node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
301 size= node->totmtface*256;
302 memcpy(node->mtface, mtface, size*sizeof(MTFace));
306 node->totmtface= n+1;
310 if(n>=node->totmtface)
313 if(name) *name= obr->mtface[n];
316 return node->mtface + index;
319 MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
322 int nr= vlr->index>>8, vlakindex= (vlr->index&255);
323 int index= (n<<8) + vlakindex;
325 node= &obr->vlaknodes[nr];
328 if(n>=node->totmcol) {
329 MCol *mcol= node->mcol;
332 node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
335 size= node->totmcol*256;
336 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
347 if(name) *name= obr->mcol[n];
350 return node->mcol + index*RE_MCOL_ELEMS;
353 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
356 int nr= vlak->index>>8;
358 surfnor= obr->vlaknodes[nr].surfnor;
361 surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
365 return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
368 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
371 int nr= vlak->index>>8;
373 tangent= obr->vlaknodes[nr].tangent;
376 tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
380 return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
383 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
386 int nr= vlak->index>>8;
388 radface= obr->vlaknodes[nr].radface;
391 radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
395 return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
398 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
400 VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
401 MTFace *mtface, *mtface1;
403 float *surfnor, *surfnor1, *tangent, *tangent1;
404 RadFace **radface, **radface1;
405 int i, index = vlr1->index;
411 for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
412 mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
413 memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
416 for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
417 mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
418 memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
421 surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
423 surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
424 VECCOPY(surfnor1, surfnor);
427 tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
429 tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
430 memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
433 radface= RE_vlakren_get_radface(obr, vlr, 0);
435 radface1= RE_vlakren_get_radface(obr, vlr1, 1);
442 int RE_vlakren_get_normal(Render *re, ObjectInstanceRen *obi, VlakRen *vlr, float *nor)
444 float v1[3], (*nmat)[3]= obi->nmat;
447 if(obi->flag & R_TRANSFORMED) {
448 VECCOPY(nor, vlr->n);
450 Mat3MulVecfl(nmat, nor);
454 VECCOPY(nor, vlr->n);
456 if((vlr->flag & R_NOPUNOFLIP)==0) {
457 if(re->r.mode & R_ORTHO) {
462 VECCOPY(v1, vlr->v1->co);
463 if(obi->flag & R_TRANSFORMED)
464 Mat4MulVecfl(obi->mat, v1);
465 if(INPR(v1, nor) < 0.0f) {
480 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
482 /* CustomData layer names are stored per object here, because the
483 DerivedMesh which stores the layers is freed */
485 CustomDataLayer *layer;
486 int numtf = 0, numcol = 0, i, mtfn, mcn;
488 if (CustomData_has_layer(data, CD_MTFACE)) {
489 numtf= CustomData_number_of_layers(data, CD_MTFACE);
490 obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
493 if (CustomData_has_layer(data, CD_MCOL)) {
494 numcol= CustomData_number_of_layers(data, CD_MCOL);
495 obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
498 for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
499 layer= &data->layers[i];
501 if (layer->type == CD_MTFACE) {
502 strcpy(obr->mtface[mtfn++], layer->name);
503 obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
504 obr->bakemtface= layer->active;
506 else if (layer->type == CD_MCOL) {
507 strcpy(obr->mcol[mcn++], layer->name);
508 obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
513 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
520 printf("error in findOrAddVlak: %d\n",nr);
521 return obr->vlaknodes[0].vlak;
525 if (a>=obr->vlaknodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
526 temp= obr->vlaknodes;
528 obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
529 if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
530 memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
532 obr->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
533 if(temp) MEM_freeN(temp);
536 v= obr->vlaknodes[a].vlak;
541 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
542 obr->vlaknodes[a].vlak= v;
544 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
551 /* ------------------------------------------------------------------------ */
553 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
556 int nr= strand->index>>8;
558 surfnor= obr->strandnodes[nr].surfnor;
561 surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
565 return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
568 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
570 StrandTableNode *node;
571 int nr= strand->index>>8, strandindex= (strand->index&255);
572 int index= (n<<8) + strandindex;
574 node= &obr->strandnodes[nr];
581 node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
584 size= node->totuv*256;
585 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
596 if(name) *name= obr->mtface[n];
599 return node->uv + index*RE_UV_ELEMS;
602 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
604 StrandTableNode *node;
605 int nr= strand->index>>8, strandindex= (strand->index&255);
606 int index= (n<<8) + strandindex;
608 node= &obr->strandnodes[nr];
611 if(n>=node->totmcol) {
612 MCol *mcol= node->mcol;
615 node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
618 size= node->totmcol*256;
619 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
630 if(name) *name= obr->mcol[n];
633 return node->mcol + index*RE_MCOL_ELEMS;
636 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
639 int nr= strand->index>>8;
641 simplify= obr->strandnodes[nr].simplify;
644 simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
648 return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
651 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
654 int nr= strand->index>>8;
656 face= obr->strandnodes[nr].face;
659 face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
663 return face + (strand->index & 255)*RE_FACE_ELEMS;
666 /* winspeed is exception, it is stored per instance */
667 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
672 winspeed= obi->vectors;
675 totvector= obi->obr->totvert + obi->obr->totstrand;
676 winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
681 return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
684 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
686 StrandTableNode *temp;
691 printf("error in findOrAddStrand: %d\n",nr);
692 return obr->strandnodes[0].strand;
696 if (a>=obr->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
697 temp= obr->strandnodes;
699 obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes");
700 if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
701 memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
703 obr->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
704 if(temp) MEM_freeN(temp);
707 v= obr->strandnodes[a].strand;
712 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
713 obr->strandnodes[a].strand= v;
715 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
722 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
724 StrandBuffer *strandbuf;
726 strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
727 strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
728 strandbuf->totvert= totvert;
731 obr->strandbuf= strandbuf;
736 /* ------------------------------------------------------------------------ */
738 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
740 ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
742 BLI_addtail(&re->objecttable, obr);
746 obr->psysindex= psysindex;
752 void free_renderdata_vertnodes(VertTableNode *vertnodes)
756 if(vertnodes==NULL) return;
758 for(a=0; vertnodes[a].vert; a++) {
759 MEM_freeN(vertnodes[a].vert);
762 MEM_freeN(vertnodes[a].rad);
763 if(vertnodes[a].sticky)
764 MEM_freeN(vertnodes[a].sticky);
765 if(vertnodes[a].strand)
766 MEM_freeN(vertnodes[a].strand);
767 if(vertnodes[a].tangent)
768 MEM_freeN(vertnodes[a].tangent);
769 if(vertnodes[a].stress)
770 MEM_freeN(vertnodes[a].stress);
771 if(vertnodes[a].winspeed)
772 MEM_freeN(vertnodes[a].winspeed);
775 MEM_freeN(vertnodes);
778 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
782 if(vlaknodes==NULL) return;
784 for(a=0; vlaknodes[a].vlak; a++) {
785 MEM_freeN(vlaknodes[a].vlak);
787 if(vlaknodes[a].mtface)
788 MEM_freeN(vlaknodes[a].mtface);
789 if(vlaknodes[a].mcol)
790 MEM_freeN(vlaknodes[a].mcol);
791 if(vlaknodes[a].surfnor)
792 MEM_freeN(vlaknodes[a].surfnor);
793 if(vlaknodes[a].tangent)
794 MEM_freeN(vlaknodes[a].tangent);
795 if(vlaknodes[a].radface)
796 MEM_freeN(vlaknodes[a].radface);
799 MEM_freeN(vlaknodes);
802 void free_renderdata_strandnodes(StrandTableNode *strandnodes)
806 if(strandnodes==NULL) return;
808 for(a=0; strandnodes[a].strand; a++) {
809 MEM_freeN(strandnodes[a].strand);
811 if(strandnodes[a].uv)
812 MEM_freeN(strandnodes[a].uv);
813 if(strandnodes[a].mcol)
814 MEM_freeN(strandnodes[a].mcol);
815 if(strandnodes[a].winspeed)
816 MEM_freeN(strandnodes[a].winspeed);
817 if(strandnodes[a].surfnor)
818 MEM_freeN(strandnodes[a].surfnor);
819 if(strandnodes[a].simplify)
820 MEM_freeN(strandnodes[a].simplify);
821 if(strandnodes[a].face)
822 MEM_freeN(strandnodes[a].face);
825 MEM_freeN(strandnodes);
828 void free_renderdata_tables(Render *re)
830 ObjectInstanceRen *obi;
832 StrandBuffer *strandbuf;
835 for(obr=re->objecttable.first; obr; obr=obr->next) {
837 free_renderdata_vertnodes(obr->vertnodes);
838 obr->vertnodes= NULL;
839 obr->vertnodeslen= 0;
843 free_renderdata_vlaknodes(obr->vlaknodes);
844 obr->vlaknodes= NULL;
845 obr->vlaknodeslen= 0;
850 for(a=0; obr->bloha[a]; a++)
851 MEM_freeN(obr->bloha[a]);
853 MEM_freeN(obr->bloha);
858 if(obr->strandnodes) {
859 free_renderdata_strandnodes(obr->strandnodes);
860 obr->strandnodes= NULL;
861 obr->strandnodeslen= 0;
864 strandbuf= obr->strandbuf;
866 if(strandbuf->vert) MEM_freeN(strandbuf->vert);
867 if(strandbuf->bound) MEM_freeN(strandbuf->bound);
868 MEM_freeN(strandbuf);
872 MEM_freeN(obr->mtface);
874 MEM_freeN(obr->mcol);
877 if(re->objectinstance) {
878 for(obi=re->instancetable.first; obi; obi=obi->next)
880 MEM_freeN(obi->vectors);
882 MEM_freeN(re->objectinstance);
883 re->objectinstance= NULL;
885 re->instancetable.first= re->instancetable.last= NULL;
888 if(re->sortedhalos) {
889 MEM_freeN(re->sortedhalos);
890 re->sortedhalos= NULL;
893 BLI_freelistN(&re->customdata_names);
894 BLI_freelistN(&re->objecttable);
895 BLI_freelistN(&re->instancetable);
898 /* ------------------------------------------------------------------------ */
900 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
906 printf("error in findOrAddHalo: %d\n",nr);
911 if (a>=obr->blohalen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
912 //printf("Allocating %i more halo groups. %i total.\n",
913 // TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
916 obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
917 if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
918 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
919 obr->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
920 if(temp) MEM_freeN(temp);
925 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
932 /* ------------------------------------------------------------------------- */
934 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, float *vec, float *vec1,
935 float *orco, float hasize, float vectsize, int seed)
939 float tin, tr, tg, tb, ta;
940 float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
942 if(hasize==0.0) return NULL;
944 projectverto(vec, re->winmat, hoco);
945 if(hoco[3]==0.0) return NULL;
947 projectverto(vec1, re->winmat, hoco1);
948 if(hoco1[3]==0.0) return NULL;
951 har= RE_findOrAddHalo(obr, obr->tothalo++);
952 VECCOPY(har->co, vec);
955 /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
956 /* we do it here for sorting of halos */
958 har->xs= 0.5*re->winx*(hoco[0]/zn);
959 har->ys= 0.5*re->winy*(hoco[1]/zn);
960 har->zs= 0x7FFFFF*(hoco[2]/zn);
962 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
967 har->type |= HA_VECT;
969 xn= har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
970 yn= har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
971 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
972 else zn= atan2(yn, xn);
976 zn= VecLenf(vec1, vec);
978 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
980 VecSubf(har->no, vec, vec1);
984 if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
986 har->alfa= ma->alpha;
990 har->add= (255.0*ma->add);
993 har->seed= seed % 256;
995 if(ma->mode & MA_STAR) har->starpoints= ma->starc;
996 if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
997 if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
998 if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1003 if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
1007 VECCOPY(texvec, vec);
1009 if(mtex->texco & TEXCO_NORM) {
1012 else if(mtex->texco & TEXCO_OBJECT) {
1013 /* texvec[0]+= imatbase->ivec[0]; */
1014 /* texvec[1]+= imatbase->ivec[1]; */
1015 /* texvec[2]+= imatbase->ivec[2]; */
1016 /* Mat3MulVecfl(imatbase->imat, texvec); */
1020 VECCOPY(texvec, orco);
1024 externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
1026 yn= tin*mtex->colfac;
1027 zn= tin*mtex->varfac;
1029 if(mtex->mapto & MAP_COL) {
1031 har->r= (yn*tr+ zn*ma->r);
1032 har->g= (yn*tg+ zn*ma->g);
1033 har->b= (yn*tb+ zn*ma->b);
1035 if(mtex->texco & TEXCO_UV) {
1038 if(mtex->mapto & MAP_ALPHA)
1046 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, float *vec, float *vec1,
1047 float *orco, float *uvco, float hasize, float vectsize, int seed)
1051 float tin, tr, tg, tb, ta;
1052 float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
1055 if(hasize==0.0) return NULL;
1057 projectverto(vec, re->winmat, hoco);
1058 if(hoco[3]==0.0) return NULL;
1060 projectverto(vec1, re->winmat, hoco1);
1061 if(hoco1[3]==0.0) return NULL;
1064 har= RE_findOrAddHalo(obr, obr->tothalo++);
1065 VECCOPY(har->co, vec);
1066 har->hasize= hasize;
1068 /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1069 /* we do it here for sorting of halos */
1071 har->xs= 0.5*re->winx*(hoco[0]/zn);
1072 har->ys= 0.5*re->winy*(hoco[1]/zn);
1073 har->zs= 0x7FFFFF*(hoco[2]/zn);
1075 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1080 har->type |= HA_VECT;
1082 xn= har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
1083 yn= har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
1084 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
1085 else zn= atan2(yn, xn);
1089 zn= VecLenf(vec1, vec)*0.5;
1091 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
1093 VecSubf(har->no, vec, vec1);
1097 if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1099 har->alfa= ma->alpha;
1103 har->add= (255.0*ma->add);
1106 har->seed= seed % 256;
1108 if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1109 if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1110 if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1111 if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1113 if((ma->mode & MA_HALOTEX) && ma->mtex[0]){
1118 for(i=0; i<MAX_MTEX; i++)
1119 if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
1121 VECCOPY(texvec, vec);
1123 if(mtex->texco & TEXCO_NORM) {
1126 else if(mtex->texco & TEXCO_OBJECT) {
1129 /* imat should really be cached somewhere before this */
1130 Mat4Invert(imat,mtex->object->obmat);
1131 Mat4MulVecfl(imat,texvec);
1133 /* texvec[0]+= imatbase->ivec[0]; */
1134 /* texvec[1]+= imatbase->ivec[1]; */
1135 /* texvec[2]+= imatbase->ivec[2]; */
1136 /* Mat3MulVecfl(imatbase->imat, texvec); */
1138 else if(mtex->texco & TEXCO_GLOB){
1139 VECCOPY(texvec,vec);
1141 else if(mtex->texco & TEXCO_UV && uvco){
1142 int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
1144 uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
1146 uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
1148 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1149 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1153 VECCOPY(texvec, orco);
1156 externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
1158 //yn= tin*mtex->colfac;
1159 //zn= tin*mtex->varfac;
1160 if(mtex->mapto & MAP_COL) {
1168 texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
1170 //har->r= (yn*tr+ zn*ma->r);
1171 //har->g= (yn*tg+ zn*ma->g);
1172 //har->b= (yn*tb+ zn*ma->b);
1177 if(mtex->mapto & MAP_ALPHA)
1178 har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_ALPHA);
1179 if(mtex->mapto & MAP_HAR)
1180 har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_HAR);
1181 if(mtex->mapto & MAP_RAYMIRR)
1182 har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_RAYMIRR);
1183 /* now what on earth is this good for?? */
1184 //if(mtex->texco & 16) {
1192 /* -------------------------- operations on entire database ----------------------- */
1194 /* ugly function for halos in panorama */
1195 static int panotestclip(Render *re, int do_pano, float *v)
1197 /* to be used for halos en infos */
1201 if(do_pano==0) return testclip(v);
1205 if(v[2]< -abs4) c=16; /* this used to be " if(v[2]<0) ", see clippz() */
1206 else if(v[2]> abs4) c+= 32;
1208 if( v[1]>abs4) c+=4;
1209 else if( v[1]< -abs4) c+=8;
1212 if( v[0]>abs4) c+=2;
1213 else if( v[0]< -abs4) c+=1;
1219 This adds the hcs coordinates to vertices. It iterates over all
1220 vertices, halos and faces. After the conversion, we clip in hcs.
1222 Elsewhere, all primites are converted to vertices.
1224 - envmapping (envmap.c)
1225 - shadow buffering (shadbuf.c)
1228 void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets)
1231 HaloRen *har = NULL;
1232 float zn, vec[3], hoco[4];
1236 float panophi= xoffs;
1238 re->panosi= sin(panophi);
1239 re->panoco= cos(panophi);
1242 for(obr=re->objecttable.first; obr; obr=obr->next) {
1243 /* calculate view coordinates (and zbuffer value) */
1244 for(a=0; a<obr->tothalo; a++) {
1245 if((a & 255)==0) har= obr->bloha[a>>8];
1249 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1251 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1254 VECCOPY(vec, har->co);
1257 projectfunc(vec, re->winmat, hoco);
1259 /* we clip halos less critical, but not for the Z */
1263 if( panotestclip(re, do_pano, hoco) ) {
1264 har->miny= har->maxy= -10000; /* that way render clips it */
1266 else if(hoco[3]<0.0) {
1267 har->miny= har->maxy= -10000; /* render clips it */
1269 else /* do the projection...*/
1271 /* bring back hocos */
1276 har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1277 har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
1279 /* this should be the zbuffer coordinate */
1280 har->zs= 0x7FFFFF*(hoco[2]/zn);
1281 /* taking this from the face clip functions? seems ok... */
1282 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1284 vec[0]+= har->hasize;
1285 projectfunc(vec, re->winmat, hoco);
1286 vec[0]-= har->hasize;
1288 har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
1290 /* this clip is not really OK, to prevent stars to become too large */
1291 if(har->type & HA_ONLYSKY) {
1292 if(har->rad>3.0) har->rad= 3.0;
1295 har->radsq= har->rad*har->rad;
1297 har->miny= har->ys - har->rad/re->ycor;
1298 har->maxy= har->ys + har->rad/re->ycor;
1300 /* the Zd value is still not really correct for pano */
1302 vec[2]-= har->hasize; /* z negative, otherwise it's clipped */
1303 projectfunc(vec, re->winmat, hoco);
1305 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
1306 har->zd= CLAMPIS(zn, 0, INT_MAX);
1314 /* ------------------------------------------------------------------------- */
1316 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
1318 ObjectInstanceRen *obi;
1321 obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1326 obi->psysindex= psysindex;
1330 Mat4CpyMat4(obi->mat, mat);
1331 Mat3CpyMat4(mat3, mat);
1332 Mat3Inv(obi->nmat, mat3);
1333 Mat3Transp(obi->nmat);
1334 obi->flag |= R_DUPLI_TRANSFORMED;
1337 BLI_addtail(&re->instancetable, obi);
1342 void RE_makeRenderInstances(Render *re)
1344 ObjectInstanceRen *obi, *oldobi;
1348 /* convert list of object instances to an array for index based lookup */
1349 tot= BLI_countlist(&re->instancetable);
1350 re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1351 re->totinstance= tot;
1352 newlist.first= newlist.last= NULL;
1354 obi= re->objectinstance;
1355 for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1359 obi->prev= obi->next= NULL;
1360 BLI_addtail(&newlist, obi);
1367 BLI_freelistN(&re->instancetable);
1368 re->instancetable= newlist;
1371 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
1373 float mat[4][4], vec[4];
1374 int a, fl, flag= -1;
1376 Mat4CpyMat4(mat, winmat);
1378 for(a=0; a<8; a++) {
1379 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1380 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1381 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1383 Mat4MulVec4fl(mat, vec);
1387 if(vec[0] > bounds[1]*vec[3]) fl |= 1;
1388 if(vec[0]< bounds[0]*vec[3]) fl |= 2;
1389 if(vec[1] > bounds[3]*vec[3]) fl |= 4;
1390 if(vec[1]< bounds[2]*vec[3]) fl |= 8;
1393 if(vec[0] < -vec[3]) fl |= 1;
1394 if(vec[0] > vec[3]) fl |= 2;
1395 if(vec[1] < -vec[3]) fl |= 4;
1396 if(vec[1] > vec[3]) fl |= 8;
1398 if(vec[2] < -vec[3]) fl |= 16;
1399 if(vec[2] > vec[3]) fl |= 32;
1402 if(flag==0) return 0;