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