style cleanup
[blender.git] / source / blender / render / intern / source / renderdatabase.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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. 
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): 2004-2006, Blender Foundation, full recode
22  *
23  * ***** END GPL/BL DUAL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/renderdatabase.c
27  *  \ingroup render
28  */
29
30
31 /*
32  * Storage, retrieval and query of render specific data.
33  *
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
37  * database.  
38  *
39  * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
40  * entries each.
41  *
42  * The index of an entry is >>8 (the highest 24 * bits), to find an
43  * offset in a 256-entry block.
44  *
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.
48  *
49  * - If the entry has no block allocated for it yet, memory is
50  * allocated.
51  *
52  * The pointer to the correct entry is returned. Memory is guaranteed
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.
56  * 
57  */
58
59 #include <limits.h>
60 #include <math.h>
61 #include <string.h>
62
63 #include "MEM_guardedalloc.h"
64
65
66 #include "BLI_math.h"
67 #include "BLI_blenlib.h"
68 #include "BLI_utildefines.h"
69 #include "BLI_ghash.h"
70 #include "BLI_memarena.h"
71
72 #include "DNA_material_types.h" 
73 #include "DNA_mesh_types.h" 
74 #include "DNA_meshdata_types.h" 
75 #include "DNA_texture_types.h" 
76
77 #include "BKE_customdata.h"
78 #include "BKE_texture.h" 
79 #include "BKE_DerivedMesh.h"
80
81 #include "RE_render_ext.h"      /* externtex */
82
83 #include "rayobject.h"
84 #include "renderpipeline.h"
85 #include "render_types.h"
86 #include "renderdatabase.h"
87 #include "texture.h"
88 #include "strand.h"
89 #include "zbuf.h"
90
91 /* ------------------------------------------------------------------------- */
92
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
97  * the index */
98
99 /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
100 #define RE_STRESS_ELEMS         1
101 #define RE_RAD_ELEMS            4
102 #define RE_STRAND_ELEMS         1
103 #define RE_TANGENT_ELEMS        3
104 #define RE_WINSPEED_ELEMS       4
105 #define RE_MTFACE_ELEMS         1
106 #define RE_MCOL_ELEMS           4
107 #define RE_UV_ELEMS                     2
108 #define RE_VLAK_ORIGINDEX_ELEMS 1
109 #define RE_VERT_ORIGINDEX_ELEMS 1
110 #define RE_SURFNOR_ELEMS        3
111 #define RE_RADFACE_ELEMS        1
112 #define RE_SIMPLIFY_ELEMS       2
113 #define RE_FACE_ELEMS           1
114 #define RE_NMAP_TANGENT_ELEMS   16
115
116 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
117 {
118         float *stress;
119         int nr= ver->index>>8;
120         
121         stress= obr->vertnodes[nr].stress;
122         if (stress==NULL) {
123                 if (verify) 
124                         stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
125                 else
126                         return NULL;
127         }
128         return stress + (ver->index & 255)*RE_STRESS_ELEMS;
129 }
130
131 /* this one callocs! */
132 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
133 {
134         float *rad;
135         int nr= ver->index>>8;
136         
137         rad= obr->vertnodes[nr].rad;
138         if (rad==NULL) {
139                 if (verify) 
140                         rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
141                 else
142                         return NULL;
143         }
144         return rad + (ver->index & 255)*RE_RAD_ELEMS;
145 }
146
147 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
148 {
149         float *strand;
150         int nr= ver->index>>8;
151         
152         strand= obr->vertnodes[nr].strand;
153         if (strand==NULL) {
154                 if (verify) 
155                         strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
156                 else
157                         return NULL;
158         }
159         return strand + (ver->index & 255)*RE_STRAND_ELEMS;
160 }
161
162 /* needs calloc */
163 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
164 {
165         float *tangent;
166         int nr= ver->index>>8;
167         
168         tangent= obr->vertnodes[nr].tangent;
169         if (tangent==NULL) {
170                 if (verify) 
171                         tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
172                 else
173                         return NULL;
174         }
175         return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
176 }
177
178 /* needs calloc! not all renderverts have them */
179 /* also winspeed is exception, it is stored per instance */
180 float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
181 {
182         float *winspeed;
183         int totvector;
184         
185         winspeed= obi->vectors;
186         if (winspeed==NULL) {
187                 if (verify) {
188                         totvector= obi->obr->totvert + obi->obr->totstrand;
189                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
190                 }
191                 else
192                         return NULL;
193         }
194         return winspeed + ver->index*RE_WINSPEED_ELEMS;
195 }
196
197 int *RE_vertren_get_origindex(ObjectRen *obr, VertRen *ver, int verify)
198 {
199         int *origindex;
200         int nr= ver->index>>8;
201
202         origindex= obr->vertnodes[nr].origindex;
203         if (origindex==NULL) {
204                 if (verify)
205                         origindex= obr->vertnodes[nr].origindex= MEM_mallocN(256*RE_VERT_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
206                 else
207                         return NULL;
208         }
209         return origindex + (ver->index & 255)*RE_VERT_ORIGINDEX_ELEMS;
210 }
211
212 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
213 {
214         VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
215         float *fp1, *fp2;
216         int *int1, *int2;
217         int index= v1->index;
218         
219         *v1= *ver;
220         v1->index= index;
221
222         fp1= RE_vertren_get_stress(obr, ver, 0);
223         if (fp1) {
224                 fp2= RE_vertren_get_stress(obr, v1, 1);
225                 memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
226         }
227         fp1= RE_vertren_get_rad(obr, ver, 0);
228         if (fp1) {
229                 fp2= RE_vertren_get_rad(obr, v1, 1);
230                 memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
231         }
232         fp1= RE_vertren_get_strand(obr, ver, 0);
233         if (fp1) {
234                 fp2= RE_vertren_get_strand(obr, v1, 1);
235                 memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
236         }
237         fp1= RE_vertren_get_tangent(obr, ver, 0);
238         if (fp1) {
239                 fp2= RE_vertren_get_tangent(obr, v1, 1);
240                 memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
241         }
242         int1= RE_vertren_get_origindex(obr, ver, 0);
243         if (int1) {
244                 int2= RE_vertren_get_origindex(obr, v1, 1);
245                 memcpy(int2, int1, RE_VERT_ORIGINDEX_ELEMS*sizeof(int));
246         }
247         return v1;
248 }
249
250 VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
251 {
252         VertTableNode *temp;
253         VertRen *v;
254         int a;
255
256         if (nr<0) {
257                 printf("error in findOrAddVert: %d\n", nr);
258                 return NULL;
259         }
260         a= nr>>8;
261         
262         if (a>=obr->vertnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
263                 temp= obr->vertnodes;
264                 
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));
268                 
269                 obr->vertnodeslen+=TABLEINITSIZE; 
270                 if (temp) MEM_freeN(temp);
271         }
272         
273         v= obr->vertnodes[a].vert;
274         if (v==NULL) {
275                 int i;
276                 
277                 v= (VertRen *)MEM_callocN(256*sizeof(VertRen), "findOrAddVert");
278                 obr->vertnodes[a].vert= v;
279                 
280                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
281                         v[a].index= i;
282                 }
283         }
284         v+= (nr & 255);
285         return v;
286 }
287
288 /* ------------------------------------------------------------------------ */
289
290 MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
291 {
292         VlakTableNode *node;
293         int nr= vlr->index>>8, vlakindex= (vlr->index&255);
294         int index= (n<<8) + vlakindex;
295
296         node= &obr->vlaknodes[nr];
297
298         if (verify) {
299                 if (n>=node->totmtface) {
300                         MTFace *mtface= node->mtface;
301                         int size= (n+1)*256;
302
303                         node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
304
305                         if (mtface) {
306                                 size= node->totmtface*256;
307                                 memcpy(node->mtface, mtface, size*sizeof(MTFace));
308                                 MEM_freeN(mtface);
309                         }
310
311                         node->totmtface= n+1;
312                 }
313         }
314         else {
315                 if (n>=node->totmtface)
316                         return NULL;
317
318                 if (name) *name= obr->mtface[n];
319         }
320
321         return node->mtface + index;
322 }
323
324 MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
325 {
326         VlakTableNode *node;
327         int nr= vlr->index>>8, vlakindex= (vlr->index&255);
328         int index= (n<<8) + vlakindex;
329
330         node= &obr->vlaknodes[nr];
331
332         if (verify) {
333                 if (n>=node->totmcol) {
334                         MCol *mcol= node->mcol;
335                         int size= (n+1)*256;
336
337                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
338
339                         if (mcol) {
340                                 size= node->totmcol*256;
341                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
342                                 MEM_freeN(mcol);
343                         }
344
345                         node->totmcol= n+1;
346                 }
347         }
348         else {
349                 if (n>=node->totmcol)
350                         return NULL;
351
352                 if (name) *name= obr->mcol[n];
353         }
354
355         return node->mcol + index*RE_MCOL_ELEMS;
356 }
357
358 int *RE_vlakren_get_origindex(ObjectRen *obr, VlakRen *vlak, int verify)
359 {
360         int *origindex;
361         int nr= vlak->index>>8;
362
363         origindex= obr->vlaknodes[nr].origindex;
364         if (origindex==NULL) {
365                 if (verify)
366                         origindex= obr->vlaknodes[nr].origindex= MEM_callocN(256*RE_VLAK_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
367                 else
368                         return NULL;
369         }
370         return origindex + (vlak->index & 255)*RE_VLAK_ORIGINDEX_ELEMS;
371 }
372
373 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
374 {
375         float *surfnor;
376         int nr= vlak->index>>8;
377         
378         surfnor= obr->vlaknodes[nr].surfnor;
379         if (surfnor==NULL) {
380                 if (verify) 
381                         surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
382                 else
383                         return NULL;
384         }
385         return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
386 }
387
388 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
389 {
390         float *tangent;
391         int nr= vlak->index>>8;
392
393         tangent= obr->vlaknodes[nr].tangent;
394         if (tangent==NULL) {
395                 if (verify) 
396                         tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
397                 else
398                         return NULL;
399         }
400         return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
401 }
402
403 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
404 {
405         RadFace **radface;
406         int nr= vlak->index>>8;
407         
408         radface= obr->vlaknodes[nr].radface;
409         if (radface==NULL) {
410                 if (verify) 
411                         radface = obr->vlaknodes[nr].radface= MEM_callocN(256 * RE_RADFACE_ELEMS * sizeof(void *), "radface table");
412                 else
413                         return NULL;
414         }
415         return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
416 }
417
418 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
419 {
420         VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
421         MTFace *mtface, *mtface1;
422         MCol *mcol, *mcol1;
423         float *surfnor, *surfnor1, *tangent, *tangent1;
424         int *origindex, *origindex1;
425         RadFace **radface, **radface1;
426         int i, index = vlr1->index;
427         char *name;
428
429         *vlr1= *vlr;
430         vlr1->index= index;
431
432         for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
433                 mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
434                 memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
435         }
436
437         for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
438                 mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
439                 memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
440         }
441
442         origindex= RE_vlakren_get_origindex(obr, vlr, 0);
443         if (origindex) {
444                 origindex1= RE_vlakren_get_origindex(obr, vlr1, 1);
445                 /* Just an int, but memcpy for consistency. */
446                 memcpy(origindex1, origindex, sizeof(int)*RE_VLAK_ORIGINDEX_ELEMS);
447         }
448
449         surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
450         if (surfnor) {
451                 surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
452                 copy_v3_v3(surfnor1, surfnor);
453         }
454
455         tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
456         if (tangent) {
457                 tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
458                 memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
459         }
460
461         radface= RE_vlakren_get_radface(obr, vlr, 0);
462         if (radface) {
463                 radface1= RE_vlakren_get_radface(obr, vlr1, 1);
464                 *radface1= *radface;
465         }
466
467         return vlr1;
468 }
469
470 void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float r_nor[3])
471 {
472         float (*nmat)[3]= obi->nmat;
473
474         if (obi->flag & R_TRANSFORMED) {
475                 mul_v3_m3v3(r_nor, nmat, vlr->n);
476                 normalize_v3(r_nor);
477         }
478         else {
479                 copy_v3_v3(r_nor, vlr->n);
480         }
481 }
482
483 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
484 {
485         /* CustomData layer names are stored per object here, because the
486          * DerivedMesh which stores the layers is freed */
487         
488         CustomDataLayer *layer;
489         int numtf = 0, numcol = 0, i, mtfn, mcn;
490
491         if (CustomData_has_layer(data, CD_MTFACE)) {
492                 numtf= CustomData_number_of_layers(data, CD_MTFACE);
493                 obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
494         }
495
496         if (CustomData_has_layer(data, CD_MCOL)) {
497                 numcol= CustomData_number_of_layers(data, CD_MCOL);
498                 obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
499         }
500
501         for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
502                 layer= &data->layers[i];
503
504                 if (layer->type == CD_MTFACE) {
505                         BLI_strncpy(obr->mtface[mtfn++], layer->name, sizeof(layer->name));
506                         obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
507                         obr->bakemtface= layer->active;
508                 }
509                 else if (layer->type == CD_MCOL) {
510                         BLI_strncpy(obr->mcol[mcn++], layer->name, sizeof(layer->name));
511                         obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
512                 }
513         }
514 }
515
516 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
517 {
518         VlakTableNode *temp;
519         VlakRen *v;
520         int a;
521
522         if (nr<0) {
523                 printf("error in findOrAddVlak: %d\n", nr);
524                 return obr->vlaknodes[0].vlak;
525         }
526         a= nr>>8;
527         
528         if (a>=obr->vlaknodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
529                 temp= obr->vlaknodes;
530                 
531                 obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE), "vlaknodes");
532                 if (temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
533                 memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
534
535                 obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
536                 if (temp) MEM_freeN(temp);
537         }
538
539         v= obr->vlaknodes[a].vlak;
540         
541         if (v==NULL) {
542                 int i;
543
544                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen), "findOrAddVlak");
545                 obr->vlaknodes[a].vlak= v;
546
547                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
548                         v[a].index= i;
549         }
550         v+= (nr & 255);
551         return v;
552 }
553
554 /* ------------------------------------------------------------------------ */
555
556 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
557 {
558         float *surfnor;
559         int nr= strand->index>>8;
560         
561         surfnor= obr->strandnodes[nr].surfnor;
562         if (surfnor==NULL) {
563                 if (verify) 
564                         surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
565                 else
566                         return NULL;
567         }
568         return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
569 }
570
571 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
572 {
573         StrandTableNode *node;
574         int nr= strand->index>>8, strandindex= (strand->index&255);
575         int index= (n<<8) + strandindex;
576
577         node= &obr->strandnodes[nr];
578
579         if (verify) {
580                 if (n>=node->totuv) {
581                         float *uv= node->uv;
582                         int size= (n+1)*256;
583
584                         node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
585
586                         if (uv) {
587                                 size= node->totuv*256;
588                                 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
589                                 MEM_freeN(uv);
590                         }
591
592                         node->totuv= n+1;
593                 }
594         }
595         else {
596                 if (n>=node->totuv)
597                         return NULL;
598
599                 if (name) *name= obr->mtface[n];
600         }
601
602         return node->uv + index*RE_UV_ELEMS;
603 }
604
605 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
606 {
607         StrandTableNode *node;
608         int nr= strand->index>>8, strandindex= (strand->index&255);
609         int index= (n<<8) + strandindex;
610
611         node= &obr->strandnodes[nr];
612
613         if (verify) {
614                 if (n>=node->totmcol) {
615                         MCol *mcol= node->mcol;
616                         int size= (n+1)*256;
617
618                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
619
620                         if (mcol) {
621                                 size= node->totmcol*256;
622                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
623                                 MEM_freeN(mcol);
624                         }
625
626                         node->totmcol= n+1;
627                 }
628         }
629         else {
630                 if (n>=node->totmcol)
631                         return NULL;
632
633                 if (name) *name= obr->mcol[n];
634         }
635
636         return node->mcol + index*RE_MCOL_ELEMS;
637 }
638
639 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
640 {
641         float *simplify;
642         int nr= strand->index>>8;
643         
644         simplify= obr->strandnodes[nr].simplify;
645         if (simplify==NULL) {
646                 if (verify) 
647                         simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
648                 else
649                         return NULL;
650         }
651         return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
652 }
653
654 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
655 {
656         int *face;
657         int nr= strand->index>>8;
658         
659         face= obr->strandnodes[nr].face;
660         if (face==NULL) {
661                 if (verify) 
662                         face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
663                 else
664                         return NULL;
665         }
666         return face + (strand->index & 255)*RE_FACE_ELEMS;
667 }
668
669 /* winspeed is exception, it is stored per instance */
670 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
671 {
672         float *winspeed;
673         int totvector;
674         
675         winspeed= obi->vectors;
676         if (winspeed==NULL) {
677                 if (verify) {
678                         totvector= obi->obr->totvert + obi->obr->totstrand;
679                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
680                 }
681                 else
682                         return NULL;
683         }
684         return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
685 }
686
687 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
688 {
689         StrandTableNode *temp;
690         StrandRen *v;
691         int a;
692
693         if (nr<0) {
694                 printf("error in findOrAddStrand: %d\n", nr);
695                 return obr->strandnodes[0].strand;
696         }
697         a= nr>>8;
698         
699         if (a>=obr->strandnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
700                 temp= obr->strandnodes;
701                 
702                 obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE), "strandnodes");
703                 if (temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
704                 memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
705
706                 obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
707                 if (temp) MEM_freeN(temp);
708         }
709
710         v= obr->strandnodes[a].strand;
711         
712         if (v==NULL) {
713                 int i;
714
715                 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen), "findOrAddStrand");
716                 obr->strandnodes[a].strand= v;
717
718                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
719                         v[a].index= i;
720         }
721         v+= (nr & 255);
722         return v;
723 }
724
725 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
726 {
727         StrandBuffer *strandbuf;
728
729         strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
730         strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
731         strandbuf->totvert= totvert;
732         strandbuf->obr= obr;
733
734         obr->strandbuf= strandbuf;
735
736         return strandbuf;
737 }
738
739 /* ------------------------------------------------------------------------ */
740
741 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
742 {
743         ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
744         
745         BLI_addtail(&re->objecttable, obr);
746         obr->ob= ob;
747         obr->par= par;
748         obr->index= index;
749         obr->psysindex= psysindex;
750         obr->lay= lay;
751
752         return obr;
753 }
754
755 void free_renderdata_vertnodes(VertTableNode *vertnodes)
756 {
757         int a;
758         
759         if (vertnodes==NULL) return;
760         
761         for (a=0; vertnodes[a].vert; a++) {
762                 MEM_freeN(vertnodes[a].vert);
763                 
764                 if (vertnodes[a].rad)
765                         MEM_freeN(vertnodes[a].rad);
766                 if (vertnodes[a].strand)
767                         MEM_freeN(vertnodes[a].strand);
768                 if (vertnodes[a].tangent)
769                         MEM_freeN(vertnodes[a].tangent);
770                 if (vertnodes[a].stress)
771                         MEM_freeN(vertnodes[a].stress);
772                 if (vertnodes[a].winspeed)
773                         MEM_freeN(vertnodes[a].winspeed);
774                 if (vertnodes[a].origindex)
775                         MEM_freeN(vertnodes[a].origindex);
776         }
777         
778         MEM_freeN(vertnodes);
779 }
780
781 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
782 {
783         int a;
784         
785         if (vlaknodes==NULL) return;
786         
787         for (a=0; vlaknodes[a].vlak; a++) {
788                 MEM_freeN(vlaknodes[a].vlak);
789                 
790                 if (vlaknodes[a].mtface)
791                         MEM_freeN(vlaknodes[a].mtface);
792                 if (vlaknodes[a].mcol)
793                         MEM_freeN(vlaknodes[a].mcol);
794                 if (vlaknodes[a].origindex)
795                         MEM_freeN(vlaknodes[a].origindex);
796                 if (vlaknodes[a].surfnor)
797                         MEM_freeN(vlaknodes[a].surfnor);
798                 if (vlaknodes[a].tangent)
799                         MEM_freeN(vlaknodes[a].tangent);
800                 if (vlaknodes[a].radface)
801                         MEM_freeN(vlaknodes[a].radface);
802         }
803         
804         MEM_freeN(vlaknodes);
805 }
806
807 static void free_renderdata_strandnodes(StrandTableNode *strandnodes)
808 {
809         int a;
810         
811         if (strandnodes==NULL) return;
812         
813         for (a=0; strandnodes[a].strand; a++) {
814                 MEM_freeN(strandnodes[a].strand);
815                 
816                 if (strandnodes[a].uv)
817                         MEM_freeN(strandnodes[a].uv);
818                 if (strandnodes[a].mcol)
819                         MEM_freeN(strandnodes[a].mcol);
820                 if (strandnodes[a].winspeed)
821                         MEM_freeN(strandnodes[a].winspeed);
822                 if (strandnodes[a].surfnor)
823                         MEM_freeN(strandnodes[a].surfnor);
824                 if (strandnodes[a].simplify)
825                         MEM_freeN(strandnodes[a].simplify);
826                 if (strandnodes[a].face)
827                         MEM_freeN(strandnodes[a].face);
828         }
829         
830         MEM_freeN(strandnodes);
831 }
832
833 void free_renderdata_tables(Render *re)
834 {
835         ObjectInstanceRen *obi;
836         ObjectRen *obr;
837         StrandBuffer *strandbuf;
838         int a=0;
839         
840         for (obr=re->objecttable.first; obr; obr=obr->next) {
841                 if (obr->vertnodes) {
842                         free_renderdata_vertnodes(obr->vertnodes);
843                         obr->vertnodes= NULL;
844                         obr->vertnodeslen= 0;
845                 }
846
847                 if (obr->vlaknodes) {
848                         free_renderdata_vlaknodes(obr->vlaknodes);
849                         obr->vlaknodes= NULL;
850                         obr->vlaknodeslen= 0;
851                         obr->totvlak= 0;
852                 }
853
854                 if (obr->bloha) {
855                         for (a=0; obr->bloha[a]; a++)
856                                 MEM_freeN(obr->bloha[a]);
857
858                         MEM_freeN(obr->bloha);
859                         obr->bloha= NULL;
860                         obr->blohalen= 0;
861                 }
862
863                 if (obr->strandnodes) {
864                         free_renderdata_strandnodes(obr->strandnodes);
865                         obr->strandnodes= NULL;
866                         obr->strandnodeslen= 0;
867                 }
868
869                 strandbuf= obr->strandbuf;
870                 if (strandbuf) {
871                         if (strandbuf->vert) MEM_freeN(strandbuf->vert);
872                         if (strandbuf->bound) MEM_freeN(strandbuf->bound);
873                         MEM_freeN(strandbuf);
874                 }
875
876                 if (obr->mtface)
877                         MEM_freeN(obr->mtface);
878
879                 if (obr->mcol)
880                         MEM_freeN(obr->mcol);
881                         
882                 if (obr->rayfaces) {
883                         MEM_freeN(obr->rayfaces);
884                         obr->rayfaces = NULL;
885                 }
886
887                 if (obr->rayprimitives) {
888                         MEM_freeN(obr->rayprimitives);
889                         obr->rayprimitives = NULL;
890                 }
891
892                 if (obr->raytree) {
893                         RE_rayobject_free(obr->raytree);
894                         obr->raytree = NULL;
895                 }
896         }
897
898         if (re->objectinstance) {
899                 for (obi=re->instancetable.first; obi; obi=obi->next) {
900                         if (obi->vectors)
901                                 MEM_freeN(obi->vectors);
902
903                         if (obi->raytree)
904                                 RE_rayobject_free(obi->raytree);
905                 }
906
907                 MEM_freeN(re->objectinstance);
908                 re->objectinstance= NULL;
909                 re->totinstance= 0;
910                 re->instancetable.first= re->instancetable.last= NULL;
911         }
912
913         if (re->sortedhalos) {
914                 MEM_freeN(re->sortedhalos);
915                 re->sortedhalos= NULL;
916         }
917
918         BLI_freelistN(&re->customdata_names);
919         BLI_freelistN(&re->objecttable);
920         BLI_freelistN(&re->instancetable);
921 }
922
923 /* ------------------------------------------------------------------------ */
924
925 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
926 {
927         HaloRen *h, **temp;
928         int a;
929
930         if (nr<0) {
931                 printf("error in findOrAddHalo: %d\n", nr);
932                 return NULL;
933         }
934         a= nr>>8;
935         
936         if (a>=obr->blohalen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
937                 //printf("Allocating %i more halo groups.  %i total.\n", 
938                 //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
939                 temp=obr->bloha;
940                 
941                 obr->bloha = (HaloRen **)MEM_callocN(sizeof(void *) * (obr->blohalen + TABLEINITSIZE), "Bloha");
942                 if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void *));
943                 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE * sizeof(void *));
944                 obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
945                 if (temp) MEM_freeN(temp);
946         }
947         
948         h= obr->bloha[a];
949         if (h==NULL) {
950                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen), "findOrAdHalo");
951                 obr->bloha[a]= h;
952         }
953         h+= (nr & 255);
954         return h;
955 }
956
957 /* ------------------------------------------------------------------------- */
958
959 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
960                      const float vec[3], const float vec1[3],
961                      const float *orco, float hasize, float vectsize, int seed)
962 {
963         HaloRen *har;
964         MTex *mtex;
965         float tin, tr, tg, tb, ta;
966         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
967
968         if (hasize==0.0f) return NULL;
969
970         projectverto(vec, re->winmat, hoco);
971         if (hoco[3]==0.0f) return NULL;
972         if (vec1) {
973                 projectverto(vec1, re->winmat, hoco1);
974                 if (hoco1[3]==0.0f) return NULL;
975         }
976
977         har= RE_findOrAddHalo(obr, obr->tothalo++);
978         copy_v3_v3(har->co, vec);
979         har->hasize= hasize;
980
981         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
982         /* we do it here for sorting of halos */
983         zn= hoco[3];
984         har->xs= 0.5f*re->winx*(hoco[0]/zn);
985         har->ys= 0.5f*re->winy*(hoco[1]/zn);
986         har->zs= 0x7FFFFF*(hoco[2]/zn);
987         
988         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
989         
990         /* halovect */
991         if (vec1) {
992
993                 har->type |= HA_VECT;
994
995                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
996                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
997                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
998                 else zn= atan2(yn, xn);
999
1000                 har->sin= sin(zn);
1001                 har->cos= cos(zn);
1002                 zn= len_v3v3(vec1, vec);
1003
1004                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1005                 
1006                 sub_v3_v3v3(har->no, vec, vec1);
1007                 normalize_v3(har->no);
1008         }
1009
1010         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1011
1012         har->alfa= ma->alpha;
1013         har->r= ma->r;
1014         har->g= ma->g;
1015         har->b= ma->b;
1016         har->add= (255.0f*ma->add);
1017         har->mat= ma;
1018         har->hard= ma->har;
1019         har->seed= seed % 256;
1020
1021         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1022         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1023         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1024         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1025
1026
1027         if (ma->mtex[0]) {
1028
1029                 if (ma->mode & MA_HALOTEX) {
1030                         har->tex = 1;
1031                 }
1032                 else if (har->mat->septex & (1 << 0)) {
1033                         /* only 1 level textures */
1034                 }
1035                 else {
1036                         mtex= ma->mtex[0];
1037                         copy_v3_v3(texvec, vec);
1038
1039                         if (mtex->texco & TEXCO_NORM) {
1040                                 ;
1041                         }
1042                         else if (mtex->texco & TEXCO_OBJECT) {
1043                                 /* texvec[0]+= imatbase->ivec[0]; */
1044                                 /* texvec[1]+= imatbase->ivec[1]; */
1045                                 /* texvec[2]+= imatbase->ivec[2]; */
1046                                 /* mul_m3_v3(imatbase->imat, texvec); */
1047                         }
1048                         else {
1049                                 if (orco) {
1050                                         copy_v3_v3(texvec, orco);
1051                                 }
1052                         }
1053
1054                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
1055
1056                         yn= tin*mtex->colfac;
1057                         //zn= tin*mtex->alphafac;
1058
1059                         if (mtex->mapto & MAP_COL) {
1060                                 zn= 1.0f-yn;
1061                                 har->r= (yn*tr+ zn*ma->r);
1062                                 har->g= (yn*tg+ zn*ma->g);
1063                                 har->b= (yn*tb+ zn*ma->b);
1064                         }
1065                         if (mtex->texco & TEXCO_UV) {
1066                                 har->alfa= tin;
1067                         }
1068                         if (mtex->mapto & MAP_ALPHA)
1069                                 har->alfa= tin;
1070                 }
1071         }
1072
1073         har->pool = re->pool;
1074
1075         return har;
1076 }
1077
1078 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,
1079                               const float vec[3], const float vec1[3],
1080                               const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3])
1081 {
1082         HaloRen *har;
1083         MTex *mtex;
1084         float tin, tr, tg, tb, ta;
1085         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3];
1086         int i, hasrgb;
1087
1088         if (hasize==0.0f) return NULL;
1089
1090         projectverto(vec, re->winmat, hoco);
1091         if (hoco[3]==0.0f) return NULL;
1092         if (vec1) {
1093                 projectverto(vec1, re->winmat, hoco1);
1094                 if (hoco1[3]==0.0f) return NULL;
1095         }
1096
1097         har= RE_findOrAddHalo(obr, obr->tothalo++);
1098         copy_v3_v3(har->co, vec);
1099         har->hasize= hasize;
1100
1101         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1102         /* we do it here for sorting of halos */
1103         zn= hoco[3];
1104         har->xs= 0.5f*re->winx*(hoco[0]/zn);
1105         har->ys= 0.5f*re->winy*(hoco[1]/zn);
1106         har->zs= 0x7FFFFF*(hoco[2]/zn);
1107         
1108         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1109         
1110         /* halovect */
1111         if (vec1) {
1112
1113                 har->type |= HA_VECT;
1114
1115                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1116                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1117                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1118                 else zn= atan2(yn, xn);
1119
1120                 har->sin= sin(zn);
1121                 har->cos= cos(zn);
1122                 zn= len_v3v3(vec1, vec)*0.5f;
1123
1124                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1125                 
1126                 sub_v3_v3v3(har->no, vec, vec1);
1127                 normalize_v3(har->no);
1128         }
1129
1130         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1131
1132         har->alfa= ma->alpha;
1133         har->r= ma->r;
1134         har->g= ma->g;
1135         har->b= ma->b;
1136         har->add= (255.0f*ma->add);
1137         har->mat= ma;
1138         har->hard= ma->har;
1139         har->seed= seed % 256;
1140
1141         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1142         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1143         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1144         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1145
1146         if ((ma->mode & MA_HALOTEX) && ma->mtex[0])
1147                 har->tex= 1;
1148         
1149         for (i=0; i<MAX_MTEX; i++)
1150                 if (ma->mtex[i] && (ma->septex & (1<<i))==0) {
1151                         mtex= ma->mtex[i];
1152                         copy_v3_v3(texvec, vec);
1153
1154                         if (mtex->texco & TEXCO_NORM) {
1155                                 ;
1156                         }
1157                         else if (mtex->texco & TEXCO_OBJECT) {
1158                                 if (mtex->object)
1159                                         mul_m4_v3(mtex->object->imat_ren, texvec);
1160                         }
1161                         else if (mtex->texco & TEXCO_GLOB) {
1162                                 copy_v3_v3(texvec, vec);
1163                         }
1164                         else if (mtex->texco & TEXCO_UV && uvco) {
1165                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname);
1166                                 if (uv_index<0)
1167                                         uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
1168
1169                                 uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
1170
1171                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1172                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1173                                 texvec[2]=0.0f;
1174                         }
1175                         else if (mtex->texco & TEXCO_PARTICLE) {
1176                                 /* particle coordinates in range [0, 1] */
1177                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1178                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1179                                 texvec[2] = pa_co[2];
1180                         }
1181                         else if (orco) {
1182                                 copy_v3_v3(texvec, orco);
1183                         }
1184
1185                         hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
1186
1187                         //yn= tin*mtex->colfac;
1188                         //zn= tin*mtex->alphafac;
1189                         if (mtex->mapto & MAP_COL) {
1190                                 tex[0]=tr;
1191                                 tex[1]=tg;
1192                                 tex[2]=tb;
1193                                 out[0]=har->r;
1194                                 out[1]=har->g;
1195                                 out[2]=har->b;
1196
1197                                 texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype);
1198                         //      zn= 1.0-yn;
1199                                 //har->r= (yn*tr+ zn*ma->r);
1200                                 //har->g= (yn*tg+ zn*ma->g);
1201                                 //har->b= (yn*tb+ zn*ma->b);
1202                                 har->r= in[0];
1203                                 har->g= in[1];
1204                                 har->b= in[2];
1205                         }
1206
1207                         /* alpha returned, so let's use it instead of intensity */
1208                         if (hasrgb)
1209                                 tin = ta;
1210
1211                         if (mtex->mapto & MAP_ALPHA)
1212                                 har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype);
1213                         if (mtex->mapto & MAP_HAR)
1214                                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype);
1215                         if (mtex->mapto & MAP_RAYMIRR)
1216                                 har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype);
1217                         if (mtex->mapto & MAP_TRANSLU) {
1218                                 float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype);
1219                                 CLAMP(add, 0.f, 1.f);
1220                                 har->add = 255.0f*add;
1221                         }
1222                         /* now what on earth is this good for?? */
1223                         //if (mtex->texco & 16) {
1224                         //      har->alfa= tin;
1225                         //}
1226                 }
1227
1228         har->pool = re->pool;
1229
1230         return har;
1231 }
1232
1233 /* -------------------------- operations on entire database ----------------------- */
1234
1235 /* ugly function for halos in panorama */
1236 static int panotestclip(Render *re, int do_pano, float v[4])
1237 {
1238         /* part size (ensure we run RE_parts_clamp first) */
1239         BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx));
1240         BLI_assert(re->party == min_ii(re->r.tiley, re->recty));
1241
1242         if (do_pano == FALSE) {
1243                 return testclip(v);
1244         }
1245         else {
1246                 /* to be used for halos en infos */
1247                 float abs4;
1248                 short c = 0;
1249
1250                 int xparts = (re->rectx + re->partx - 1) / re->partx;
1251
1252                 abs4= fabsf(v[3]);
1253
1254                 if (v[2]< -abs4) c=16;          /* this used to be " if (v[2]<0) ", see clippz() */
1255                 else if (v[2]> abs4) c+= 32;
1256
1257                 if ( v[1]>abs4) c+=4;
1258                 else if ( v[1]< -abs4) c+=8;
1259
1260                 abs4*= xparts;
1261                 if ( v[0]>abs4) c+=2;
1262                 else if ( v[0]< -abs4) c+=1;
1263
1264                 return c;
1265         }
1266 }
1267
1268 /**
1269  * This adds the hcs coordinates to vertices. It iterates over all
1270  * vertices, halos and faces. After the conversion, we clip in hcs.
1271  *
1272  * Elsewhere, all primites are converted to vertices.
1273  * Called in
1274  * - envmapping (envmap.c)
1275  * - shadow buffering (shadbuf.c)
1276  */
1277
1278 void project_renderdata(Render *re,
1279                         void (*projectfunc)(const float *, float mat[4][4], float *),
1280                         int do_pano, float xoffs, int UNUSED(do_buckets))
1281 {
1282         ObjectRen *obr;
1283         HaloRen *har = NULL;
1284         float zn, vec[3], hoco[4];
1285         int a;
1286
1287         if (do_pano) {
1288                 float panophi= xoffs;
1289                 
1290                 re->panosi= sin(panophi);
1291                 re->panoco= cos(panophi);
1292         }
1293
1294         for (obr=re->objecttable.first; obr; obr=obr->next) {
1295                 /* calculate view coordinates (and zbuffer value) */
1296                 for (a=0; a<obr->tothalo; a++) {
1297                         if ((a & 255)==0) har= obr->bloha[a>>8];
1298                         else har++;
1299
1300                         if (do_pano) {
1301                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1302                                 vec[1]= har->co[1];
1303                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1304                         }
1305                         else {
1306                                 copy_v3_v3(vec, har->co);
1307                         }
1308
1309                         projectfunc(vec, re->winmat, hoco);
1310                         
1311                         /* we clip halos less critical, but not for the Z */
1312                         hoco[0]*= 0.5f;
1313                         hoco[1]*= 0.5f;
1314                         
1315                         if ( panotestclip(re, do_pano, hoco) ) {
1316                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1317                         }
1318                         else if (hoco[3]<0.0f) {
1319                                 har->miny= har->maxy= -10000;   /* render clips it */
1320                         }
1321                         else { /* do the projection...*/
1322                                 /* bring back hocos */
1323                                 hoco[0]*= 2.0f;
1324                                 hoco[1]*= 2.0f;
1325                                 
1326                                 zn= hoco[3];
1327                                 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1328                                 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
1329                         
1330                                 /* this should be the zbuffer coordinate */
1331                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1332                                 /* taking this from the face clip functions? seems ok... */
1333                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1334                                 
1335                                 vec[0]+= har->hasize;
1336                                 projectfunc(vec, re->winmat, hoco);
1337                                 vec[0]-= har->hasize;
1338                                 zn= hoco[3];
1339                                 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
1340                         
1341                                 /* this clip is not really OK, to prevent stars to become too large */
1342                                 if (har->type & HA_ONLYSKY) {
1343                                         if (har->rad>3.0f) har->rad= 3.0f;
1344                                 }
1345                         
1346                                 har->radsq= har->rad*har->rad;
1347                         
1348                                 har->miny= har->ys - har->rad/re->ycor;
1349                                 har->maxy= har->ys + har->rad/re->ycor;
1350                         
1351                                 /* the Zd value is still not really correct for pano */
1352                         
1353                                 vec[2] -= har->hasize;  /* z negative, otherwise it's clipped */
1354                                 projectfunc(vec, re->winmat, hoco);
1355                                 zn = hoco[3];
1356                                 zn = fabsf((float)har->zs - 0x7FFFFF * (hoco[2] / zn));
1357                                 har->zd = CLAMPIS(zn, 0, INT_MAX);
1358                         
1359                         }
1360                         
1361                 }
1362         }
1363 }
1364
1365 /* ------------------------------------------------------------------------- */
1366
1367 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[4][4], int lay)
1368 {
1369         ObjectInstanceRen *obi;
1370         float mat3[3][3];
1371
1372         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1373         obi->obr= obr;
1374         obi->ob= ob;
1375         obi->par= par;
1376         obi->index= index;
1377         obi->psysindex= psysindex;
1378         obi->lay= lay;
1379
1380         if (mat) {
1381                 copy_m4_m4(obi->mat, mat);
1382                 copy_m3_m4(mat3, mat);
1383                 invert_m3_m3(obi->nmat, mat3);
1384                 transpose_m3(obi->nmat);
1385                 obi->flag |= R_DUPLI_TRANSFORMED;
1386         }
1387
1388         BLI_addtail(&re->instancetable, obi);
1389
1390         return obi;
1391 }
1392
1393 void RE_makeRenderInstances(Render *re)
1394 {
1395         ObjectInstanceRen *obi, *oldobi;
1396         ListBase newlist;
1397         int tot;
1398
1399         /* convert list of object instances to an array for index based lookup */
1400         tot= BLI_countlist(&re->instancetable);
1401         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1402         re->totinstance= tot;
1403         newlist.first= newlist.last= NULL;
1404
1405         obi= re->objectinstance;
1406         for (oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1407                 *obi= *oldobi;
1408
1409                 if (obi->obr) {
1410                         obi->prev= obi->next= NULL;
1411                         BLI_addtail(&newlist, obi);
1412                         obi++;
1413                 }
1414                 else
1415                         re->totinstance--;
1416         }
1417
1418         BLI_freelistN(&re->instancetable);
1419         re->instancetable= newlist;
1420 }
1421
1422 int clip_render_object(float boundbox[2][3], float bounds[4], float winmat[4][4])
1423 {
1424         float mat[4][4], vec[4];
1425         int a, fl, flag = -1;
1426
1427         copy_m4_m4(mat, winmat);
1428
1429         for (a=0; a < 8; a++) {
1430                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1431                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1432                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1433                 vec[3]= 1.0;
1434                 mul_m4_v4(mat, vec);
1435
1436                 fl = 0;
1437                 if (bounds) {
1438                         if      (vec[0] < bounds[0] * vec[3]) fl |= 1;
1439                         else if (vec[0] > bounds[1] * vec[3]) fl |= 2;
1440                         
1441                         if      (vec[1] > bounds[3] * vec[3]) fl |= 4;
1442                         else if (vec[1] < bounds[2] * vec[3]) fl |= 8;
1443                 }
1444                 else {
1445                         if      (vec[0] < -vec[3]) fl |= 1;
1446                         else if (vec[0] >  vec[3]) fl |= 2;
1447                         
1448                         if      (vec[1] >  vec[3]) fl |= 4;
1449                         else if (vec[1] < -vec[3]) fl |= 8;
1450                 }
1451                 if      (vec[2] < -vec[3]) fl |= 16;
1452                 else if (vec[2] >  vec[3]) fl |= 32;
1453
1454                 flag &= fl;
1455                 if (flag == 0) {
1456                         return 0;
1457                 }
1458         }
1459
1460         return flag;
1461 }
1462