2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): 2004-2006, Blender Foundation, full recode
23 * ***** END GPL/BL DUAL LICENSE BLOCK *****
26 /** \file blender/render/intern/source/renderdatabase.c
32 * Storage, retrieval and query of render specific data.
34 * All data from a Blender scene is converted by the renderconverter/
35 * into a special format that is used by the render module to make
36 * images out of. These functions interface to the render-specific
39 * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
42 * The index of an entry is >>8 (the highest 24 * bits), to find an
43 * offset in a 256-entry block.
45 * - If the 256-entry block entry has an entry in the
46 * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in
47 * that block is allocated to this entry.
49 * - If the entry has no block allocated for it yet, memory is
52 * The pointer to the correct entry is returned. Memory is guarateed
53 * to exist (as long as the malloc does not break). Since guarded
54 * allocation is used, memory _must_ be available. Otherwise, an
55 * exit(0) would occur.
63 #include "MEM_guardedalloc.h"
67 #include "BLI_blenlib.h"
68 #include "BLI_utildefines.h"
69 #include "BLI_ghash.h"
70 #include "BLI_memarena.h"
72 #include "DNA_material_types.h"
73 #include "DNA_mesh_types.h"
74 #include "DNA_meshdata_types.h"
75 #include "DNA_texture_types.h"
77 #include "BKE_customdata.h"
78 #include "BKE_texture.h"
79 #include "BKE_DerivedMesh.h"
81 #include "RE_render_ext.h" /* externtex */
83 #include "rayobject.h"
84 #include "renderpipeline.h"
85 #include "render_types.h"
86 #include "renderdatabase.h"
91 /* ------------------------------------------------------------------------- */
93 /* More dynamic allocation of options for render vertices and faces, so we don't
94 * have to reserve this space inside vertices.
95 * Important; vertices and faces, should have been created already (to get tables
96 * checked) that's a reason why the calls demand VertRen/VlakRen * as arg, not
99 /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
101 #define RE_STICKY_ELEMS 2
102 #define RE_STRESS_ELEMS 1
103 #define RE_RAD_ELEMS 4
104 #define RE_STRAND_ELEMS 1
105 #define RE_TANGENT_ELEMS 3
106 #define RE_STRESS_ELEMS 1
107 #define RE_WINSPEED_ELEMS 4
108 #define RE_MTFACE_ELEMS 1
109 #define RE_MCOL_ELEMS 4
110 #define RE_UV_ELEMS 2
111 #define RE_SURFNOR_ELEMS 3
112 #define RE_RADFACE_ELEMS 1
113 #define RE_SIMPLIFY_ELEMS 2
114 #define RE_FACE_ELEMS 1
115 #define RE_NMAP_TANGENT_ELEMS 16
117 float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
120 int nr= ver->index>>8;
122 sticky= obr->vertnodes[nr].sticky;
125 sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
129 return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
132 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
135 int nr= ver->index>>8;
137 stress= obr->vertnodes[nr].stress;
140 stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
144 return stress + (ver->index & 255)*RE_STRESS_ELEMS;
147 /* this one callocs! */
148 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
151 int nr= ver->index>>8;
153 rad= obr->vertnodes[nr].rad;
156 rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
160 return rad + (ver->index & 255)*RE_RAD_ELEMS;
163 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
166 int nr= ver->index>>8;
168 strand= obr->vertnodes[nr].strand;
171 strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
175 return strand + (ver->index & 255)*RE_STRAND_ELEMS;
179 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
182 int nr= ver->index>>8;
184 tangent= obr->vertnodes[nr].tangent;
187 tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
191 return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
194 /* needs calloc! not all renderverts have them */
195 /* also winspeed is exception, it is stored per instance */
196 float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
201 winspeed= obi->vectors;
202 if (winspeed==NULL) {
204 totvector= obi->obr->totvert + obi->obr->totstrand;
205 winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
210 return winspeed + ver->index*RE_WINSPEED_ELEMS;
213 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
215 VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
217 int index= v1->index;
222 fp1= RE_vertren_get_sticky(obr, ver, 0);
224 fp2= RE_vertren_get_sticky(obr, v1, 1);
225 memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
227 fp1= RE_vertren_get_stress(obr, ver, 0);
229 fp2= RE_vertren_get_stress(obr, v1, 1);
230 memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
232 fp1= RE_vertren_get_rad(obr, ver, 0);
234 fp2= RE_vertren_get_rad(obr, v1, 1);
235 memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
237 fp1= RE_vertren_get_strand(obr, ver, 0);
239 fp2= RE_vertren_get_strand(obr, v1, 1);
240 memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
242 fp1= RE_vertren_get_tangent(obr, ver, 0);
244 fp2= RE_vertren_get_tangent(obr, v1, 1);
245 memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
250 VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
257 printf("error in findOrAddVert: %d\n", nr);
262 if (a>=obr->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */
263 temp= obr->vertnodes;
265 obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE), "vertnodes");
266 if (temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode));
267 memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
269 obr->vertnodeslen+=TABLEINITSIZE;
270 if (temp) MEM_freeN(temp);
273 v= obr->vertnodes[a].vert;
277 v= (VertRen *)MEM_callocN(256*sizeof(VertRen), "findOrAddVert");
278 obr->vertnodes[a].vert= v;
280 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
288 /* ------------------------------------------------------------------------ */
290 MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
293 int nr= vlr->index>>8, vlakindex= (vlr->index&255);
294 int index= (n<<8) + vlakindex;
296 node= &obr->vlaknodes[nr];
299 if (n>=node->totmtface) {
300 MTFace *mtface= node->mtface;
303 node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
306 size= node->totmtface*256;
307 memcpy(node->mtface, mtface, size*sizeof(MTFace));
311 node->totmtface= n+1;
315 if (n>=node->totmtface)
318 if (name) *name= obr->mtface[n];
321 return node->mtface + index;
324 MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
327 int nr= vlr->index>>8, vlakindex= (vlr->index&255);
328 int index= (n<<8) + vlakindex;
330 node= &obr->vlaknodes[nr];
333 if (n>=node->totmcol) {
334 MCol *mcol= node->mcol;
337 node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
340 size= node->totmcol*256;
341 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
349 if (n>=node->totmcol)
352 if (name) *name= obr->mcol[n];
355 return node->mcol + index*RE_MCOL_ELEMS;
358 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
361 int nr= vlak->index>>8;
363 surfnor= obr->vlaknodes[nr].surfnor;
366 surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
370 return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
373 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
376 int nr= vlak->index>>8;
378 tangent= obr->vlaknodes[nr].tangent;
381 tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
385 return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
388 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
391 int nr= vlak->index>>8;
393 radface= obr->vlaknodes[nr].radface;
396 radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
400 return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
403 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
405 VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
406 MTFace *mtface, *mtface1;
408 float *surfnor, *surfnor1, *tangent, *tangent1;
409 RadFace **radface, **radface1;
410 int i, index = vlr1->index;
416 for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
417 mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
418 memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
421 for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
422 mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
423 memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
426 surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
428 surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
429 copy_v3_v3(surfnor1, surfnor);
432 tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
434 tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
435 memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
438 radface= RE_vlakren_get_radface(obr, vlr, 0);
440 radface1= RE_vlakren_get_radface(obr, vlr1, 1);
447 void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float *nor)
449 float (*nmat)[3]= obi->nmat;
451 if (obi->flag & R_TRANSFORMED) {
452 mul_v3_m3v3(nor, nmat, vlr->n);
456 copy_v3_v3(nor, vlr->n);
460 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
462 /* CustomData layer names are stored per object here, because the
463 * DerivedMesh which stores the layers is freed */
465 CustomDataLayer *layer;
466 int numtf = 0, numcol = 0, i, mtfn, mcn;
468 if (CustomData_has_layer(data, CD_MTFACE)) {
469 numtf= CustomData_number_of_layers(data, CD_MTFACE);
470 obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
473 if (CustomData_has_layer(data, CD_MCOL)) {
474 numcol= CustomData_number_of_layers(data, CD_MCOL);
475 obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
478 for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
479 layer= &data->layers[i];
481 if (layer->type == CD_MTFACE) {
482 BLI_strncpy(obr->mtface[mtfn++], layer->name, sizeof(layer->name));
483 obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
484 obr->bakemtface= layer->active;
486 else if (layer->type == CD_MCOL) {
487 BLI_strncpy(obr->mcol[mcn++], layer->name, sizeof(layer->name));
488 obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
493 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
500 printf("error in findOrAddVlak: %d\n", nr);
501 return obr->vlaknodes[0].vlak;
505 if (a>=obr->vlaknodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */
506 temp= obr->vlaknodes;
508 obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE), "vlaknodes");
509 if (temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
510 memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
512 obr->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
513 if (temp) MEM_freeN(temp);
516 v= obr->vlaknodes[a].vlak;
521 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen), "findOrAddVlak");
522 obr->vlaknodes[a].vlak= v;
524 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
531 /* ------------------------------------------------------------------------ */
533 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
536 int nr= strand->index>>8;
538 surfnor= obr->strandnodes[nr].surfnor;
541 surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
545 return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
548 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
550 StrandTableNode *node;
551 int nr= strand->index>>8, strandindex= (strand->index&255);
552 int index= (n<<8) + strandindex;
554 node= &obr->strandnodes[nr];
557 if (n>=node->totuv) {
561 node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
564 size= node->totuv*256;
565 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
576 if (name) *name= obr->mtface[n];
579 return node->uv + index*RE_UV_ELEMS;
582 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
584 StrandTableNode *node;
585 int nr= strand->index>>8, strandindex= (strand->index&255);
586 int index= (n<<8) + strandindex;
588 node= &obr->strandnodes[nr];
591 if (n>=node->totmcol) {
592 MCol *mcol= node->mcol;
595 node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
598 size= node->totmcol*256;
599 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
607 if (n>=node->totmcol)
610 if (name) *name= obr->mcol[n];
613 return node->mcol + index*RE_MCOL_ELEMS;
616 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
619 int nr= strand->index>>8;
621 simplify= obr->strandnodes[nr].simplify;
622 if (simplify==NULL) {
624 simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
628 return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
631 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
634 int nr= strand->index>>8;
636 face= obr->strandnodes[nr].face;
639 face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
643 return face + (strand->index & 255)*RE_FACE_ELEMS;
646 /* winspeed is exception, it is stored per instance */
647 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
652 winspeed= obi->vectors;
653 if (winspeed==NULL) {
655 totvector= obi->obr->totvert + obi->obr->totstrand;
656 winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
661 return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
664 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
666 StrandTableNode *temp;
671 printf("error in findOrAddStrand: %d\n", nr);
672 return obr->strandnodes[0].strand;
676 if (a>=obr->strandnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */
677 temp= obr->strandnodes;
679 obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE), "strandnodes");
680 if (temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
681 memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
683 obr->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
684 if (temp) MEM_freeN(temp);
687 v= obr->strandnodes[a].strand;
692 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen), "findOrAddStrand");
693 obr->strandnodes[a].strand= v;
695 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
702 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
704 StrandBuffer *strandbuf;
706 strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
707 strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
708 strandbuf->totvert= totvert;
711 obr->strandbuf= strandbuf;
716 /* ------------------------------------------------------------------------ */
718 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
720 ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
722 BLI_addtail(&re->objecttable, obr);
726 obr->psysindex= psysindex;
732 void free_renderdata_vertnodes(VertTableNode *vertnodes)
736 if (vertnodes==NULL) return;
738 for (a=0; vertnodes[a].vert; a++) {
739 MEM_freeN(vertnodes[a].vert);
741 if (vertnodes[a].rad)
742 MEM_freeN(vertnodes[a].rad);
743 if (vertnodes[a].sticky)
744 MEM_freeN(vertnodes[a].sticky);
745 if (vertnodes[a].strand)
746 MEM_freeN(vertnodes[a].strand);
747 if (vertnodes[a].tangent)
748 MEM_freeN(vertnodes[a].tangent);
749 if (vertnodes[a].stress)
750 MEM_freeN(vertnodes[a].stress);
751 if (vertnodes[a].winspeed)
752 MEM_freeN(vertnodes[a].winspeed);
755 MEM_freeN(vertnodes);
758 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
762 if (vlaknodes==NULL) return;
764 for (a=0; vlaknodes[a].vlak; a++) {
765 MEM_freeN(vlaknodes[a].vlak);
767 if (vlaknodes[a].mtface)
768 MEM_freeN(vlaknodes[a].mtface);
769 if (vlaknodes[a].mcol)
770 MEM_freeN(vlaknodes[a].mcol);
771 if (vlaknodes[a].surfnor)
772 MEM_freeN(vlaknodes[a].surfnor);
773 if (vlaknodes[a].tangent)
774 MEM_freeN(vlaknodes[a].tangent);
775 if (vlaknodes[a].radface)
776 MEM_freeN(vlaknodes[a].radface);
779 MEM_freeN(vlaknodes);
782 static void free_renderdata_strandnodes(StrandTableNode *strandnodes)
786 if (strandnodes==NULL) return;
788 for (a=0; strandnodes[a].strand; a++) {
789 MEM_freeN(strandnodes[a].strand);
791 if (strandnodes[a].uv)
792 MEM_freeN(strandnodes[a].uv);
793 if (strandnodes[a].mcol)
794 MEM_freeN(strandnodes[a].mcol);
795 if (strandnodes[a].winspeed)
796 MEM_freeN(strandnodes[a].winspeed);
797 if (strandnodes[a].surfnor)
798 MEM_freeN(strandnodes[a].surfnor);
799 if (strandnodes[a].simplify)
800 MEM_freeN(strandnodes[a].simplify);
801 if (strandnodes[a].face)
802 MEM_freeN(strandnodes[a].face);
805 MEM_freeN(strandnodes);
808 void free_renderdata_tables(Render *re)
810 ObjectInstanceRen *obi;
812 StrandBuffer *strandbuf;
815 for (obr=re->objecttable.first; obr; obr=obr->next) {
816 if (obr->vertnodes) {
817 free_renderdata_vertnodes(obr->vertnodes);
818 obr->vertnodes= NULL;
819 obr->vertnodeslen= 0;
822 if (obr->vlaknodes) {
823 free_renderdata_vlaknodes(obr->vlaknodes);
824 obr->vlaknodes= NULL;
825 obr->vlaknodeslen= 0;
830 for (a=0; obr->bloha[a]; a++)
831 MEM_freeN(obr->bloha[a]);
833 MEM_freeN(obr->bloha);
838 if (obr->strandnodes) {
839 free_renderdata_strandnodes(obr->strandnodes);
840 obr->strandnodes= NULL;
841 obr->strandnodeslen= 0;
844 strandbuf= obr->strandbuf;
846 if (strandbuf->vert) MEM_freeN(strandbuf->vert);
847 if (strandbuf->bound) MEM_freeN(strandbuf->bound);
848 MEM_freeN(strandbuf);
852 MEM_freeN(obr->mtface);
855 MEM_freeN(obr->mcol);
858 MEM_freeN(obr->rayfaces);
859 obr->rayfaces = NULL;
862 if (obr->rayprimitives) {
863 MEM_freeN(obr->rayprimitives);
864 obr->rayprimitives = NULL;
868 RE_rayobject_free(obr->raytree);
873 if (re->objectinstance) {
874 for (obi=re->instancetable.first; obi; obi=obi->next) {
876 MEM_freeN(obi->vectors);
879 RE_rayobject_free(obi->raytree);
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.0f) return NULL;
944 projectverto(vec, re->winmat, hoco);
945 if (hoco[3]==0.0f) return NULL;
947 projectverto(vec1, re->winmat, hoco1);
948 if (hoco1[3]==0.0f) return NULL;
951 har= RE_findOrAddHalo(obr, obr->tothalo++);
952 copy_v3_v3(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.5f*re->winx*(hoco[0]/zn);
959 har->ys= 0.5f*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.5f*re->winx*(hoco1[0]/hoco1[3]);
970 yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
971 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
972 else zn= atan2(yn, xn);
976 zn= len_v3v3(vec1, vec);
978 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
980 sub_v3_v3v3(har->no, vec, vec1);
981 normalize_v3(har->no);
984 if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
986 har->alfa= ma->alpha;
990 har->add= (255.0f*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;
1004 else if (har->mat->septex & (1<<0)); /* only 1 level textures */
1008 copy_v3_v3(texvec, vec);
1010 if (mtex->texco & TEXCO_NORM) {
1013 else if (mtex->texco & TEXCO_OBJECT) {
1014 /* texvec[0]+= imatbase->ivec[0]; */
1015 /* texvec[1]+= imatbase->ivec[1]; */
1016 /* texvec[2]+= imatbase->ivec[2]; */
1017 /* mul_m3_v3(imatbase->imat, texvec); */
1021 copy_v3_v3(texvec, orco);
1025 externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1027 yn= tin*mtex->colfac;
1028 //zn= tin*mtex->alphafac;
1030 if (mtex->mapto & MAP_COL) {
1032 har->r= (yn*tr+ zn*ma->r);
1033 har->g= (yn*tg+ zn*ma->g);
1034 har->b= (yn*tb+ zn*ma->b);
1036 if (mtex->texco & TEXCO_UV) {
1039 if (mtex->mapto & MAP_ALPHA)
1047 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, float *vec, float *vec1,
1048 float *orco, float *uvco, float hasize, float vectsize, int seed, float *pa_co)
1052 float tin, tr, tg, tb, ta;
1053 float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3];
1056 if (hasize==0.0f) return NULL;
1058 projectverto(vec, re->winmat, hoco);
1059 if (hoco[3]==0.0f) return NULL;
1061 projectverto(vec1, re->winmat, hoco1);
1062 if (hoco1[3]==0.0f) return NULL;
1065 har= RE_findOrAddHalo(obr, obr->tothalo++);
1066 copy_v3_v3(har->co, vec);
1067 har->hasize= hasize;
1069 /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1070 /* we do it here for sorting of halos */
1072 har->xs= 0.5f*re->winx*(hoco[0]/zn);
1073 har->ys= 0.5f*re->winy*(hoco[1]/zn);
1074 har->zs= 0x7FFFFF*(hoco[2]/zn);
1076 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1081 har->type |= HA_VECT;
1083 xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1084 yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1085 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1086 else zn= atan2(yn, xn);
1090 zn= len_v3v3(vec1, vec)*0.5f;
1092 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1094 sub_v3_v3v3(har->no, vec, vec1);
1095 normalize_v3(har->no);
1098 if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1100 har->alfa= ma->alpha;
1104 har->add= (255.0f*ma->add);
1107 har->seed= seed % 256;
1109 if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1110 if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1111 if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1112 if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1114 if ((ma->mode & MA_HALOTEX) && ma->mtex[0])
1117 for (i=0; i<MAX_MTEX; i++)
1118 if (ma->mtex[i] && (ma->septex & (1<<i))==0) {
1120 copy_v3_v3(texvec, vec);
1122 if (mtex->texco & TEXCO_NORM) {
1125 else if (mtex->texco & TEXCO_OBJECT) {
1127 mul_m4_v3(mtex->object->imat_ren, texvec);
1129 else if (mtex->texco & TEXCO_GLOB) {
1130 copy_v3_v3(texvec, vec);
1132 else if (mtex->texco & TEXCO_UV && uvco) {
1133 int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname);
1135 uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
1137 uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
1139 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1140 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1143 else if (mtex->texco & TEXCO_PARTICLE) {
1144 /* particle coordinates in range [0, 1] */
1145 texvec[0] = 2.f * pa_co[0] - 1.f;
1146 texvec[1] = 2.f * pa_co[1] - 1.f;
1147 texvec[2] = pa_co[2];
1150 copy_v3_v3(texvec, orco);
1153 hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1155 //yn= tin*mtex->colfac;
1156 //zn= tin*mtex->alphafac;
1157 if (mtex->mapto & MAP_COL) {
1165 texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype);
1167 //har->r= (yn*tr+ zn*ma->r);
1168 //har->g= (yn*tg+ zn*ma->g);
1169 //har->b= (yn*tb+ zn*ma->b);
1175 /* alpha returned, so let's use it instead of intensity */
1179 if (mtex->mapto & MAP_ALPHA)
1180 har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype);
1181 if (mtex->mapto & MAP_HAR)
1182 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype);
1183 if (mtex->mapto & MAP_RAYMIRR)
1184 har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype);
1185 if (mtex->mapto & MAP_TRANSLU) {
1186 float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype);
1187 CLAMP(add, 0.f, 1.f);
1188 har->add = 255.0f*add;
1190 /* now what on earth is this good for?? */
1191 //if (mtex->texco & 16) {
1199 /* -------------------------- operations on entire database ----------------------- */
1201 /* ugly function for halos in panorama */
1202 static int panotestclip(Render *re, int do_pano, float *v)
1204 /* to be used for halos en infos */
1208 if (do_pano == FALSE) {
1214 if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */
1215 else if (v[2]> abs4) c+= 32;
1217 if ( v[1]>abs4) c+=4;
1218 else if ( v[1]< -abs4) c+=8;
1221 if ( v[0]>abs4) c+=2;
1222 else if ( v[0]< -abs4) c+=1;
1228 * This adds the hcs coordinates to vertices. It iterates over all
1229 * vertices, halos and faces. After the conversion, we clip in hcs.
1231 * Elsewhere, all primites are converted to vertices.
1233 * - envmapping (envmap.c)
1234 * - shadow buffering (shadbuf.c)
1237 void project_renderdata(Render *re, void (*projectfunc)(const float *, float mat[][4], float *), int do_pano, float xoffs, int UNUSED(do_buckets))
1240 HaloRen *har = NULL;
1241 float zn, vec[3], hoco[4];
1245 float panophi= xoffs;
1247 re->panosi= sin(panophi);
1248 re->panoco= cos(panophi);
1251 for (obr=re->objecttable.first; obr; obr=obr->next) {
1252 /* calculate view coordinates (and zbuffer value) */
1253 for (a=0; a<obr->tothalo; a++) {
1254 if ((a & 255)==0) har= obr->bloha[a>>8];
1258 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1260 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1263 copy_v3_v3(vec, har->co);
1266 projectfunc(vec, re->winmat, hoco);
1268 /* we clip halos less critical, but not for the Z */
1272 if ( panotestclip(re, do_pano, hoco) ) {
1273 har->miny= har->maxy= -10000; /* that way render clips it */
1275 else if (hoco[3]<0.0f) {
1276 har->miny= har->maxy= -10000; /* render clips it */
1278 else { /* do the projection...*/
1279 /* bring back hocos */
1284 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1285 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
1287 /* this should be the zbuffer coordinate */
1288 har->zs= 0x7FFFFF*(hoco[2]/zn);
1289 /* taking this from the face clip functions? seems ok... */
1290 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1292 vec[0]+= har->hasize;
1293 projectfunc(vec, re->winmat, hoco);
1294 vec[0]-= har->hasize;
1296 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
1298 /* this clip is not really OK, to prevent stars to become too large */
1299 if (har->type & HA_ONLYSKY) {
1300 if (har->rad>3.0f) har->rad= 3.0f;
1303 har->radsq= har->rad*har->rad;
1305 har->miny= har->ys - har->rad/re->ycor;
1306 har->maxy= har->ys + har->rad/re->ycor;
1308 /* the Zd value is still not really correct for pano */
1310 vec[2]-= har->hasize; /* z negative, otherwise it's clipped */
1311 projectfunc(vec, re->winmat, hoco);
1313 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
1314 har->zd= CLAMPIS(zn, 0, INT_MAX);
1322 /* ------------------------------------------------------------------------- */
1324 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
1326 ObjectInstanceRen *obi;
1329 obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1334 obi->psysindex= psysindex;
1338 copy_m4_m4(obi->mat, mat);
1339 copy_m3_m4(mat3, mat);
1340 invert_m3_m3(obi->nmat, mat3);
1341 transpose_m3(obi->nmat);
1342 obi->flag |= R_DUPLI_TRANSFORMED;
1345 BLI_addtail(&re->instancetable, obi);
1350 void RE_makeRenderInstances(Render *re)
1352 ObjectInstanceRen *obi, *oldobi;
1356 /* convert list of object instances to an array for index based lookup */
1357 tot= BLI_countlist(&re->instancetable);
1358 re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1359 re->totinstance= tot;
1360 newlist.first= newlist.last= NULL;
1362 obi= re->objectinstance;
1363 for (oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1367 obi->prev= obi->next= NULL;
1368 BLI_addtail(&newlist, obi);
1375 BLI_freelistN(&re->instancetable);
1376 re->instancetable= newlist;
1379 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
1381 float mat[4][4], vec[4];
1382 int a, fl, flag= -1;
1384 copy_m4_m4(mat, winmat);
1386 for (a=0; a<8; a++) {
1387 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1388 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1389 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1391 mul_m4_v4(mat, vec);
1395 if (vec[0] < bounds[0]*vec[3]) fl |= 1;
1396 else if (vec[0] > bounds[1]*vec[3]) fl |= 2;
1398 if (vec[1] > bounds[3]*vec[3]) fl |= 4;
1399 else if (vec[1]< bounds[2]*vec[3]) fl |= 8;
1402 if (vec[0] < -vec[3]) fl |= 1;
1403 else if (vec[0] > vec[3]) fl |= 2;
1405 if (vec[1] > vec[3]) fl |= 4;
1406 else if (vec[1] < -vec[3]) fl |= 8;
1408 if (vec[2] < -vec[3]) fl |= 16;
1409 else if (vec[2] > vec[3]) fl |= 32;
1412 if (flag==0) return 0;