style cleanup, brackets in else/if, some indentation.
[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 dont
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 *nor)
448 {
449         float (*nmat)[3]= obi->nmat;
450
451         if(obi->flag & R_TRANSFORMED) {
452                 mul_v3_m3v3(nor, nmat, vlr->n);
453                 normalize_v3(nor);
454         }
455         else {
456                 copy_v3_v3(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                 {
876                         if(obi->vectors)
877                                 MEM_freeN(obi->vectors);
878
879                         if(obi->raytree)
880                                 RE_rayobject_free(obi->raytree);
881                 }
882
883                 MEM_freeN(re->objectinstance);
884                 re->objectinstance= NULL;
885                 re->totinstance= 0;
886                 re->instancetable.first= re->instancetable.last= NULL;
887         }
888
889         if(re->sortedhalos) {
890                 MEM_freeN(re->sortedhalos);
891                 re->sortedhalos= NULL;
892         }
893
894         BLI_freelistN(&re->customdata_names);
895         BLI_freelistN(&re->objecttable);
896         BLI_freelistN(&re->instancetable);
897 }
898
899 /* ------------------------------------------------------------------------ */
900
901 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
902 {
903         HaloRen *h, **temp;
904         int a;
905
906         if(nr<0) {
907                 printf("error in findOrAddHalo: %d\n",nr);
908                 return NULL;
909         }
910         a= nr>>8;
911         
912         if (a>=obr->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
913                 //printf("Allocating %i more halo groups.  %i total.\n", 
914                 //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
915                 temp=obr->bloha;
916                 
917                 obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
918                 if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
919                 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
920                 obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
921                 if(temp) MEM_freeN(temp);       
922         }
923         
924         h= obr->bloha[a];
925         if(h==NULL) {
926                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
927                 obr->bloha[a]= h;
928         }
929         h+= (nr & 255);
930         return h;
931 }
932
933 /* ------------------------------------------------------------------------- */
934
935 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   float *vec1, 
936                                   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,   float *vec,   float *vec1, 
1049                                   float *orco, float *uvco, float hasize, float vectsize, int seed, float *pa_co)
1050 {
1051         HaloRen *har;
1052         MTex *mtex;
1053         float tin, tr, tg, tb, ta;
1054         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
1055         int i, hasrgb;
1056
1057         if(hasize==0.0f) return NULL;
1058
1059         projectverto(vec, re->winmat, hoco);
1060         if(hoco[3]==0.0f) return NULL;
1061         if(vec1) {
1062                 projectverto(vec1, re->winmat, hoco1);
1063                 if(hoco1[3]==0.0f) return NULL;
1064         }
1065
1066         har= RE_findOrAddHalo(obr, obr->tothalo++);
1067         copy_v3_v3(har->co, vec);
1068         har->hasize= hasize;
1069
1070         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1071         /* we do it here for sorting of halos */
1072         zn= hoco[3];
1073         har->xs= 0.5f*re->winx*(hoco[0]/zn);
1074         har->ys= 0.5f*re->winy*(hoco[1]/zn);
1075         har->zs= 0x7FFFFF*(hoco[2]/zn);
1076         
1077         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1078         
1079         /* halovect */
1080         if(vec1) {
1081
1082                 har->type |= HA_VECT;
1083
1084                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1085                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1086                 if(xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1087                 else zn= atan2(yn, xn);
1088
1089                 har->sin= sin(zn);
1090                 har->cos= cos(zn);
1091                 zn= len_v3v3(vec1, vec)*0.5f;
1092
1093                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1094                 
1095                 sub_v3_v3v3(har->no, vec, vec1);
1096                 normalize_v3(har->no);
1097         }
1098
1099         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1100
1101         har->alfa= ma->alpha;
1102         har->r= ma->r;
1103         har->g= ma->g;
1104         har->b= ma->b;
1105         har->add= (255.0f*ma->add);
1106         har->mat= ma;
1107         har->hard= ma->har;
1108         har->seed= seed % 256;
1109
1110         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1111         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1112         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1113         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1114
1115         if((ma->mode & MA_HALOTEX) && ma->mtex[0])
1116                 har->tex= 1;
1117         
1118         for(i=0; i<MAX_MTEX; i++)
1119                 if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
1120                         mtex= ma->mtex[i];
1121                         copy_v3_v3(texvec, vec);
1122
1123                         if(mtex->texco & TEXCO_NORM) {
1124                                 ;
1125                         }
1126                         else if(mtex->texco & TEXCO_OBJECT) {
1127                                 if(mtex->object)
1128                                         mul_m4_v3(mtex->object->imat_ren,texvec);
1129                         }
1130                         else if(mtex->texco & TEXCO_GLOB){
1131                                 copy_v3_v3(texvec,vec);
1132                         }
1133                         else if(mtex->texco & TEXCO_UV && uvco){
1134                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
1135                                 if(uv_index<0)
1136                                         uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
1137
1138                                 uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
1139
1140                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1141                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1142                                 texvec[2]=0.0f;
1143                         }
1144                         else if(mtex->texco & TEXCO_PARTICLE) {
1145                                 /* particle coordinates in range [0,1] */
1146                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1147                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1148                                 texvec[2] = pa_co[2];
1149                         }
1150                         else if(orco) {
1151                                 copy_v3_v3(texvec, orco);
1152                         }
1153
1154                         hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1155
1156                         //yn= tin*mtex->colfac;
1157                         //zn= tin*mtex->alphafac;
1158                         if(mtex->mapto & MAP_COL) {
1159                                 tex[0]=tr;
1160                                 tex[1]=tg;
1161                                 tex[2]=tb;
1162                                 out[0]=har->r;
1163                                 out[1]=har->g;
1164                                 out[2]=har->b;
1165
1166                                 texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
1167                         //      zn= 1.0-yn;
1168                                 //har->r= (yn*tr+ zn*ma->r);
1169                                 //har->g= (yn*tg+ zn*ma->g);
1170                                 //har->b= (yn*tb+ zn*ma->b);
1171                                 har->r= in[0];
1172                                 har->g= in[1];
1173                                 har->b= in[2];
1174                         }
1175
1176                         /* alpha returned, so let's use it instead of intensity */
1177                         if(hasrgb)
1178                                 tin = ta;
1179
1180                         if(mtex->mapto & MAP_ALPHA)
1181                                 har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->alphafac,mtex->blendtype);
1182                         if(mtex->mapto & MAP_HAR)
1183                                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var,((float)har->hard)/127.0f,tin,mtex->hardfac,mtex->blendtype);
1184                         if(mtex->mapto & MAP_RAYMIRR)
1185                                 har->hasize = 100.0f*texture_value_blend(mtex->def_var,har->hasize/100.0f,tin,mtex->raymirrfac,mtex->blendtype);
1186                         if(mtex->mapto & MAP_TRANSLU) {
1187                                 float add = texture_value_blend(mtex->def_var,(float)har->add/255.0f,tin,mtex->translfac,mtex->blendtype);
1188                                 CLAMP(add, 0.f, 1.f);
1189                                 har->add = 255.0f*add;
1190                         }
1191                         /* now what on earth is this good for?? */
1192                         //if(mtex->texco & 16) {
1193                         //      har->alfa= tin;
1194                         //}
1195                 }
1196
1197         return har;
1198 }
1199
1200 /* -------------------------- operations on entire database ----------------------- */
1201
1202 /* ugly function for halos in panorama */
1203 static int panotestclip(Render *re, int do_pano, float *v)
1204 {
1205         /* to be used for halos en infos */
1206         float abs4;
1207         short c=0;
1208
1209         if(do_pano==0) return testclip(v);
1210
1211         abs4= fabs(v[3]);
1212
1213         if(v[2]< -abs4) c=16;           /* this used to be " if(v[2]<0) ", see clippz() */
1214         else if(v[2]> abs4) c+= 32;
1215
1216         if( v[1]>abs4) c+=4;
1217         else if( v[1]< -abs4) c+=8;
1218
1219         abs4*= re->xparts;
1220         if( v[0]>abs4) c+=2;
1221         else if( v[0]< -abs4) c+=1;
1222
1223         return c;
1224 }
1225
1226 /*
1227   This adds the hcs coordinates to vertices. It iterates over all
1228   vertices, halos and faces. After the conversion, we clip in hcs.
1229
1230   Elsewhere, all primites are converted to vertices. 
1231   Called in 
1232   - envmapping (envmap.c)
1233   - shadow buffering (shadbuf.c)
1234 */
1235
1236 void project_renderdata(Render *re, void (*projectfunc)(const float *, float mat[][4], float *),  int do_pano, float xoffs, int UNUSED(do_buckets))
1237 {
1238         ObjectRen *obr;
1239         HaloRen *har = NULL;
1240         float zn, vec[3], hoco[4];
1241         int a;
1242
1243         if(do_pano) {
1244                 float panophi= xoffs;
1245                 
1246                 re->panosi= sin(panophi);
1247                 re->panoco= cos(panophi);
1248         }
1249
1250         for(obr=re->objecttable.first; obr; obr=obr->next) {
1251                 /* calculate view coordinates (and zbuffer value) */
1252                 for(a=0; a<obr->tothalo; a++) {
1253                         if((a & 255)==0) har= obr->bloha[a>>8];
1254                         else har++;
1255
1256                         if(do_pano) {
1257                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1258                                 vec[1]= har->co[1];
1259                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1260                         }
1261                         else {
1262                                 copy_v3_v3(vec, har->co);
1263                         }
1264
1265                         projectfunc(vec, re->winmat, hoco);
1266                         
1267                         /* we clip halos less critical, but not for the Z */
1268                         hoco[0]*= 0.5f;
1269                         hoco[1]*= 0.5f;
1270                         
1271                         if( panotestclip(re, do_pano, hoco) ) {
1272                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1273                         }
1274                         else if(hoco[3]<0.0f) {
1275                                 har->miny= har->maxy= -10000;   /* render clips it */
1276                         }
1277                         else /* do the projection...*/
1278                         {
1279                                 /* bring back hocos */
1280                                 hoco[0]*= 2.0f;
1281                                 hoco[1]*= 2.0f;
1282                                 
1283                                 zn= hoco[3];
1284                                 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1285                                 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
1286                         
1287                                 /* this should be the zbuffer coordinate */
1288                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1289                                 /* taking this from the face clip functions? seems ok... */
1290                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1291                                 
1292                                 vec[0]+= har->hasize;
1293                                 projectfunc(vec, re->winmat, hoco);
1294                                 vec[0]-= har->hasize;
1295                                 zn= hoco[3];
1296                                 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
1297                         
1298                                 /* this clip is not really OK, to prevent stars to become too large */
1299                                 if(har->type & HA_ONLYSKY) {
1300                                         if(har->rad>3.0f) har->rad= 3.0f;
1301                                 }
1302                         
1303                                 har->radsq= har->rad*har->rad;
1304                         
1305                                 har->miny= har->ys - har->rad/re->ycor;
1306                                 har->maxy= har->ys + har->rad/re->ycor;
1307                         
1308                                 /* the Zd value is still not really correct for pano */
1309                         
1310                                 vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
1311                                 projectfunc(vec, re->winmat, hoco);
1312                                 zn= hoco[3];
1313                                 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
1314                                 har->zd= CLAMPIS(zn, 0, INT_MAX);
1315                         
1316                         }
1317                         
1318                 }
1319         }
1320 }
1321
1322 /* ------------------------------------------------------------------------- */
1323
1324 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
1325 {
1326         ObjectInstanceRen *obi;
1327         float mat3[3][3];
1328
1329         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1330         obi->obr= obr;
1331         obi->ob= ob;
1332         obi->par= par;
1333         obi->index= index;
1334         obi->psysindex= psysindex;
1335         obi->lay= lay;
1336
1337         if(mat) {
1338                 copy_m4_m4(obi->mat, mat);
1339                 copy_m3_m4(mat3, mat);
1340                 invert_m3_m3(obi->nmat, mat3);
1341                 transpose_m3(obi->nmat);
1342                 obi->flag |= R_DUPLI_TRANSFORMED;
1343         }
1344
1345         BLI_addtail(&re->instancetable, obi);
1346
1347         return obi;
1348 }
1349
1350 void RE_makeRenderInstances(Render *re)
1351 {
1352         ObjectInstanceRen *obi, *oldobi;
1353         ListBase newlist;
1354         int tot;
1355
1356         /* convert list of object instances to an array for index based lookup */
1357         tot= BLI_countlist(&re->instancetable);
1358         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1359         re->totinstance= tot;
1360         newlist.first= newlist.last= NULL;
1361
1362         obi= re->objectinstance;
1363         for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1364                 *obi= *oldobi;
1365
1366                 if(obi->obr) {
1367                         obi->prev= obi->next= NULL;
1368                         BLI_addtail(&newlist, obi);
1369                         obi++;
1370                 }
1371                 else
1372                         re->totinstance--;
1373         }
1374
1375         BLI_freelistN(&re->instancetable);
1376         re->instancetable= newlist;
1377 }
1378
1379 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
1380 {
1381         float mat[4][4], vec[4];
1382         int a, fl, flag= -1;
1383
1384         copy_m4_m4(mat, winmat);
1385
1386         for(a=0; a<8; a++) {
1387                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1388                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1389                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1390                 vec[3]= 1.0;
1391                 mul_m4_v4(mat, vec);
1392
1393                 fl= 0;
1394                 if(bounds) {
1395                         if(vec[0] < bounds[0]*vec[3]) fl |= 1;
1396                         else if(vec[0] > bounds[1]*vec[3]) fl |= 2;
1397                         
1398                         if(vec[1] > bounds[3]*vec[3]) fl |= 4;
1399                         else if(vec[1]< bounds[2]*vec[3]) fl |= 8;
1400                 }
1401                 else {
1402                         if(vec[0] < -vec[3]) fl |= 1;
1403                         else if(vec[0] > vec[3]) fl |= 2;
1404                         
1405                         if(vec[1] > vec[3]) fl |= 4;
1406                         else if(vec[1] < -vec[3]) fl |= 8;
1407                 }
1408                 if(vec[2] < -vec[3]) fl |= 16;
1409                 else if(vec[2] > vec[3]) fl |= 32;
1410
1411                 flag &= fl;
1412                 if(flag==0) return 0;
1413         }
1414
1415         return flag;
1416 }
1417