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