code cleanup: use const float and define array size
[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 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.
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
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
116
117 float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
118 {
119         float *sticky;
120         int nr= ver->index>>8;
121         
122         sticky= obr->vertnodes[nr].sticky;
123         if (sticky==NULL) {
124                 if (verify) 
125                         sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
126                 else
127                         return NULL;
128         }
129         return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
130 }
131
132 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
133 {
134         float *stress;
135         int nr= ver->index>>8;
136         
137         stress= obr->vertnodes[nr].stress;
138         if (stress==NULL) {
139                 if (verify) 
140                         stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
141                 else
142                         return NULL;
143         }
144         return stress + (ver->index & 255)*RE_STRESS_ELEMS;
145 }
146
147 /* this one callocs! */
148 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
149 {
150         float *rad;
151         int nr= ver->index>>8;
152         
153         rad= obr->vertnodes[nr].rad;
154         if (rad==NULL) {
155                 if (verify) 
156                         rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
157                 else
158                         return NULL;
159         }
160         return rad + (ver->index & 255)*RE_RAD_ELEMS;
161 }
162
163 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
164 {
165         float *strand;
166         int nr= ver->index>>8;
167         
168         strand= obr->vertnodes[nr].strand;
169         if (strand==NULL) {
170                 if (verify) 
171                         strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
172                 else
173                         return NULL;
174         }
175         return strand + (ver->index & 255)*RE_STRAND_ELEMS;
176 }
177
178 /* needs calloc */
179 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
180 {
181         float *tangent;
182         int nr= ver->index>>8;
183         
184         tangent= obr->vertnodes[nr].tangent;
185         if (tangent==NULL) {
186                 if (verify) 
187                         tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
188                 else
189                         return NULL;
190         }
191         return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
192 }
193
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)
197 {
198         float *winspeed;
199         int totvector;
200         
201         winspeed= obi->vectors;
202         if (winspeed==NULL) {
203                 if (verify) {
204                         totvector= obi->obr->totvert + obi->obr->totstrand;
205                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
206                 }
207                 else
208                         return NULL;
209         }
210         return winspeed + ver->index*RE_WINSPEED_ELEMS;
211 }
212
213 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
214 {
215         VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
216         float *fp1, *fp2;
217         int index= v1->index;
218         
219         *v1= *ver;
220         v1->index= index;
221         
222         fp1= RE_vertren_get_sticky(obr, ver, 0);
223         if (fp1) {
224                 fp2= RE_vertren_get_sticky(obr, v1, 1);
225                 memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
226         }
227         fp1= RE_vertren_get_stress(obr, ver, 0);
228         if (fp1) {
229                 fp2= RE_vertren_get_stress(obr, v1, 1);
230                 memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
231         }
232         fp1= RE_vertren_get_rad(obr, ver, 0);
233         if (fp1) {
234                 fp2= RE_vertren_get_rad(obr, v1, 1);
235                 memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
236         }
237         fp1= RE_vertren_get_strand(obr, ver, 0);
238         if (fp1) {
239                 fp2= RE_vertren_get_strand(obr, v1, 1);
240                 memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
241         }
242         fp1= RE_vertren_get_tangent(obr, ver, 0);
243         if (fp1) {
244                 fp2= RE_vertren_get_tangent(obr, v1, 1);
245                 memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
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 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
359 {
360         float *surfnor;
361         int nr= vlak->index>>8;
362         
363         surfnor= obr->vlaknodes[nr].surfnor;
364         if (surfnor==NULL) {
365                 if (verify) 
366                         surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
367                 else
368                         return NULL;
369         }
370         return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
371 }
372
373 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
374 {
375         float *tangent;
376         int nr= vlak->index>>8;
377
378         tangent= obr->vlaknodes[nr].tangent;
379         if (tangent==NULL) {
380                 if (verify) 
381                         tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
382                 else
383                         return NULL;
384         }
385         return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
386 }
387
388 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
389 {
390         RadFace **radface;
391         int nr= vlak->index>>8;
392         
393         radface= obr->vlaknodes[nr].radface;
394         if (radface==NULL) {
395                 if (verify) 
396                         radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
397                 else
398                         return NULL;
399         }
400         return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
401 }
402
403 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
404 {
405         VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
406         MTFace *mtface, *mtface1;
407         MCol *mcol, *mcol1;
408         float *surfnor, *surfnor1, *tangent, *tangent1;
409         RadFace **radface, **radface1;
410         int i, index = vlr1->index;
411         char *name;
412
413         *vlr1= *vlr;
414         vlr1->index= index;
415
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);
419         }
420
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);
424         }
425
426         surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
427         if (surfnor) {
428                 surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
429                 copy_v3_v3(surfnor1, surfnor);
430         }
431
432         tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
433         if (tangent) {
434                 tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
435                 memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
436         }
437
438         radface= RE_vlakren_get_radface(obr, vlr, 0);
439         if (radface) {
440                 radface1= RE_vlakren_get_radface(obr, vlr1, 1);
441                 *radface1= *radface;
442         }
443
444         return vlr1;
445 }
446
447 void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float r_nor[3])
448 {
449         float (*nmat)[3]= obi->nmat;
450
451         if (obi->flag & R_TRANSFORMED) {
452                 mul_v3_m3v3(r_nor, nmat, vlr->n);
453                 normalize_v3(r_nor);
454         }
455         else {
456                 copy_v3_v3(r_nor, vlr->n);
457         }
458 }
459
460 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
461 {
462         /* CustomData layer names are stored per object here, because the
463          * DerivedMesh which stores the layers is freed */
464         
465         CustomDataLayer *layer;
466         int numtf = 0, numcol = 0, i, mtfn, mcn;
467
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");
471         }
472
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");
476         }
477
478         for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
479                 layer= &data->layers[i];
480
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;
485                 }
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);
489                 }
490         }
491 }
492
493 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
494 {
495         VlakTableNode *temp;
496         VlakRen *v;
497         int a;
498
499         if (nr<0) {
500                 printf("error in findOrAddVlak: %d\n", nr);
501                 return obr->vlaknodes[0].vlak;
502         }
503         a= nr>>8;
504         
505         if (a>=obr->vlaknodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
506                 temp= obr->vlaknodes;
507                 
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));
511
512                 obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
513                 if (temp) MEM_freeN(temp);      
514         }
515
516         v= obr->vlaknodes[a].vlak;
517         
518         if (v==NULL) {
519                 int i;
520
521                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen), "findOrAddVlak");
522                 obr->vlaknodes[a].vlak= v;
523
524                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
525                         v[a].index= i;
526         }
527         v+= (nr & 255);
528         return v;
529 }
530
531 /* ------------------------------------------------------------------------ */
532
533 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
534 {
535         float *surfnor;
536         int nr= strand->index>>8;
537         
538         surfnor= obr->strandnodes[nr].surfnor;
539         if (surfnor==NULL) {
540                 if (verify) 
541                         surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
542                 else
543                         return NULL;
544         }
545         return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
546 }
547
548 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
549 {
550         StrandTableNode *node;
551         int nr= strand->index>>8, strandindex= (strand->index&255);
552         int index= (n<<8) + strandindex;
553
554         node= &obr->strandnodes[nr];
555
556         if (verify) {
557                 if (n>=node->totuv) {
558                         float *uv= node->uv;
559                         int size= (n+1)*256;
560
561                         node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
562
563                         if (uv) {
564                                 size= node->totuv*256;
565                                 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
566                                 MEM_freeN(uv);
567                         }
568
569                         node->totuv= n+1;
570                 }
571         }
572         else {
573                 if (n>=node->totuv)
574                         return NULL;
575
576                 if (name) *name= obr->mtface[n];
577         }
578
579         return node->uv + index*RE_UV_ELEMS;
580 }
581
582 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
583 {
584         StrandTableNode *node;
585         int nr= strand->index>>8, strandindex= (strand->index&255);
586         int index= (n<<8) + strandindex;
587
588         node= &obr->strandnodes[nr];
589
590         if (verify) {
591                 if (n>=node->totmcol) {
592                         MCol *mcol= node->mcol;
593                         int size= (n+1)*256;
594
595                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
596
597                         if (mcol) {
598                                 size= node->totmcol*256;
599                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
600                                 MEM_freeN(mcol);
601                         }
602
603                         node->totmcol= n+1;
604                 }
605         }
606         else {
607                 if (n>=node->totmcol)
608                         return NULL;
609
610                 if (name) *name= obr->mcol[n];
611         }
612
613         return node->mcol + index*RE_MCOL_ELEMS;
614 }
615
616 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
617 {
618         float *simplify;
619         int nr= strand->index>>8;
620         
621         simplify= obr->strandnodes[nr].simplify;
622         if (simplify==NULL) {
623                 if (verify) 
624                         simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
625                 else
626                         return NULL;
627         }
628         return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
629 }
630
631 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
632 {
633         int *face;
634         int nr= strand->index>>8;
635         
636         face= obr->strandnodes[nr].face;
637         if (face==NULL) {
638                 if (verify) 
639                         face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
640                 else
641                         return NULL;
642         }
643         return face + (strand->index & 255)*RE_FACE_ELEMS;
644 }
645
646 /* winspeed is exception, it is stored per instance */
647 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
648 {
649         float *winspeed;
650         int totvector;
651         
652         winspeed= obi->vectors;
653         if (winspeed==NULL) {
654                 if (verify) {
655                         totvector= obi->obr->totvert + obi->obr->totstrand;
656                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
657                 }
658                 else
659                         return NULL;
660         }
661         return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
662 }
663
664 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
665 {
666         StrandTableNode *temp;
667         StrandRen *v;
668         int a;
669
670         if (nr<0) {
671                 printf("error in findOrAddStrand: %d\n", nr);
672                 return obr->strandnodes[0].strand;
673         }
674         a= nr>>8;
675         
676         if (a>=obr->strandnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
677                 temp= obr->strandnodes;
678                 
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));
682
683                 obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
684                 if (temp) MEM_freeN(temp);      
685         }
686
687         v= obr->strandnodes[a].strand;
688         
689         if (v==NULL) {
690                 int i;
691
692                 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen), "findOrAddStrand");
693                 obr->strandnodes[a].strand= v;
694
695                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
696                         v[a].index= i;
697         }
698         v+= (nr & 255);
699         return v;
700 }
701
702 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
703 {
704         StrandBuffer *strandbuf;
705
706         strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
707         strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
708         strandbuf->totvert= totvert;
709         strandbuf->obr= obr;
710
711         obr->strandbuf= strandbuf;
712
713         return strandbuf;
714 }
715
716 /* ------------------------------------------------------------------------ */
717
718 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
719 {
720         ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
721         
722         BLI_addtail(&re->objecttable, obr);
723         obr->ob= ob;
724         obr->par= par;
725         obr->index= index;
726         obr->psysindex= psysindex;
727         obr->lay= lay;
728
729         return obr;
730 }
731
732 void free_renderdata_vertnodes(VertTableNode *vertnodes)
733 {
734         int a;
735         
736         if (vertnodes==NULL) return;
737         
738         for (a=0; vertnodes[a].vert; a++) {
739                 MEM_freeN(vertnodes[a].vert);
740                 
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);
753         }
754         
755         MEM_freeN(vertnodes);
756 }
757
758 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
759 {
760         int a;
761         
762         if (vlaknodes==NULL) return;
763         
764         for (a=0; vlaknodes[a].vlak; a++) {
765                 MEM_freeN(vlaknodes[a].vlak);
766                 
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);
777         }
778         
779         MEM_freeN(vlaknodes);
780 }
781
782 static void free_renderdata_strandnodes(StrandTableNode *strandnodes)
783 {
784         int a;
785         
786         if (strandnodes==NULL) return;
787         
788         for (a=0; strandnodes[a].strand; a++) {
789                 MEM_freeN(strandnodes[a].strand);
790                 
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);
803         }
804         
805         MEM_freeN(strandnodes);
806 }
807
808 void free_renderdata_tables(Render *re)
809 {
810         ObjectInstanceRen *obi;
811         ObjectRen *obr;
812         StrandBuffer *strandbuf;
813         int a=0;
814         
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;
820                 }
821
822                 if (obr->vlaknodes) {
823                         free_renderdata_vlaknodes(obr->vlaknodes);
824                         obr->vlaknodes= NULL;
825                         obr->vlaknodeslen= 0;
826                         obr->totvlak= 0;
827                 }
828
829                 if (obr->bloha) {
830                         for (a=0; obr->bloha[a]; a++)
831                                 MEM_freeN(obr->bloha[a]);
832
833                         MEM_freeN(obr->bloha);
834                         obr->bloha= NULL;
835                         obr->blohalen= 0;
836                 }
837
838                 if (obr->strandnodes) {
839                         free_renderdata_strandnodes(obr->strandnodes);
840                         obr->strandnodes= NULL;
841                         obr->strandnodeslen= 0;
842                 }
843
844                 strandbuf= obr->strandbuf;
845                 if (strandbuf) {
846                         if (strandbuf->vert) MEM_freeN(strandbuf->vert);
847                         if (strandbuf->bound) MEM_freeN(strandbuf->bound);
848                         MEM_freeN(strandbuf);
849                 }
850
851                 if (obr->mtface)
852                         MEM_freeN(obr->mtface);
853
854                 if (obr->mcol)
855                         MEM_freeN(obr->mcol);
856                         
857                 if (obr->rayfaces) {
858                         MEM_freeN(obr->rayfaces);
859                         obr->rayfaces = NULL;
860                 }
861
862                 if (obr->rayprimitives) {
863                         MEM_freeN(obr->rayprimitives);
864                         obr->rayprimitives = NULL;
865                 }
866
867                 if (obr->raytree) {
868                         RE_rayobject_free(obr->raytree);
869                         obr->raytree = NULL;
870                 }
871         }
872
873         if (re->objectinstance) {
874                 for (obi=re->instancetable.first; obi; obi=obi->next) {
875                         if (obi->vectors)
876                                 MEM_freeN(obi->vectors);
877
878                         if (obi->raytree)
879                                 RE_rayobject_free(obi->raytree);
880                 }
881
882                 MEM_freeN(re->objectinstance);
883                 re->objectinstance= NULL;
884                 re->totinstance= 0;
885                 re->instancetable.first= re->instancetable.last= NULL;
886         }
887
888         if (re->sortedhalos) {
889                 MEM_freeN(re->sortedhalos);
890                 re->sortedhalos= NULL;
891         }
892
893         BLI_freelistN(&re->customdata_names);
894         BLI_freelistN(&re->objecttable);
895         BLI_freelistN(&re->instancetable);
896 }
897
898 /* ------------------------------------------------------------------------ */
899
900 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
901 {
902         HaloRen *h, **temp;
903         int a;
904
905         if (nr<0) {
906                 printf("error in findOrAddHalo: %d\n", nr);
907                 return NULL;
908         }
909         a= nr>>8;
910         
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 );
914                 temp=obr->bloha;
915                 
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);      
921         }
922         
923         h= obr->bloha[a];
924         if (h==NULL) {
925                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen), "findOrAdHalo");
926                 obr->bloha[a]= h;
927         }
928         h+= (nr & 255);
929         return h;
930 }
931
932 /* ------------------------------------------------------------------------- */
933
934 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
935                      const float vec[3], const float vec1[3],
936                      const float *orco, float hasize, float vectsize, int seed)
937 {
938         HaloRen *har;
939         MTex *mtex;
940         float tin, tr, tg, tb, ta;
941         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
942
943         if (hasize==0.0f) return NULL;
944
945         projectverto(vec, re->winmat, hoco);
946         if (hoco[3]==0.0f) return NULL;
947         if (vec1) {
948                 projectverto(vec1, re->winmat, hoco1);
949                 if (hoco1[3]==0.0f) return NULL;
950         }
951
952         har= RE_findOrAddHalo(obr, obr->tothalo++);
953         copy_v3_v3(har->co, vec);
954         har->hasize= hasize;
955
956         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
957         /* we do it here for sorting of halos */
958         zn= hoco[3];
959         har->xs= 0.5f*re->winx*(hoco[0]/zn);
960         har->ys= 0.5f*re->winy*(hoco[1]/zn);
961         har->zs= 0x7FFFFF*(hoco[2]/zn);
962         
963         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
964         
965         /* halovect */
966         if (vec1) {
967
968                 har->type |= HA_VECT;
969
970                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
971                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
972                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
973                 else zn= atan2(yn, xn);
974
975                 har->sin= sin(zn);
976                 har->cos= cos(zn);
977                 zn= len_v3v3(vec1, vec);
978
979                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
980                 
981                 sub_v3_v3v3(har->no, vec, vec1);
982                 normalize_v3(har->no);
983         }
984
985         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
986
987         har->alfa= ma->alpha;
988         har->r= ma->r;
989         har->g= ma->g;
990         har->b= ma->b;
991         har->add= (255.0f*ma->add);
992         har->mat= ma;
993         har->hard= ma->har;
994         har->seed= seed % 256;
995
996         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
997         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
998         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
999         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1000
1001
1002         if (ma->mtex[0]) {
1003
1004                 if ( (ma->mode & MA_HALOTEX) ) har->tex= 1;
1005                 else if (har->mat->septex & (1<<0));    /* only 1 level textures */
1006                 else {
1007
1008                         mtex= ma->mtex[0];
1009                         copy_v3_v3(texvec, vec);
1010
1011                         if (mtex->texco & TEXCO_NORM) {
1012                                 ;
1013                         }
1014                         else if (mtex->texco & TEXCO_OBJECT) {
1015                                 /* texvec[0]+= imatbase->ivec[0]; */
1016                                 /* texvec[1]+= imatbase->ivec[1]; */
1017                                 /* texvec[2]+= imatbase->ivec[2]; */
1018                                 /* mul_m3_v3(imatbase->imat, texvec); */
1019                         }
1020                         else {
1021                                 if (orco) {
1022                                         copy_v3_v3(texvec, orco);
1023                                 }
1024                         }
1025
1026                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1027
1028                         yn= tin*mtex->colfac;
1029                         //zn= tin*mtex->alphafac;
1030
1031                         if (mtex->mapto & MAP_COL) {
1032                                 zn= 1.0f-yn;
1033                                 har->r= (yn*tr+ zn*ma->r);
1034                                 har->g= (yn*tg+ zn*ma->g);
1035                                 har->b= (yn*tb+ zn*ma->b);
1036                         }
1037                         if (mtex->texco & TEXCO_UV) {
1038                                 har->alfa= tin;
1039                         }
1040                         if (mtex->mapto & MAP_ALPHA)
1041                                 har->alfa= tin;
1042                 }
1043         }
1044
1045         return har;
1046 }
1047
1048 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,
1049                               const float vec[3], const float vec1[3],
1050                               const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3])
1051 {
1052         HaloRen *har;
1053         MTex *mtex;
1054         float tin, tr, tg, tb, ta;
1055         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3];
1056         int i, hasrgb;
1057
1058         if (hasize==0.0f) return NULL;
1059
1060         projectverto(vec, re->winmat, hoco);
1061         if (hoco[3]==0.0f) return NULL;
1062         if (vec1) {
1063                 projectverto(vec1, re->winmat, hoco1);
1064                 if (hoco1[3]==0.0f) return NULL;
1065         }
1066
1067         har= RE_findOrAddHalo(obr, obr->tothalo++);
1068         copy_v3_v3(har->co, vec);
1069         har->hasize= hasize;
1070
1071         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1072         /* we do it here for sorting of halos */
1073         zn= hoco[3];
1074         har->xs= 0.5f*re->winx*(hoco[0]/zn);
1075         har->ys= 0.5f*re->winy*(hoco[1]/zn);
1076         har->zs= 0x7FFFFF*(hoco[2]/zn);
1077         
1078         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1079         
1080         /* halovect */
1081         if (vec1) {
1082
1083                 har->type |= HA_VECT;
1084
1085                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1086                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1087                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1088                 else zn= atan2(yn, xn);
1089
1090                 har->sin= sin(zn);
1091                 har->cos= cos(zn);
1092                 zn= len_v3v3(vec1, vec)*0.5f;
1093
1094                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1095                 
1096                 sub_v3_v3v3(har->no, vec, vec1);
1097                 normalize_v3(har->no);
1098         }
1099
1100         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1101
1102         har->alfa= ma->alpha;
1103         har->r= ma->r;
1104         har->g= ma->g;
1105         har->b= ma->b;
1106         har->add= (255.0f*ma->add);
1107         har->mat= ma;
1108         har->hard= ma->har;
1109         har->seed= seed % 256;
1110
1111         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1112         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1113         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1114         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1115
1116         if ((ma->mode & MA_HALOTEX) && ma->mtex[0])
1117                 har->tex= 1;
1118         
1119         for (i=0; i<MAX_MTEX; i++)
1120                 if (ma->mtex[i] && (ma->septex & (1<<i))==0) {
1121                         mtex= ma->mtex[i];
1122                         copy_v3_v3(texvec, vec);
1123
1124                         if (mtex->texco & TEXCO_NORM) {
1125                                 ;
1126                         }
1127                         else if (mtex->texco & TEXCO_OBJECT) {
1128                                 if (mtex->object)
1129                                         mul_m4_v3(mtex->object->imat_ren, texvec);
1130                         }
1131                         else if (mtex->texco & TEXCO_GLOB) {
1132                                 copy_v3_v3(texvec, vec);
1133                         }
1134                         else if (mtex->texco & TEXCO_UV && uvco) {
1135                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname);
1136                                 if (uv_index<0)
1137                                         uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
1138
1139                                 uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
1140
1141                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1142                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1143                                 texvec[2]=0.0f;
1144                         }
1145                         else if (mtex->texco & TEXCO_PARTICLE) {
1146                                 /* particle coordinates in range [0, 1] */
1147                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1148                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1149                                 texvec[2] = pa_co[2];
1150                         }
1151                         else if (orco) {
1152                                 copy_v3_v3(texvec, orco);
1153                         }
1154
1155                         hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1156
1157                         //yn= tin*mtex->colfac;
1158                         //zn= tin*mtex->alphafac;
1159                         if (mtex->mapto & MAP_COL) {
1160                                 tex[0]=tr;
1161                                 tex[1]=tg;
1162                                 tex[2]=tb;
1163                                 out[0]=har->r;
1164                                 out[1]=har->g;
1165                                 out[2]=har->b;
1166
1167                                 texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype);
1168                         //      zn= 1.0-yn;
1169                                 //har->r= (yn*tr+ zn*ma->r);
1170                                 //har->g= (yn*tg+ zn*ma->g);
1171                                 //har->b= (yn*tb+ zn*ma->b);
1172                                 har->r= in[0];
1173                                 har->g= in[1];
1174                                 har->b= in[2];
1175                         }
1176
1177                         /* alpha returned, so let's use it instead of intensity */
1178                         if (hasrgb)
1179                                 tin = ta;
1180
1181                         if (mtex->mapto & MAP_ALPHA)
1182                                 har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype);
1183                         if (mtex->mapto & MAP_HAR)
1184                                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype);
1185                         if (mtex->mapto & MAP_RAYMIRR)
1186                                 har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype);
1187                         if (mtex->mapto & MAP_TRANSLU) {
1188                                 float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype);
1189                                 CLAMP(add, 0.f, 1.f);
1190                                 har->add = 255.0f*add;
1191                         }
1192                         /* now what on earth is this good for?? */
1193                         //if (mtex->texco & 16) {
1194                         //      har->alfa= tin;
1195                         //}
1196                 }
1197
1198         return har;
1199 }
1200
1201 /* -------------------------- operations on entire database ----------------------- */
1202
1203 /* ugly function for halos in panorama */
1204 static int panotestclip(Render *re, int do_pano, float *v)
1205 {
1206         /* to be used for halos en infos */
1207         float abs4;
1208         short c=0;
1209
1210         if (do_pano == FALSE) {
1211                 return testclip(v);
1212         }
1213
1214         abs4= fabs(v[3]);
1215
1216         if (v[2]< -abs4) c=16;          /* this used to be " if (v[2]<0) ", see clippz() */
1217         else if (v[2]> abs4) c+= 32;
1218
1219         if ( v[1]>abs4) c+=4;
1220         else if ( v[1]< -abs4) c+=8;
1221
1222         abs4*= re->xparts;
1223         if ( v[0]>abs4) c+=2;
1224         else if ( v[0]< -abs4) c+=1;
1225
1226         return c;
1227 }
1228
1229 /**
1230  * This adds the hcs coordinates to vertices. It iterates over all
1231  * vertices, halos and faces. After the conversion, we clip in hcs.
1232  *
1233  * Elsewhere, all primites are converted to vertices.
1234  * Called in
1235  * - envmapping (envmap.c)
1236  * - shadow buffering (shadbuf.c)
1237  */
1238
1239 void project_renderdata(Render *re, void (*projectfunc)(const float *, float mat[][4], float *),  int do_pano, float xoffs, int UNUSED(do_buckets))
1240 {
1241         ObjectRen *obr;
1242         HaloRen *har = NULL;
1243         float zn, vec[3], hoco[4];
1244         int a;
1245
1246         if (do_pano) {
1247                 float panophi= xoffs;
1248                 
1249                 re->panosi= sin(panophi);
1250                 re->panoco= cos(panophi);
1251         }
1252
1253         for (obr=re->objecttable.first; obr; obr=obr->next) {
1254                 /* calculate view coordinates (and zbuffer value) */
1255                 for (a=0; a<obr->tothalo; a++) {
1256                         if ((a & 255)==0) har= obr->bloha[a>>8];
1257                         else har++;
1258
1259                         if (do_pano) {
1260                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1261                                 vec[1]= har->co[1];
1262                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1263                         }
1264                         else {
1265                                 copy_v3_v3(vec, har->co);
1266                         }
1267
1268                         projectfunc(vec, re->winmat, hoco);
1269                         
1270                         /* we clip halos less critical, but not for the Z */
1271                         hoco[0]*= 0.5f;
1272                         hoco[1]*= 0.5f;
1273                         
1274                         if ( panotestclip(re, do_pano, hoco) ) {
1275                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1276                         }
1277                         else if (hoco[3]<0.0f) {
1278                                 har->miny= har->maxy= -10000;   /* render clips it */
1279                         }
1280                         else { /* do the projection...*/
1281                                 /* bring back hocos */
1282                                 hoco[0]*= 2.0f;
1283                                 hoco[1]*= 2.0f;
1284                                 
1285                                 zn= hoco[3];
1286                                 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1287                                 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
1288                         
1289                                 /* this should be the zbuffer coordinate */
1290                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1291                                 /* taking this from the face clip functions? seems ok... */
1292                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1293                                 
1294                                 vec[0]+= har->hasize;
1295                                 projectfunc(vec, re->winmat, hoco);
1296                                 vec[0]-= har->hasize;
1297                                 zn= hoco[3];
1298                                 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
1299                         
1300                                 /* this clip is not really OK, to prevent stars to become too large */
1301                                 if (har->type & HA_ONLYSKY) {
1302                                         if (har->rad>3.0f) har->rad= 3.0f;
1303                                 }
1304                         
1305                                 har->radsq= har->rad*har->rad;
1306                         
1307                                 har->miny= har->ys - har->rad/re->ycor;
1308                                 har->maxy= har->ys + har->rad/re->ycor;
1309                         
1310                                 /* the Zd value is still not really correct for pano */
1311                         
1312                                 vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
1313                                 projectfunc(vec, re->winmat, hoco);
1314                                 zn= hoco[3];
1315                                 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
1316                                 har->zd= CLAMPIS(zn, 0, INT_MAX);
1317                         
1318                         }
1319                         
1320                 }
1321         }
1322 }
1323
1324 /* ------------------------------------------------------------------------- */
1325
1326 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
1327 {
1328         ObjectInstanceRen *obi;
1329         float mat3[3][3];
1330
1331         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1332         obi->obr= obr;
1333         obi->ob= ob;
1334         obi->par= par;
1335         obi->index= index;
1336         obi->psysindex= psysindex;
1337         obi->lay= lay;
1338
1339         if (mat) {
1340                 copy_m4_m4(obi->mat, mat);
1341                 copy_m3_m4(mat3, mat);
1342                 invert_m3_m3(obi->nmat, mat3);
1343                 transpose_m3(obi->nmat);
1344                 obi->flag |= R_DUPLI_TRANSFORMED;
1345         }
1346
1347         BLI_addtail(&re->instancetable, obi);
1348
1349         return obi;
1350 }
1351
1352 void RE_makeRenderInstances(Render *re)
1353 {
1354         ObjectInstanceRen *obi, *oldobi;
1355         ListBase newlist;
1356         int tot;
1357
1358         /* convert list of object instances to an array for index based lookup */
1359         tot= BLI_countlist(&re->instancetable);
1360         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1361         re->totinstance= tot;
1362         newlist.first= newlist.last= NULL;
1363
1364         obi= re->objectinstance;
1365         for (oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1366                 *obi= *oldobi;
1367
1368                 if (obi->obr) {
1369                         obi->prev= obi->next= NULL;
1370                         BLI_addtail(&newlist, obi);
1371                         obi++;
1372                 }
1373                 else
1374                         re->totinstance--;
1375         }
1376
1377         BLI_freelistN(&re->instancetable);
1378         re->instancetable= newlist;
1379 }
1380
1381 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
1382 {
1383         float mat[4][4], vec[4];
1384         int a, fl, flag= -1;
1385
1386         copy_m4_m4(mat, winmat);
1387
1388         for (a=0; a<8; a++) {
1389                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1390                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1391                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1392                 vec[3]= 1.0;
1393                 mul_m4_v4(mat, vec);
1394
1395                 fl= 0;
1396                 if (bounds) {
1397                         if (vec[0] < bounds[0]*vec[3]) fl |= 1;
1398                         else if (vec[0] > bounds[1]*vec[3]) fl |= 2;
1399                         
1400                         if (vec[1] > bounds[3]*vec[3]) fl |= 4;
1401                         else if (vec[1]< bounds[2]*vec[3]) fl |= 8;
1402                 }
1403                 else {
1404                         if (vec[0] < -vec[3]) fl |= 1;
1405                         else if (vec[0] > vec[3]) fl |= 2;
1406                         
1407                         if (vec[1] > vec[3]) fl |= 4;
1408                         else if (vec[1] < -vec[3]) fl |= 8;
1409                 }
1410                 if (vec[2] < -vec[3]) fl |= 16;
1411                 else if (vec[2] > vec[3]) fl |= 32;
1412
1413                 flag &= fl;
1414                 if (flag==0) return 0;
1415         }
1416
1417         return flag;
1418 }
1419