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