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