Merged Soc 2009 - raytrace optimization [0]
[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->rayprimitives)
883                 {
884                         MEM_freeN(obr->rayprimitives);
885                         obr->rayprimitives = NULL;
886                 }
887                 if(obr->raytree)
888                 {
889                         RE_rayobject_free(obr->raytree);
890                         obr->raytree = NULL;
891                 }
892         }
893
894         if(re->objectinstance) {
895                 for(obi=re->instancetable.first; obi; obi=obi->next)
896                 {
897                         if(obi->vectors)
898                                 MEM_freeN(obi->vectors);
899
900                         if(obi->raytree)
901                                 RE_rayobject_free(obi->raytree);
902                 }
903
904                 MEM_freeN(re->objectinstance);
905                 re->objectinstance= NULL;
906                 re->totinstance= 0;
907                 re->instancetable.first= re->instancetable.last= NULL;
908         }
909
910         if(re->sortedhalos) {
911                 MEM_freeN(re->sortedhalos);
912                 re->sortedhalos= NULL;
913         }
914
915         BLI_freelistN(&re->customdata_names);
916         BLI_freelistN(&re->objecttable);
917         BLI_freelistN(&re->instancetable);
918 }
919
920 /* ------------------------------------------------------------------------ */
921
922 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
923 {
924         HaloRen *h, **temp;
925         int a;
926
927         if(nr<0) {
928                 printf("error in findOrAddHalo: %d\n",nr);
929                 return NULL;
930         }
931         a= nr>>8;
932         
933         if (a>=obr->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
934                 //printf("Allocating %i more halo groups.  %i total.\n", 
935                 //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
936                 temp=obr->bloha;
937                 
938                 obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
939                 if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
940                 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
941                 obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
942                 if(temp) MEM_freeN(temp);       
943         }
944         
945         h= obr->bloha[a];
946         if(h==NULL) {
947                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
948                 obr->bloha[a]= h;
949         }
950         h+= (nr & 255);
951         return h;
952 }
953
954 /* ------------------------------------------------------------------------- */
955
956 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   float *vec1, 
957                                   float *orco,   float hasize,   float vectsize, int seed)
958 {
959         HaloRen *har;
960         MTex *mtex;
961         float tin, tr, tg, tb, ta;
962         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
963
964         if(hasize==0.0) return NULL;
965
966         projectverto(vec, re->winmat, hoco);
967         if(hoco[3]==0.0) return NULL;
968         if(vec1) {
969                 projectverto(vec1, re->winmat, hoco1);
970                 if(hoco1[3]==0.0) return NULL;
971         }
972
973         har= RE_findOrAddHalo(obr, obr->tothalo++);
974         VECCOPY(har->co, vec);
975         har->hasize= hasize;
976
977         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
978         /* we do it here for sorting of halos */
979         zn= hoco[3];
980         har->xs= 0.5*re->winx*(hoco[0]/zn);
981         har->ys= 0.5*re->winy*(hoco[1]/zn);
982         har->zs= 0x7FFFFF*(hoco[2]/zn);
983         
984         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
985         
986         /* halovect */
987         if(vec1) {
988
989                 har->type |= HA_VECT;
990
991                 xn=  har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
992                 yn=  har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
993                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
994                 else zn= atan2(yn, xn);
995
996                 har->sin= sin(zn);
997                 har->cos= cos(zn);
998                 zn= VecLenf(vec1, vec);
999
1000                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
1001                 
1002                 VecSubf(har->no, vec, vec1);
1003                 Normalize(har->no);
1004         }
1005
1006         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1007
1008         har->alfa= ma->alpha;
1009         har->r= ma->r;
1010         har->g= ma->g;
1011         har->b= ma->b;
1012         har->add= (255.0*ma->add);
1013         har->mat= ma;
1014         har->hard= ma->har;
1015         har->seed= seed % 256;
1016
1017         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1018         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1019         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1020         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1021
1022
1023         if(ma->mtex[0]) {
1024
1025                 if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
1026                 else {
1027
1028                         mtex= ma->mtex[0];
1029                         VECCOPY(texvec, vec);
1030
1031                         if(mtex->texco & TEXCO_NORM) {
1032                                 ;
1033                         }
1034                         else if(mtex->texco & TEXCO_OBJECT) {
1035                                 /* texvec[0]+= imatbase->ivec[0]; */
1036                                 /* texvec[1]+= imatbase->ivec[1]; */
1037                                 /* texvec[2]+= imatbase->ivec[2]; */
1038                                 /* Mat3MulVecfl(imatbase->imat, texvec); */
1039                         }
1040                         else {
1041                                 if(orco) {
1042                                         VECCOPY(texvec, orco);
1043                                 }
1044                         }
1045
1046                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
1047
1048                         yn= tin*mtex->colfac;
1049                         zn= tin*mtex->alphafac;
1050
1051                         if(mtex->mapto & MAP_COL) {
1052                                 zn= 1.0-yn;
1053                                 har->r= (yn*tr+ zn*ma->r);
1054                                 har->g= (yn*tg+ zn*ma->g);
1055                                 har->b= (yn*tb+ zn*ma->b);
1056                         }
1057                         if(mtex->texco & TEXCO_UV) {
1058                                 har->alfa= tin;
1059                         }
1060                         if(mtex->mapto & MAP_ALPHA)
1061                                 har->alfa= tin;
1062                 }
1063         }
1064
1065         return har;
1066 }
1067
1068 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
1069                                   float *orco, float *uvco, float hasize, float vectsize, int seed)
1070 {
1071         HaloRen *har;
1072         MTex *mtex;
1073         float tin, tr, tg, tb, ta;
1074         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
1075         int i;
1076
1077         if(hasize==0.0) return NULL;
1078
1079         projectverto(vec, re->winmat, hoco);
1080         if(hoco[3]==0.0) return NULL;
1081         if(vec1) {
1082                 projectverto(vec1, re->winmat, hoco1);
1083                 if(hoco1[3]==0.0) return NULL;
1084         }
1085
1086         har= RE_findOrAddHalo(obr, obr->tothalo++);
1087         VECCOPY(har->co, vec);
1088         har->hasize= hasize;
1089
1090         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1091         /* we do it here for sorting of halos */
1092         zn= hoco[3];
1093         har->xs= 0.5*re->winx*(hoco[0]/zn);
1094         har->ys= 0.5*re->winy*(hoco[1]/zn);
1095         har->zs= 0x7FFFFF*(hoco[2]/zn);
1096         
1097         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1098         
1099         /* halovect */
1100         if(vec1) {
1101
1102                 har->type |= HA_VECT;
1103
1104                 xn=  har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
1105                 yn=  har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
1106                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
1107                 else zn= atan2(yn, xn);
1108
1109                 har->sin= sin(zn);
1110                 har->cos= cos(zn);
1111                 zn= VecLenf(vec1, vec)*0.5;
1112
1113                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
1114                 
1115                 VecSubf(har->no, vec, vec1);
1116                 Normalize(har->no);
1117         }
1118
1119         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1120
1121         har->alfa= ma->alpha;
1122         har->r= ma->r;
1123         har->g= ma->g;
1124         har->b= ma->b;
1125         har->add= (255.0*ma->add);
1126         har->mat= ma;
1127         har->hard= ma->har;
1128         har->seed= seed % 256;
1129
1130         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1131         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1132         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1133         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1134
1135         if((ma->mode & MA_HALOTEX) && ma->mtex[0]){
1136                 har->tex= 1;
1137                 i=1;
1138         }
1139         
1140         for(i=0; i<MAX_MTEX; i++)
1141                 if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
1142                         mtex= ma->mtex[i];
1143                         VECCOPY(texvec, vec);
1144
1145                         if(mtex->texco & TEXCO_NORM) {
1146                                 ;
1147                         }
1148                         else if(mtex->texco & TEXCO_OBJECT) {
1149                                 if(mtex->object){
1150                                         float imat[4][4];
1151                                         /* imat should really be cached somewhere before this */
1152                                         Mat4Invert(imat,mtex->object->obmat);
1153                                         Mat4MulVecfl(imat,texvec);
1154                                 }
1155                                 /* texvec[0]+= imatbase->ivec[0]; */
1156                                 /* texvec[1]+= imatbase->ivec[1]; */
1157                                 /* texvec[2]+= imatbase->ivec[2]; */
1158                                 /* Mat3MulVecfl(imatbase->imat, texvec); */
1159                         }
1160                         else if(mtex->texco & TEXCO_GLOB){
1161                                 VECCOPY(texvec,vec);
1162                         }
1163                         else if(mtex->texco & TEXCO_UV && uvco){
1164                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
1165                                 if(uv_index<0)
1166                                         uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
1167
1168                                 uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
1169
1170                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1171                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1172                                 texvec[2]=0.0f;
1173                         }
1174                         else if(orco) {
1175                                 VECCOPY(texvec, orco);
1176                         }
1177
1178                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
1179
1180                         //yn= tin*mtex->colfac;
1181                         //zn= tin*mtex->alphafac;
1182                         if(mtex->mapto & MAP_COL) {
1183                                 tex[0]=tr;
1184                                 tex[1]=tg;
1185                                 tex[2]=tb;
1186                                 out[0]=har->r;
1187                                 out[1]=har->g;
1188                                 out[2]=har->b;
1189
1190                                 texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
1191                         //      zn= 1.0-yn;
1192                                 //har->r= (yn*tr+ zn*ma->r);
1193                                 //har->g= (yn*tg+ zn*ma->g);
1194                                 //har->b= (yn*tb+ zn*ma->b);
1195                                 har->r= in[0];
1196                                 har->g= in[1];
1197                                 har->b= in[2];
1198                         }
1199                         if(mtex->mapto & MAP_ALPHA)
1200                                 har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->alphafac,mtex->blendtype);
1201                         if(mtex->mapto & MAP_HAR)
1202                                 har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->hardfac,mtex->blendtype);
1203                         if(mtex->mapto & MAP_RAYMIRR)
1204                                 har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->raymirrfac,mtex->blendtype);
1205                         /* now what on earth is this good for?? */
1206                         //if(mtex->texco & 16) {
1207                         //      har->alfa= tin;
1208                         //}
1209                 }
1210
1211         return har;
1212 }
1213
1214 /* -------------------------- operations on entire database ----------------------- */
1215
1216 /* ugly function for halos in panorama */
1217 static int panotestclip(Render *re, int do_pano, float *v)
1218 {
1219         /* to be used for halos en infos */
1220         float abs4;
1221         short c=0;
1222
1223         if(do_pano==0) return testclip(v);
1224
1225         abs4= fabs(v[3]);
1226
1227         if(v[2]< -abs4) c=16;           /* this used to be " if(v[2]<0) ", see clippz() */
1228         else if(v[2]> abs4) c+= 32;
1229
1230         if( v[1]>abs4) c+=4;
1231         else if( v[1]< -abs4) c+=8;
1232
1233         abs4*= re->xparts;
1234         if( v[0]>abs4) c+=2;
1235         else if( v[0]< -abs4) c+=1;
1236
1237         return c;
1238 }
1239
1240 /*
1241   This adds the hcs coordinates to vertices. It iterates over all
1242   vertices, halos and faces. After the conversion, we clip in hcs.
1243
1244   Elsewhere, all primites are converted to vertices. 
1245   Called in 
1246   - envmapping (envmap.c)
1247   - shadow buffering (shadbuf.c)
1248 */
1249
1250 void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, float xoffs, int do_buckets)
1251 {
1252         ObjectRen *obr;
1253         HaloRen *har = NULL;
1254         float zn, vec[3], hoco[4];
1255         int a;
1256
1257         if(do_pano) {
1258                 float panophi= xoffs;
1259                 
1260                 re->panosi= sin(panophi);
1261                 re->panoco= cos(panophi);
1262         }
1263
1264         for(obr=re->objecttable.first; obr; obr=obr->next) {
1265                 /* calculate view coordinates (and zbuffer value) */
1266                 for(a=0; a<obr->tothalo; a++) {
1267                         if((a & 255)==0) har= obr->bloha[a>>8];
1268                         else har++;
1269
1270                         if(do_pano) {
1271                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1272                                 vec[1]= har->co[1];
1273                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1274                         }
1275                         else {
1276                                 VECCOPY(vec, har->co);
1277                         }
1278
1279                         projectfunc(vec, re->winmat, hoco);
1280                         
1281                         /* we clip halos less critical, but not for the Z */
1282                         hoco[0]*= 0.5;
1283                         hoco[1]*= 0.5;
1284                         
1285                         if( panotestclip(re, do_pano, hoco) ) {
1286                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1287                         }
1288                         else if(hoco[3]<0.0) {
1289                                 har->miny= har->maxy= -10000;   /* render clips it */
1290                         }
1291                         else /* do the projection...*/
1292                         {
1293                                 /* bring back hocos */
1294                                 hoco[0]*= 2.0;
1295                                 hoco[1]*= 2.0;
1296                                 
1297                                 zn= hoco[3];
1298                                 har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1299                                 har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
1300                         
1301                                 /* this should be the zbuffer coordinate */
1302                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1303                                 /* taking this from the face clip functions? seems ok... */
1304                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1305                                 
1306                                 vec[0]+= har->hasize;
1307                                 projectfunc(vec, re->winmat, hoco);
1308                                 vec[0]-= har->hasize;
1309                                 zn= hoco[3];
1310                                 har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
1311                         
1312                                 /* this clip is not really OK, to prevent stars to become too large */
1313                                 if(har->type & HA_ONLYSKY) {
1314                                         if(har->rad>3.0) har->rad= 3.0;
1315                                 }
1316                         
1317                                 har->radsq= har->rad*har->rad;
1318                         
1319                                 har->miny= har->ys - har->rad/re->ycor;
1320                                 har->maxy= har->ys + har->rad/re->ycor;
1321                         
1322                                 /* the Zd value is still not really correct for pano */
1323                         
1324                                 vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
1325                                 projectfunc(vec, re->winmat, hoco);
1326                                 zn= hoco[3];
1327                                 zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
1328                                 har->zd= CLAMPIS(zn, 0, INT_MAX);
1329                         
1330                         }
1331                         
1332                 }
1333         }
1334 }
1335
1336 /* ------------------------------------------------------------------------- */
1337
1338 ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
1339 {
1340         ObjectInstanceRen *obi;
1341         float mat3[3][3];
1342
1343         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1344         obi->obr= obr;
1345         obi->ob= ob;
1346         obi->par= par;
1347         obi->index= index;
1348         obi->psysindex= psysindex;
1349         obi->lay= lay;
1350
1351         if(mat) {
1352                 Mat4CpyMat4(obi->mat, mat);
1353                 Mat3CpyMat4(mat3, mat);
1354                 Mat3Inv(obi->nmat, mat3);
1355                 Mat3Transp(obi->nmat);
1356                 obi->flag |= R_DUPLI_TRANSFORMED;
1357         }
1358
1359         BLI_addtail(&re->instancetable, obi);
1360
1361         return obi;
1362 }
1363
1364 void RE_makeRenderInstances(Render *re)
1365 {
1366         ObjectInstanceRen *obi, *oldobi;
1367         ListBase newlist;
1368         int tot;
1369
1370         /* convert list of object instances to an array for index based lookup */
1371         tot= BLI_countlist(&re->instancetable);
1372         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1373         re->totinstance= tot;
1374         newlist.first= newlist.last= NULL;
1375
1376         obi= re->objectinstance;
1377         for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1378                 *obi= *oldobi;
1379
1380                 if(obi->obr) {
1381                         obi->prev= obi->next= NULL;
1382                         BLI_addtail(&newlist, obi);
1383                         obi++;
1384                 }
1385                 else
1386                         re->totinstance--;
1387         }
1388
1389         BLI_freelistN(&re->instancetable);
1390         re->instancetable= newlist;
1391 }
1392
1393 int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
1394 {
1395         float mat[4][4], vec[4];
1396         int a, fl, flag= -1;
1397
1398         Mat4CpyMat4(mat, winmat);
1399
1400         for(a=0; a<8; a++) {
1401                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1402                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1403                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1404                 vec[3]= 1.0;
1405                 Mat4MulVec4fl(mat, vec);
1406
1407                 fl= 0;
1408                 if(bounds) {
1409                         if(vec[0] > bounds[1]*vec[3]) fl |= 1;
1410                         if(vec[0]< bounds[0]*vec[3]) fl |= 2;
1411                         if(vec[1] > bounds[3]*vec[3]) fl |= 4;
1412                         if(vec[1]< bounds[2]*vec[3]) fl |= 8;
1413                 }
1414                 else {
1415                         if(vec[0] < -vec[3]) fl |= 1;
1416                         if(vec[0] > vec[3]) fl |= 2;
1417                         if(vec[1] < -vec[3]) fl |= 4;
1418                         if(vec[1] > vec[3]) fl |= 8;
1419                 }
1420                 if(vec[2] < -vec[3]) fl |= 16;
1421                 if(vec[2] > vec[3]) fl |= 32;
1422
1423                 flag &= fl;
1424                 if(flag==0) return 0;
1425         }
1426
1427         return flag;
1428 }
1429