621831fb34111883f64f8423e43c9d9afbfdbedb
[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 numtf = 0, numcol = 0, i, mtfn, mcn;
487
488         if (CustomData_has_layer(data, CD_MTFACE)) {
489                 numtf= CustomData_number_of_layers(data, CD_MTFACE);
490                 obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
491         }
492
493         if (CustomData_has_layer(data, CD_MCOL)) {
494                 numcol= CustomData_number_of_layers(data, CD_MCOL);
495                 obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "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= CLAMPIS(layer->active_rnd, 0, numtf);
504                         obr->bakemtface= layer->active;
505                 }
506                 else if (layer->type == CD_MCOL) {
507                         strcpy(obr->mcol[mcn++], layer->name);
508                         obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
509                 }
510         }
511 }
512
513 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
514 {
515         VlakTableNode *temp;
516         VlakRen *v;
517         int a;
518
519         if(nr<0) {
520                 printf("error in findOrAddVlak: %d\n",nr);
521                 return obr->vlaknodes[0].vlak;
522         }
523         a= nr>>8;
524         
525         if (a>=obr->vlaknodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
526                 temp= obr->vlaknodes;
527                 
528                 obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
529                 if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
530                 memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
531
532                 obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
533                 if(temp) MEM_freeN(temp);       
534         }
535
536         v= obr->vlaknodes[a].vlak;
537         
538         if(v==NULL) {
539                 int i;
540
541                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
542                 obr->vlaknodes[a].vlak= v;
543
544                 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
545                         v[a].index= i;
546         }
547         v+= (nr & 255);
548         return v;
549 }
550
551 /* ------------------------------------------------------------------------ */
552
553 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
554 {
555         float *surfnor;
556         int nr= strand->index>>8;
557         
558         surfnor= obr->strandnodes[nr].surfnor;
559         if(surfnor==NULL) {
560                 if(verify) 
561                         surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
562                 else
563                         return NULL;
564         }
565         return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
566 }
567
568 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
569 {
570         StrandTableNode *node;
571         int nr= strand->index>>8, strandindex= (strand->index&255);
572         int index= (n<<8) + strandindex;
573
574         node= &obr->strandnodes[nr];
575
576         if(verify) {
577                 if(n>=node->totuv) {
578                         float *uv= node->uv;
579                         int size= (n+1)*256;
580
581                         node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
582
583                         if(uv) {
584                                 size= node->totuv*256;
585                                 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
586                                 MEM_freeN(uv);
587                         }
588
589                         node->totuv= n+1;
590                 }
591         }
592         else {
593                 if(n>=node->totuv)
594                         return NULL;
595
596                 if(name) *name= obr->mtface[n];
597         }
598
599         return node->uv + index*RE_UV_ELEMS;
600 }
601
602 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
603 {
604         StrandTableNode *node;
605         int nr= strand->index>>8, strandindex= (strand->index&255);
606         int index= (n<<8) + strandindex;
607
608         node= &obr->strandnodes[nr];
609
610         if(verify) {
611                 if(n>=node->totmcol) {
612                         MCol *mcol= node->mcol;
613                         int size= (n+1)*256;
614
615                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
616
617                         if(mcol) {
618                                 size= node->totmcol*256;
619                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
620                                 MEM_freeN(mcol);
621                         }
622
623                         node->totmcol= n+1;
624                 }
625         }
626         else {
627                 if(n>=node->totmcol)
628                         return NULL;
629
630                 if(name) *name= obr->mcol[n];
631         }
632
633         return node->mcol + index*RE_MCOL_ELEMS;
634 }
635
636 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
637 {
638         float *simplify;
639         int nr= strand->index>>8;
640         
641         simplify= obr->strandnodes[nr].simplify;
642         if(simplify==NULL) {
643                 if(verify) 
644                         simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
645                 else
646                         return NULL;
647         }
648         return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
649 }
650
651 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
652 {
653         int *face;
654         int nr= strand->index>>8;
655         
656         face= obr->strandnodes[nr].face;
657         if(face==NULL) {
658                 if(verify) 
659                         face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
660                 else
661                         return NULL;
662         }
663         return face + (strand->index & 255)*RE_FACE_ELEMS;
664 }
665
666 /* winspeed is exception, it is stored per instance */
667 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
668 {
669         float *winspeed;
670         int totvector;
671         
672         winspeed= obi->vectors;
673         if(winspeed==NULL) {
674                 if(verify) {
675                         totvector= obi->obr->totvert + obi->obr->totstrand;
676                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
677                 }
678                 else
679                         return NULL;
680         }
681         return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
682 }
683
684 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
685 {
686         StrandTableNode *temp;
687         StrandRen *v;
688         int a;
689
690         if(nr<0) {
691                 printf("error in findOrAddStrand: %d\n",nr);
692                 return obr->strandnodes[0].strand;
693         }
694         a= nr>>8;
695         
696         if (a>=obr->strandnodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
697                 temp= obr->strandnodes;
698                 
699                 obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes");
700                 if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
701                 memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
702
703                 obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
704                 if(temp) MEM_freeN(temp);       
705         }
706
707         v= obr->strandnodes[a].strand;
708         
709         if(v==NULL) {
710                 int i;
711
712                 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
713                 obr->strandnodes[a].strand= v;
714
715                 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
716                         v[a].index= i;
717         }
718         v+= (nr & 255);
719         return v;
720 }
721
722 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
723 {
724         StrandBuffer *strandbuf;
725
726         strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
727         strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
728         strandbuf->totvert= totvert;
729         strandbuf->obr= obr;
730
731         obr->strandbuf= strandbuf;
732
733         return strandbuf;
734 }
735
736 /* ------------------------------------------------------------------------ */
737
738 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
739 {
740         ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
741         
742         BLI_addtail(&re->objecttable, obr);
743         obr->ob= ob;
744         obr->par= par;
745         obr->index= index;
746         obr->psysindex= psysindex;
747         obr->lay= lay;
748
749         return obr;
750 }
751
752 void free_renderdata_vertnodes(VertTableNode *vertnodes)
753 {
754         int a;
755         
756         if(vertnodes==NULL) return;
757         
758         for(a=0; vertnodes[a].vert; a++) {
759                 MEM_freeN(vertnodes[a].vert);
760                 
761                 if(vertnodes[a].rad)
762                         MEM_freeN(vertnodes[a].rad);
763                 if(vertnodes[a].sticky)
764                         MEM_freeN(vertnodes[a].sticky);
765                 if(vertnodes[a].strand)
766                         MEM_freeN(vertnodes[a].strand);
767                 if(vertnodes[a].tangent)
768                         MEM_freeN(vertnodes[a].tangent);
769                 if(vertnodes[a].stress)
770                         MEM_freeN(vertnodes[a].stress);
771                 if(vertnodes[a].winspeed)
772                         MEM_freeN(vertnodes[a].winspeed);
773         }
774         
775         MEM_freeN(vertnodes);
776 }
777
778 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
779 {
780         int a;
781         
782         if(vlaknodes==NULL) return;
783         
784         for(a=0; vlaknodes[a].vlak; a++) {
785                 MEM_freeN(vlaknodes[a].vlak);
786                 
787                 if(vlaknodes[a].mtface)
788                         MEM_freeN(vlaknodes[a].mtface);
789                 if(vlaknodes[a].mcol)
790                         MEM_freeN(vlaknodes[a].mcol);
791                 if(vlaknodes[a].surfnor)
792                         MEM_freeN(vlaknodes[a].surfnor);
793                 if(vlaknodes[a].tangent)
794                         MEM_freeN(vlaknodes[a].tangent);
795                 if(vlaknodes[a].radface)
796                         MEM_freeN(vlaknodes[a].radface);
797         }
798         
799         MEM_freeN(vlaknodes);
800 }
801
802 void free_renderdata_strandnodes(StrandTableNode *strandnodes)
803 {
804         int a;
805         
806         if(strandnodes==NULL) return;
807         
808         for(a=0; strandnodes[a].strand; a++) {
809                 MEM_freeN(strandnodes[a].strand);
810                 
811                 if(strandnodes[a].uv)
812                         MEM_freeN(strandnodes[a].uv);
813                 if(strandnodes[a].mcol)
814                         MEM_freeN(strandnodes[a].mcol);
815                 if(strandnodes[a].winspeed)
816                         MEM_freeN(strandnodes[a].winspeed);
817                 if(strandnodes[a].surfnor)
818                         MEM_freeN(strandnodes[a].surfnor);
819                 if(strandnodes[a].simplify)
820                         MEM_freeN(strandnodes[a].simplify);
821                 if(strandnodes[a].face)
822                         MEM_freeN(strandnodes[a].face);
823         }
824         
825         MEM_freeN(strandnodes);
826 }
827
828 void free_renderdata_tables(Render *re)
829 {
830         ObjectInstanceRen *obi;
831         ObjectRen *obr;
832         StrandBuffer *strandbuf;
833         int a=0;
834         
835         for(obr=re->objecttable.first; obr; obr=obr->next) {
836                 if(obr->vertnodes) {
837                         free_renderdata_vertnodes(obr->vertnodes);
838                         obr->vertnodes= NULL;
839                         obr->vertnodeslen= 0;
840                 }
841
842                 if(obr->vlaknodes) {
843                         free_renderdata_vlaknodes(obr->vlaknodes);
844                         obr->vlaknodes= NULL;
845                         obr->vlaknodeslen= 0;
846                         obr->totvlak= 0;
847                 }
848
849                 if(obr->bloha) {
850                         for(a=0; obr->bloha[a]; a++)
851                                 MEM_freeN(obr->bloha[a]);
852
853                         MEM_freeN(obr->bloha);
854                         obr->bloha= NULL;
855                         obr->blohalen= 0;
856                 }
857
858                 if(obr->strandnodes) {
859                         free_renderdata_strandnodes(obr->strandnodes);
860                         obr->strandnodes= NULL;
861                         obr->strandnodeslen= 0;
862                 }
863
864                 strandbuf= obr->strandbuf;
865                 if(strandbuf) {
866                         if(strandbuf->vert) MEM_freeN(strandbuf->vert);
867                         if(strandbuf->bound) MEM_freeN(strandbuf->bound);
868                         MEM_freeN(strandbuf);
869                 }
870
871                 if(obr->mtface)
872                         MEM_freeN(obr->mtface);
873                 if(obr->mcol)
874                         MEM_freeN(obr->mcol);
875         }
876
877         if(re->objectinstance) {
878                 for(obi=re->instancetable.first; obi; obi=obi->next)
879                         if(obi->vectors)
880                                 MEM_freeN(obi->vectors);
881
882                 MEM_freeN(re->objectinstance);
883                 re->objectinstance= NULL;
884                 re->totinstance= 0;
885                 re->instancetable.first= re->instancetable.last= NULL;
886         }
887
888         if(re->sortedhalos) {
889                 MEM_freeN(re->sortedhalos);
890                 re->sortedhalos= NULL;
891         }
892
893         BLI_freelistN(&re->customdata_names);
894         BLI_freelistN(&re->objecttable);
895         BLI_freelistN(&re->instancetable);
896 }
897
898 /* ------------------------------------------------------------------------ */
899
900 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
901 {
902         HaloRen *h, **temp;
903         int a;
904
905         if(nr<0) {
906                 printf("error in findOrAddHalo: %d\n",nr);
907                 return NULL;
908         }
909         a= nr>>8;
910         
911         if (a>=obr->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
912                 //printf("Allocating %i more halo groups.  %i total.\n", 
913                 //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
914                 temp=obr->bloha;
915                 
916                 obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
917                 if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
918                 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
919                 obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
920                 if(temp) MEM_freeN(temp);       
921         }
922         
923         h= obr->bloha[a];
924         if(h==NULL) {
925                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
926                 obr->bloha[a]= h;
927         }
928         h+= (nr & 255);
929         return h;
930 }
931
932 /* ------------------------------------------------------------------------- */
933
934 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   float *vec1, 
935                                   float *orco,   float hasize,   float vectsize, int seed)
936 {
937         HaloRen *har;
938         MTex *mtex;
939         float tin, tr, tg, tb, ta;
940         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
941
942         if(hasize==0.0) return NULL;
943
944         projectverto(vec, re->winmat, hoco);
945         if(hoco[3]==0.0) return NULL;
946         if(vec1) {
947                 projectverto(vec1, re->winmat, hoco1);
948                 if(hoco1[3]==0.0) return NULL;
949         }
950
951         har= RE_findOrAddHalo(obr, obr->tothalo++);
952         VECCOPY(har->co, vec);
953         har->hasize= hasize;
954
955         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
956         /* we do it here for sorting of halos */
957         zn= hoco[3];
958         har->xs= 0.5*re->winx*(hoco[0]/zn);
959         har->ys= 0.5*re->winy*(hoco[1]/zn);
960         har->zs= 0x7FFFFF*(hoco[2]/zn);
961         
962         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
963         
964         /* halovect */
965         if(vec1) {
966
967                 har->type |= HA_VECT;
968
969                 xn=  har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
970                 yn=  har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
971                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
972                 else zn= atan2(yn, xn);
973
974                 har->sin= sin(zn);
975                 har->cos= cos(zn);
976                 zn= VecLenf(vec1, vec);
977
978                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
979                 
980                 VecSubf(har->no, vec, vec1);
981                 Normalize(har->no);
982         }
983
984         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
985
986         har->alfa= ma->alpha;
987         har->r= ma->r;
988         har->g= ma->g;
989         har->b= ma->b;
990         har->add= (255.0*ma->add);
991         har->mat= ma;
992         har->hard= ma->har;
993         har->seed= seed % 256;
994
995         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
996         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
997         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
998         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
999
1000
1001         if(ma->mtex[0]) {
1002
1003                 if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
1004                 else {
1005
1006                         mtex= ma->mtex[0];
1007                         VECCOPY(texvec, vec);
1008
1009                         if(mtex->texco & TEXCO_NORM) {
1010                                 ;
1011                         }
1012                         else if(mtex->texco & TEXCO_OBJECT) {
1013                                 /* texvec[0]+= imatbase->ivec[0]; */
1014                                 /* texvec[1]+= imatbase->ivec[1]; */
1015                                 /* texvec[2]+= imatbase->ivec[2]; */
1016                                 /* Mat3MulVecfl(imatbase->imat, texvec); */
1017                         }
1018                         else {
1019                                 if(orco) {
1020                                         VECCOPY(texvec, orco);
1021                                 }
1022                         }
1023
1024                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
1025
1026                         yn= tin*mtex->colfac;
1027                         zn= tin*mtex->varfac;
1028
1029                         if(mtex->mapto & MAP_COL) {
1030                                 zn= 1.0-yn;
1031                                 har->r= (yn*tr+ zn*ma->r);
1032                                 har->g= (yn*tg+ zn*ma->g);
1033                                 har->b= (yn*tb+ zn*ma->b);
1034                         }
1035                         if(mtex->texco & TEXCO_UV) {
1036                                 har->alfa= tin;
1037                         }
1038                         if(mtex->mapto & MAP_ALPHA)
1039                                 har->alfa= tin;
1040                 }
1041         }
1042
1043         return har;
1044 }
1045
1046 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
1047                                   float *orco, float *uvco, float hasize, float vectsize, int seed)
1048 {
1049         HaloRen *har;
1050         MTex *mtex;
1051         float tin, tr, tg, tb, ta;
1052         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
1053         int i;
1054
1055         if(hasize==0.0) return NULL;
1056
1057         projectverto(vec, re->winmat, hoco);
1058         if(hoco[3]==0.0) return NULL;
1059         if(vec1) {
1060                 projectverto(vec1, re->winmat, hoco1);
1061                 if(hoco1[3]==0.0) return NULL;
1062         }
1063
1064         har= RE_findOrAddHalo(obr, obr->tothalo++);
1065         VECCOPY(har->co, vec);
1066         har->hasize= hasize;
1067
1068         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1069         /* we do it here for sorting of halos */
1070         zn= hoco[3];
1071         har->xs= 0.5*re->winx*(hoco[0]/zn);
1072         har->ys= 0.5*re->winy*(hoco[1]/zn);
1073         har->zs= 0x7FFFFF*(hoco[2]/zn);
1074         
1075         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1076         
1077         /* halovect */
1078         if(vec1) {
1079
1080                 har->type |= HA_VECT;
1081
1082                 xn=  har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
1083                 yn=  har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
1084                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
1085                 else zn= atan2(yn, xn);
1086
1087                 har->sin= sin(zn);
1088                 har->cos= cos(zn);
1089                 zn= VecLenf(vec1, vec)*0.5;
1090
1091                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
1092                 
1093                 VecSubf(har->no, vec, vec1);
1094                 Normalize(har->no);
1095         }
1096
1097         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1098
1099         har->alfa= ma->alpha;
1100         har->r= ma->r;
1101         har->g= ma->g;
1102         har->b= ma->b;
1103         har->add= (255.0*ma->add);
1104         har->mat= ma;
1105         har->hard= ma->har;
1106         har->seed= seed % 256;
1107
1108         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1109         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1110         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1111         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1112
1113         if((ma->mode & MA_HALOTEX) && ma->mtex[0]){
1114                 har->tex= 1;
1115                 i=1;
1116         }
1117         
1118         for(i=0; i<MAX_MTEX; i++)
1119                 if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
1120                         mtex= ma->mtex[i];
1121                         VECCOPY(texvec, vec);
1122
1123                         if(mtex->texco & TEXCO_NORM) {
1124                                 ;
1125                         }
1126                         else if(mtex->texco & TEXCO_OBJECT) {
1127                                 if(mtex->object){
1128                                         float imat[4][4];
1129                                         /* imat should really be cached somewhere before this */
1130                                         Mat4Invert(imat,mtex->object->obmat);
1131                                         Mat4MulVecfl(imat,texvec);
1132                                 }
1133                                 /* texvec[0]+= imatbase->ivec[0]; */
1134                                 /* texvec[1]+= imatbase->ivec[1]; */
1135                                 /* texvec[2]+= imatbase->ivec[2]; */
1136                                 /* Mat3MulVecfl(imatbase->imat, texvec); */
1137                         }
1138                         else if(mtex->texco & TEXCO_GLOB){
1139                                 VECCOPY(texvec,vec);
1140                         }
1141                         else if(mtex->texco & TEXCO_UV && uvco){
1142                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
1143                                 if(uv_index<0)
1144                                         uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
1145
1146                                 uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
1147
1148                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1149                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1150                                 texvec[2]=0.0f;
1151                         }
1152                         else if(orco) {
1153                                 VECCOPY(texvec, orco);
1154                         }
1155
1156                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
1157
1158                         //yn= tin*mtex->colfac;
1159                         //zn= tin*mtex->varfac;
1160                         if(mtex->mapto & MAP_COL) {
1161                                 tex[0]=tr;
1162                                 tex[1]=tg;
1163                                 tex[2]=tb;
1164                                 out[0]=har->r;
1165                                 out[1]=har->g;
1166                                 out[2]=har->b;
1167
1168                                 texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
1169                         //      zn= 1.0-yn;
1170                                 //har->r= (yn*tr+ zn*ma->r);
1171                                 //har->g= (yn*tg+ zn*ma->g);
1172                                 //har->b= (yn*tb+ zn*ma->b);
1173                                 har->r= in[0];
1174                                 har->g= in[1];
1175                                 har->b= in[2];
1176                         }
1177                         if(mtex->mapto & MAP_ALPHA)
1178                                 har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_ALPHA);
1179                         if(mtex->mapto & MAP_HAR)
1180                                 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);
1181                         if(mtex->mapto & MAP_RAYMIRR)
1182                                 har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_RAYMIRR);
1183                         /* now what on earth is this good for?? */
1184                         //if(mtex->texco & 16) {
1185                         //      har->alfa= tin;
1186                         //}
1187                 }
1188
1189         return har;
1190 }
1191
1192 /* -------------------------- operations on entire database ----------------------- */
1193
1194 /* ugly function for halos in panorama */
1195 static int panotestclip(Render *re, int do_pano, float *v)
1196 {
1197         /* to be used for halos en infos */
1198         float abs4;
1199         short c=0;
1200
1201         if(do_pano==0) return testclip(v);
1202
1203         abs4= fabs(v[3]);
1204
1205         if(v[2]< -abs4) c=16;           /* this used to be " if(v[2]<0) ", see clippz() */
1206         else if(v[2]> abs4) c+= 32;
1207
1208         if( v[1]>abs4) c+=4;
1209         else if( v[1]< -abs4) c+=8;
1210
1211         abs4*= re->xparts;
1212         if( v[0]>abs4) c+=2;
1213         else if( v[0]< -abs4) c+=1;
1214
1215         return c;
1216 }
1217
1218 /*
1219   This adds the hcs coordinates to vertices. It iterates over all
1220   vertices, halos and faces. After the conversion, we clip in hcs.
1221
1222   Elsewhere, all primites are converted to vertices. 
1223   Called in 
1224   - envmapping (envmap.c)
1225   - shadow buffering (shadbuf.c)
1226 */
1227
1228 void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, float xoffs, int do_buckets)
1229 {
1230         ObjectRen *obr;
1231         HaloRen *har = NULL;
1232         float zn, vec[3], hoco[4];
1233         int a;
1234
1235         if(do_pano) {
1236                 float panophi= xoffs;
1237                 
1238                 re->panosi= sin(panophi);
1239                 re->panoco= cos(panophi);
1240         }
1241
1242         for(obr=re->objecttable.first; obr; obr=obr->next) {
1243                 /* calculate view coordinates (and zbuffer value) */
1244                 for(a=0; a<obr->tothalo; a++) {
1245                         if((a & 255)==0) har= obr->bloha[a>>8];
1246                         else har++;
1247
1248                         if(do_pano) {
1249                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1250                                 vec[1]= har->co[1];
1251                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1252                         }
1253                         else {
1254                                 VECCOPY(vec, har->co);
1255                         }
1256
1257                         projectfunc(vec, re->winmat, hoco);
1258                         
1259                         /* we clip halos less critical, but not for the Z */
1260                         hoco[0]*= 0.5;
1261                         hoco[1]*= 0.5;
1262                         
1263                         if( panotestclip(re, do_pano, hoco) ) {
1264                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1265                         }
1266                         else if(hoco[3]<0.0) {
1267                                 har->miny= har->maxy= -10000;   /* render clips it */
1268                         }
1269                         else /* do the projection...*/
1270                         {
1271                                 /* bring back hocos */
1272                                 hoco[0]*= 2.0;
1273                                 hoco[1]*= 2.0;
1274                                 
1275                                 zn= hoco[3];
1276                                 har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1277                                 har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
1278                         
1279                                 /* this should be the zbuffer coordinate */
1280                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1281                                 /* taking this from the face clip functions? seems ok... */
1282                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1283                                 
1284                                 vec[0]+= har->hasize;
1285                                 projectfunc(vec, re->winmat, hoco);
1286                                 vec[0]-= har->hasize;
1287                                 zn= hoco[3];
1288                                 har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
1289                         
1290                                 /* this clip is not really OK, to prevent stars to become too large */
1291                                 if(har->type & HA_ONLYSKY) {
1292                                         if(har->rad>3.0) har->rad= 3.0;
1293                                 }
1294                         
1295                                 har->radsq= har->rad*har->rad;
1296                         
1297                                 har->miny= har->ys - har->rad/re->ycor;
1298                                 har->maxy= har->ys + har->rad/re->ycor;
1299                         
1300                                 /* the Zd value is still not really correct for pano */
1301                         
1302                                 vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
1303                                 projectfunc(vec, re->winmat, hoco);
1304                                 zn= hoco[3];
1305                                 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
1306                                 har->zd= CLAMPIS(zn, 0, INT_MAX);
1307                         
1308                         }
1309                         
1310                 }
1311         }
1312 }
1313
1314 /* ------------------------------------------------------------------------- */
1315
1316 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
1317 {
1318         ObjectInstanceRen *obi;
1319         float mat3[3][3];
1320
1321         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1322         obi->obr= obr;
1323         obi->ob= ob;
1324         obi->par= par;
1325         obi->index= index;
1326         obi->psysindex= psysindex;
1327         obi->lay= lay;
1328
1329         if(mat) {
1330                 Mat4CpyMat4(obi->mat, mat);
1331                 Mat3CpyMat4(mat3, mat);
1332                 Mat3Inv(obi->nmat, mat3);
1333                 Mat3Transp(obi->nmat);
1334                 obi->flag |= R_DUPLI_TRANSFORMED;
1335         }
1336
1337         BLI_addtail(&re->instancetable, obi);
1338
1339         return obi;
1340 }
1341
1342 void RE_makeRenderInstances(Render *re)
1343 {
1344         ObjectInstanceRen *obi, *oldobi;
1345         ListBase newlist;
1346         int tot;
1347
1348         /* convert list of object instances to an array for index based lookup */
1349         tot= BLI_countlist(&re->instancetable);
1350         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1351         re->totinstance= tot;
1352         newlist.first= newlist.last= NULL;
1353
1354         obi= re->objectinstance;
1355         for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1356                 *obi= *oldobi;
1357
1358                 if(obi->obr) {
1359                         obi->prev= obi->next= NULL;
1360                         BLI_addtail(&newlist, obi);
1361                         obi++;
1362                 }
1363                 else
1364                         re->totinstance--;
1365         }
1366
1367         BLI_freelistN(&re->instancetable);
1368         re->instancetable= newlist;
1369 }
1370
1371 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
1372 {
1373         float mat[4][4], vec[4];
1374         int a, fl, flag= -1;
1375
1376         Mat4CpyMat4(mat, winmat);
1377
1378         for(a=0; a<8; a++) {
1379                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1380                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1381                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1382                 vec[3]= 1.0;
1383                 Mat4MulVec4fl(mat, vec);
1384
1385                 fl= 0;
1386                 if(bounds) {
1387                         if(vec[0] > bounds[1]*vec[3]) fl |= 1;
1388                         if(vec[0]< bounds[0]*vec[3]) fl |= 2;
1389                         if(vec[1] > bounds[3]*vec[3]) fl |= 4;
1390                         if(vec[1]< bounds[2]*vec[3]) fl |= 8;
1391                 }
1392                 else {
1393                         if(vec[0] < -vec[3]) fl |= 1;
1394                         if(vec[0] > vec[3]) fl |= 2;
1395                         if(vec[1] < -vec[3]) fl |= 4;
1396                         if(vec[1] > vec[3]) fl |= 8;
1397                 }
1398                 if(vec[2] < -vec[3]) fl |= 16;
1399                 if(vec[2] > vec[3]) fl |= 32;
1400
1401                 flag &= fl;
1402                 if(flag==0) return 0;
1403         }
1404
1405         return flag;
1406 }
1407