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