bc61a26564dbcc232b433b77272bf337fabce147
[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 *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                         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,   float *vec,   float *vec1, 
935                                   float *orco,   float hasize,   float vectsize, int seed)
936 {
937         HaloRen *har;
938         MTex *mtex;
939         float tin, tr, tg, tb, ta;
940         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
941
942         if (hasize==0.0f) return NULL;
943
944         projectverto(vec, re->winmat, hoco);
945         if (hoco[3]==0.0f) return NULL;
946         if (vec1) {
947                 projectverto(vec1, re->winmat, hoco1);
948                 if (hoco1[3]==0.0f) return NULL;
949         }
950
951         har= RE_findOrAddHalo(obr, obr->tothalo++);
952         copy_v3_v3(har->co, vec);
953         har->hasize= hasize;
954
955         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
956         /* we do it here for sorting of halos */
957         zn= hoco[3];
958         har->xs= 0.5f*re->winx*(hoco[0]/zn);
959         har->ys= 0.5f*re->winy*(hoco[1]/zn);
960         har->zs= 0x7FFFFF*(hoco[2]/zn);
961         
962         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
963         
964         /* halovect */
965         if (vec1) {
966
967                 har->type |= HA_VECT;
968
969                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
970                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
971                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
972                 else zn= atan2(yn, xn);
973
974                 har->sin= sin(zn);
975                 har->cos= cos(zn);
976                 zn= len_v3v3(vec1, vec);
977
978                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
979                 
980                 sub_v3_v3v3(har->no, vec, vec1);
981                 normalize_v3(har->no);
982         }
983
984         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
985
986         har->alfa= ma->alpha;
987         har->r= ma->r;
988         har->g= ma->g;
989         har->b= ma->b;
990         har->add= (255.0f*ma->add);
991         har->mat= ma;
992         har->hard= ma->har;
993         har->seed= seed % 256;
994
995         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
996         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
997         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
998         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
999
1000
1001         if (ma->mtex[0]) {
1002
1003                 if ( (ma->mode & MA_HALOTEX) ) har->tex= 1;
1004                 else if (har->mat->septex & (1<<0));    /* only 1 level textures */
1005                 else {
1006
1007                         mtex= ma->mtex[0];
1008                         copy_v3_v3(texvec, vec);
1009
1010                         if (mtex->texco & TEXCO_NORM) {
1011                                 ;
1012                         }
1013                         else if (mtex->texco & TEXCO_OBJECT) {
1014                                 /* texvec[0]+= imatbase->ivec[0]; */
1015                                 /* texvec[1]+= imatbase->ivec[1]; */
1016                                 /* texvec[2]+= imatbase->ivec[2]; */
1017                                 /* mul_m3_v3(imatbase->imat, texvec); */
1018                         }
1019                         else {
1020                                 if (orco) {
1021                                         copy_v3_v3(texvec, orco);
1022                                 }
1023                         }
1024
1025                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1026
1027                         yn= tin*mtex->colfac;
1028                         //zn= tin*mtex->alphafac;
1029
1030                         if (mtex->mapto & MAP_COL) {
1031                                 zn= 1.0f-yn;
1032                                 har->r= (yn*tr+ zn*ma->r);
1033                                 har->g= (yn*tg+ zn*ma->g);
1034                                 har->b= (yn*tb+ zn*ma->b);
1035                         }
1036                         if (mtex->texco & TEXCO_UV) {
1037                                 har->alfa= tin;
1038                         }
1039                         if (mtex->mapto & MAP_ALPHA)
1040                                 har->alfa= tin;
1041                 }
1042         }
1043
1044         return har;
1045 }
1046
1047 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
1048                                   float *orco, float *uvco, float hasize, float vectsize, int seed, float *pa_co)
1049 {
1050         HaloRen *har;
1051         MTex *mtex;
1052         float tin, tr, tg, tb, ta;
1053         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3];
1054         int i, hasrgb;
1055
1056         if (hasize==0.0f) return NULL;
1057
1058         projectverto(vec, re->winmat, hoco);
1059         if (hoco[3]==0.0f) return NULL;
1060         if (vec1) {
1061                 projectverto(vec1, re->winmat, hoco1);
1062                 if (hoco1[3]==0.0f) return NULL;
1063         }
1064
1065         har= RE_findOrAddHalo(obr, obr->tothalo++);
1066         copy_v3_v3(har->co, vec);
1067         har->hasize= hasize;
1068
1069         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1070         /* we do it here for sorting of halos */
1071         zn= hoco[3];
1072         har->xs= 0.5f*re->winx*(hoco[0]/zn);
1073         har->ys= 0.5f*re->winy*(hoco[1]/zn);
1074         har->zs= 0x7FFFFF*(hoco[2]/zn);
1075         
1076         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1077         
1078         /* halovect */
1079         if (vec1) {
1080
1081                 har->type |= HA_VECT;
1082
1083                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1084                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1085                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1086                 else zn= atan2(yn, xn);
1087
1088                 har->sin= sin(zn);
1089                 har->cos= cos(zn);
1090                 zn= len_v3v3(vec1, vec)*0.5f;
1091
1092                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1093                 
1094                 sub_v3_v3v3(har->no, vec, vec1);
1095                 normalize_v3(har->no);
1096         }
1097
1098         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1099
1100         har->alfa= ma->alpha;
1101         har->r= ma->r;
1102         har->g= ma->g;
1103         har->b= ma->b;
1104         har->add= (255.0f*ma->add);
1105         har->mat= ma;
1106         har->hard= ma->har;
1107         har->seed= seed % 256;
1108
1109         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1110         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1111         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1112         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1113
1114         if ((ma->mode & MA_HALOTEX) && ma->mtex[0])
1115                 har->tex= 1;
1116         
1117         for (i=0; i<MAX_MTEX; i++)
1118                 if (ma->mtex[i] && (ma->septex & (1<<i))==0) {
1119                         mtex= ma->mtex[i];
1120                         copy_v3_v3(texvec, vec);
1121
1122                         if (mtex->texco & TEXCO_NORM) {
1123                                 ;
1124                         }
1125                         else if (mtex->texco & TEXCO_OBJECT) {
1126                                 if (mtex->object)
1127                                         mul_m4_v3(mtex->object->imat_ren, texvec);
1128                         }
1129                         else if (mtex->texco & TEXCO_GLOB) {
1130                                 copy_v3_v3(texvec, vec);
1131                         }
1132                         else if (mtex->texco & TEXCO_UV && uvco) {
1133                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname);
1134                                 if (uv_index<0)
1135                                         uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
1136
1137                                 uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
1138
1139                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1140                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1141                                 texvec[2]=0.0f;
1142                         }
1143                         else if (mtex->texco & TEXCO_PARTICLE) {
1144                                 /* particle coordinates in range [0, 1] */
1145                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1146                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1147                                 texvec[2] = pa_co[2];
1148                         }
1149                         else if (orco) {
1150                                 copy_v3_v3(texvec, orco);
1151                         }
1152
1153                         hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1154
1155                         //yn= tin*mtex->colfac;
1156                         //zn= tin*mtex->alphafac;
1157                         if (mtex->mapto & MAP_COL) {
1158                                 tex[0]=tr;
1159                                 tex[1]=tg;
1160                                 tex[2]=tb;
1161                                 out[0]=har->r;
1162                                 out[1]=har->g;
1163                                 out[2]=har->b;
1164
1165                                 texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype);
1166                         //      zn= 1.0-yn;
1167                                 //har->r= (yn*tr+ zn*ma->r);
1168                                 //har->g= (yn*tg+ zn*ma->g);
1169                                 //har->b= (yn*tb+ zn*ma->b);
1170                                 har->r= in[0];
1171                                 har->g= in[1];
1172                                 har->b= in[2];
1173                         }
1174
1175                         /* alpha returned, so let's use it instead of intensity */
1176                         if (hasrgb)
1177                                 tin = ta;
1178
1179                         if (mtex->mapto & MAP_ALPHA)
1180                                 har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype);
1181                         if (mtex->mapto & MAP_HAR)
1182                                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype);
1183                         if (mtex->mapto & MAP_RAYMIRR)
1184                                 har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype);
1185                         if (mtex->mapto & MAP_TRANSLU) {
1186                                 float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype);
1187                                 CLAMP(add, 0.f, 1.f);
1188                                 har->add = 255.0f*add;
1189                         }
1190                         /* now what on earth is this good for?? */
1191                         //if (mtex->texco & 16) {
1192                         //      har->alfa= tin;
1193                         //}
1194                 }
1195
1196         return har;
1197 }
1198
1199 /* -------------------------- operations on entire database ----------------------- */
1200
1201 /* ugly function for halos in panorama */
1202 static int panotestclip(Render *re, int do_pano, float *v)
1203 {
1204         /* to be used for halos en infos */
1205         float abs4;
1206         short c=0;
1207
1208         if (do_pano == FALSE) {
1209                 return testclip(v);
1210         }
1211
1212         abs4= fabs(v[3]);
1213
1214         if (v[2]< -abs4) c=16;          /* this used to be " if (v[2]<0) ", see clippz() */
1215         else if (v[2]> abs4) c+= 32;
1216
1217         if ( v[1]>abs4) c+=4;
1218         else if ( v[1]< -abs4) c+=8;
1219
1220         abs4*= re->xparts;
1221         if ( v[0]>abs4) c+=2;
1222         else if ( v[0]< -abs4) c+=1;
1223
1224         return c;
1225 }
1226
1227 /**
1228  * This adds the hcs coordinates to vertices. It iterates over all
1229  * vertices, halos and faces. After the conversion, we clip in hcs.
1230  *
1231  * Elsewhere, all primites are converted to vertices.
1232  * Called in
1233  * - envmapping (envmap.c)
1234  * - shadow buffering (shadbuf.c)
1235  */
1236
1237 void project_renderdata(Render *re, void (*projectfunc)(const float *, float mat[][4], float *),  int do_pano, float xoffs, int UNUSED(do_buckets))
1238 {
1239         ObjectRen *obr;
1240         HaloRen *har = NULL;
1241         float zn, vec[3], hoco[4];
1242         int a;
1243
1244         if (do_pano) {
1245                 float panophi= xoffs;
1246                 
1247                 re->panosi= sin(panophi);
1248                 re->panoco= cos(panophi);
1249         }
1250
1251         for (obr=re->objecttable.first; obr; obr=obr->next) {
1252                 /* calculate view coordinates (and zbuffer value) */
1253                 for (a=0; a<obr->tothalo; a++) {
1254                         if ((a & 255)==0) har= obr->bloha[a>>8];
1255                         else har++;
1256
1257                         if (do_pano) {
1258                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1259                                 vec[1]= har->co[1];
1260                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1261                         }
1262                         else {
1263                                 copy_v3_v3(vec, har->co);
1264                         }
1265
1266                         projectfunc(vec, re->winmat, hoco);
1267                         
1268                         /* we clip halos less critical, but not for the Z */
1269                         hoco[0]*= 0.5f;
1270                         hoco[1]*= 0.5f;
1271                         
1272                         if ( panotestclip(re, do_pano, hoco) ) {
1273                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1274                         }
1275                         else if (hoco[3]<0.0f) {
1276                                 har->miny= har->maxy= -10000;   /* render clips it */
1277                         }
1278                         else { /* do the projection...*/
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