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