Bug fix: Render and 3d view conflict over ob->imat
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file blender/render/intern/source/renderdatabase.c
29  *  \ingroup render
30  */
31
32
33 /*
34  * Storage, retrieval and query of render specific data.
35  *
36  * All data from a Blender scene is converted by the renderconverter/
37  * into a special format that is used by the render module to make
38  * images out of. These functions interface to the render-specific
39  * database.  
40  *
41  * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
42  * entries each.
43  *
44  * The index of an entry is >>8 (the highest 24 * bits), to find an
45  * offset in a 256-entry block.
46  *
47  * - If the 256-entry block entry has an entry in the
48  * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in
49  * that block is allocated to this entry.
50  *
51  * - If the entry has no block allocated for it yet, memory is
52  * allocated.
53  *
54  * The pointer to the correct entry is returned. Memory is guarateed
55  * to exist (as long as the malloc does not break). Since guarded
56  * allocation is used, memory _must_ be available. Otherwise, an
57  * exit(0) would occur.
58  * 
59  */
60
61 #include <limits.h>
62 #include <math.h>
63 #include <string.h>
64
65 #include "MEM_guardedalloc.h"
66
67
68 #include "BLI_math.h"
69 #include "BLI_blenlib.h"
70 #include "BLI_utildefines.h"
71 #include "BLI_ghash.h"
72 #include "BLI_memarena.h"
73
74 #include "DNA_material_types.h" 
75 #include "DNA_mesh_types.h" 
76 #include "DNA_meshdata_types.h" 
77 #include "DNA_texture_types.h" 
78
79 #include "BKE_customdata.h"
80 #include "BKE_texture.h" 
81 #include "BKE_DerivedMesh.h"
82
83 #include "RE_render_ext.h"      /* externtex */
84
85 #include "rayobject.h"
86 #include "renderpipeline.h"
87 #include "render_types.h"
88 #include "renderdatabase.h"
89 #include "texture.h"
90 #include "strand.h"
91 #include "zbuf.h"
92
93 /* ------------------------------------------------------------------------- */
94
95 /* More dynamic allocation of options for render vertices and faces, so we dont
96    have to reserve this space inside vertices.
97    Important; vertices and faces, should have been created already (to get tables
98    checked) that's a reason why the calls demand VertRen/VlakRen * as arg, not
99    the index */
100
101 /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */
102
103 #define RE_STICKY_ELEMS         2
104 #define RE_STRESS_ELEMS         1
105 #define RE_RAD_ELEMS            4
106 #define RE_STRAND_ELEMS         1
107 #define RE_TANGENT_ELEMS        3
108 #define RE_STRESS_ELEMS         1
109 #define RE_WINSPEED_ELEMS       4
110 #define RE_MTFACE_ELEMS         1
111 #define RE_MCOL_ELEMS           4
112 #define RE_UV_ELEMS                     2
113 #define RE_SURFNOR_ELEMS        3
114 #define RE_RADFACE_ELEMS        1
115 #define RE_SIMPLIFY_ELEMS       2
116 #define RE_FACE_ELEMS           1
117 #define RE_NMAP_TANGENT_ELEMS   16
118
119 float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
120 {
121         float *sticky;
122         int nr= ver->index>>8;
123         
124         sticky= obr->vertnodes[nr].sticky;
125         if(sticky==NULL) {
126                 if(verify) 
127                         sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
128                 else
129                         return NULL;
130         }
131         return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
132 }
133
134 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
135 {
136         float *stress;
137         int nr= ver->index>>8;
138         
139         stress= obr->vertnodes[nr].stress;
140         if(stress==NULL) {
141                 if(verify) 
142                         stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
143                 else
144                         return NULL;
145         }
146         return stress + (ver->index & 255)*RE_STRESS_ELEMS;
147 }
148
149 /* this one callocs! */
150 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
151 {
152         float *rad;
153         int nr= ver->index>>8;
154         
155         rad= obr->vertnodes[nr].rad;
156         if(rad==NULL) {
157                 if(verify) 
158                         rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
159                 else
160                         return NULL;
161         }
162         return rad + (ver->index & 255)*RE_RAD_ELEMS;
163 }
164
165 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
166 {
167         float *strand;
168         int nr= ver->index>>8;
169         
170         strand= obr->vertnodes[nr].strand;
171         if(strand==NULL) {
172                 if(verify) 
173                         strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
174                 else
175                         return NULL;
176         }
177         return strand + (ver->index & 255)*RE_STRAND_ELEMS;
178 }
179
180 /* needs calloc */
181 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
182 {
183         float *tangent;
184         int nr= ver->index>>8;
185         
186         tangent= obr->vertnodes[nr].tangent;
187         if(tangent==NULL) {
188                 if(verify) 
189                         tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
190                 else
191                         return NULL;
192         }
193         return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
194 }
195
196 /* needs calloc! not all renderverts have them */
197 /* also winspeed is exception, it is stored per instance */
198 float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
199 {
200         float *winspeed;
201         int totvector;
202         
203         winspeed= obi->vectors;
204         if(winspeed==NULL) {
205                 if(verify) {
206                         totvector= obi->obr->totvert + obi->obr->totstrand;
207                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
208                 }
209                 else
210                         return NULL;
211         }
212         return winspeed + ver->index*RE_WINSPEED_ELEMS;
213 }
214
215 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
216 {
217         VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
218         float *fp1, *fp2;
219         int index= v1->index;
220         
221         *v1= *ver;
222         v1->index= index;
223         
224         fp1= RE_vertren_get_sticky(obr, ver, 0);
225         if(fp1) {
226                 fp2= RE_vertren_get_sticky(obr, v1, 1);
227                 memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
228         }
229         fp1= RE_vertren_get_stress(obr, ver, 0);
230         if(fp1) {
231                 fp2= RE_vertren_get_stress(obr, v1, 1);
232                 memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
233         }
234         fp1= RE_vertren_get_rad(obr, ver, 0);
235         if(fp1) {
236                 fp2= RE_vertren_get_rad(obr, v1, 1);
237                 memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
238         }
239         fp1= RE_vertren_get_strand(obr, ver, 0);
240         if(fp1) {
241                 fp2= RE_vertren_get_strand(obr, v1, 1);
242                 memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
243         }
244         fp1= RE_vertren_get_tangent(obr, ver, 0);
245         if(fp1) {
246                 fp2= RE_vertren_get_tangent(obr, v1, 1);
247                 memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
248         }
249         return v1;
250 }
251
252 VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
253 {
254         VertTableNode *temp;
255         VertRen *v;
256         int a;
257
258         if(nr<0) {
259                 printf("error in findOrAddVert: %d\n",nr);
260                 return NULL;
261         }
262         a= nr>>8;
263         
264         if (a>=obr->vertnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
265                 temp= obr->vertnodes;
266                 
267                 obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE) , "vertnodes");
268                 if(temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode));
269                 memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
270                 
271                 obr->vertnodeslen+=TABLEINITSIZE; 
272                 if(temp) MEM_freeN(temp);       
273         }
274         
275         v= obr->vertnodes[a].vert;
276         if(v==NULL) {
277                 int i;
278                 
279                 v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
280                 obr->vertnodes[a].vert= v;
281                 
282                 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
283                         v[a].index= i;
284                 }
285         }
286         v+= (nr & 255);
287         return v;
288 }
289
290 /* ------------------------------------------------------------------------ */
291
292 MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
293 {
294         VlakTableNode *node;
295         int nr= vlr->index>>8, vlakindex= (vlr->index&255);
296         int index= (n<<8) + vlakindex;
297
298         node= &obr->vlaknodes[nr];
299
300         if(verify) {
301                 if(n>=node->totmtface) {
302                         MTFace *mtface= node->mtface;
303                         int size= (n+1)*256;
304
305                         node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
306
307                         if(mtface) {
308                                 size= node->totmtface*256;
309                                 memcpy(node->mtface, mtface, size*sizeof(MTFace));
310                                 MEM_freeN(mtface);
311                         }
312
313                         node->totmtface= n+1;
314                 }
315         }
316         else {
317                 if(n>=node->totmtface)
318                         return NULL;
319
320                 if(name) *name= obr->mtface[n];
321         }
322
323         return node->mtface + index;
324 }
325
326 MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
327 {
328         VlakTableNode *node;
329         int nr= vlr->index>>8, vlakindex= (vlr->index&255);
330         int index= (n<<8) + vlakindex;
331
332         node= &obr->vlaknodes[nr];
333
334         if(verify) {
335                 if(n>=node->totmcol) {
336                         MCol *mcol= node->mcol;
337                         int size= (n+1)*256;
338
339                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
340
341                         if(mcol) {
342                                 size= node->totmcol*256;
343                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
344                                 MEM_freeN(mcol);
345                         }
346
347                         node->totmcol= n+1;
348                 }
349         }
350         else {
351                 if(n>=node->totmcol)
352                         return NULL;
353
354                 if(name) *name= obr->mcol[n];
355         }
356
357         return node->mcol + index*RE_MCOL_ELEMS;
358 }
359
360 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
361 {
362         float *surfnor;
363         int nr= vlak->index>>8;
364         
365         surfnor= obr->vlaknodes[nr].surfnor;
366         if(surfnor==NULL) {
367                 if(verify) 
368                         surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
369                 else
370                         return NULL;
371         }
372         return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
373 }
374
375 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
376 {
377         float *tangent;
378         int nr= vlak->index>>8;
379
380         tangent= obr->vlaknodes[nr].tangent;
381         if(tangent==NULL) {
382                 if(verify) 
383                         tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
384                 else
385                         return NULL;
386         }
387         return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
388 }
389
390 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
391 {
392         RadFace **radface;
393         int nr= vlak->index>>8;
394         
395         radface= obr->vlaknodes[nr].radface;
396         if(radface==NULL) {
397                 if(verify) 
398                         radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
399                 else
400                         return NULL;
401         }
402         return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
403 }
404
405 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
406 {
407         VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
408         MTFace *mtface, *mtface1;
409         MCol *mcol, *mcol1;
410         float *surfnor, *surfnor1, *tangent, *tangent1;
411         RadFace **radface, **radface1;
412         int i, index = vlr1->index;
413         char *name;
414
415         *vlr1= *vlr;
416         vlr1->index= index;
417
418         for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
419                 mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
420                 memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
421         }
422
423         for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
424                 mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
425                 memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
426         }
427
428         surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
429         if(surfnor) {
430                 surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
431                 VECCOPY(surfnor1, surfnor);
432         }
433
434         tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
435         if(tangent) {
436                 tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
437                 memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
438         }
439
440         radface= RE_vlakren_get_radface(obr, vlr, 0);
441         if(radface) {
442                 radface1= RE_vlakren_get_radface(obr, vlr1, 1);
443                 *radface1= *radface;
444         }
445
446         return vlr1;
447 }
448
449 void RE_vlakren_get_normal(Render *re, ObjectInstanceRen *obi, VlakRen *vlr, float *nor)
450 {
451         float (*nmat)[3]= obi->nmat;
452
453         if(obi->flag & R_TRANSFORMED) {
454                 VECCOPY(nor, vlr->n);
455                 
456                 mul_m3_v3(nmat, nor);
457                 normalize_v3(nor);
458         }
459         else
460                 VECCOPY(nor, vlr->n);
461 }
462
463 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
464 {
465         /* CustomData layer names are stored per object here, because the
466            DerivedMesh which stores the layers is freed */
467         
468         CustomDataLayer *layer;
469         int numtf = 0, numcol = 0, i, mtfn, mcn;
470
471         if (CustomData_has_layer(data, CD_MTFACE)) {
472                 numtf= CustomData_number_of_layers(data, CD_MTFACE);
473                 obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
474         }
475
476         if (CustomData_has_layer(data, CD_MCOL)) {
477                 numcol= CustomData_number_of_layers(data, CD_MCOL);
478                 obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
479         }
480
481         for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
482                 layer= &data->layers[i];
483
484                 if (layer->type == CD_MTFACE) {
485                         strcpy(obr->mtface[mtfn++], layer->name);
486                         obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
487                         obr->bakemtface= layer->active;
488                 }
489                 else if (layer->type == CD_MCOL) {
490                         strcpy(obr->mcol[mcn++], layer->name);
491                         obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
492                 }
493         }
494 }
495
496 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
497 {
498         VlakTableNode *temp;
499         VlakRen *v;
500         int a;
501
502         if(nr<0) {
503                 printf("error in findOrAddVlak: %d\n",nr);
504                 return obr->vlaknodes[0].vlak;
505         }
506         a= nr>>8;
507         
508         if (a>=obr->vlaknodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
509                 temp= obr->vlaknodes;
510                 
511                 obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
512                 if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
513                 memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
514
515                 obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
516                 if(temp) MEM_freeN(temp);       
517         }
518
519         v= obr->vlaknodes[a].vlak;
520         
521         if(v==NULL) {
522                 int i;
523
524                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
525                 obr->vlaknodes[a].vlak= v;
526
527                 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
528                         v[a].index= i;
529         }
530         v+= (nr & 255);
531         return v;
532 }
533
534 /* ------------------------------------------------------------------------ */
535
536 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
537 {
538         float *surfnor;
539         int nr= strand->index>>8;
540         
541         surfnor= obr->strandnodes[nr].surfnor;
542         if(surfnor==NULL) {
543                 if(verify) 
544                         surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
545                 else
546                         return NULL;
547         }
548         return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
549 }
550
551 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
552 {
553         StrandTableNode *node;
554         int nr= strand->index>>8, strandindex= (strand->index&255);
555         int index= (n<<8) + strandindex;
556
557         node= &obr->strandnodes[nr];
558
559         if(verify) {
560                 if(n>=node->totuv) {
561                         float *uv= node->uv;
562                         int size= (n+1)*256;
563
564                         node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
565
566                         if(uv) {
567                                 size= node->totuv*256;
568                                 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
569                                 MEM_freeN(uv);
570                         }
571
572                         node->totuv= n+1;
573                 }
574         }
575         else {
576                 if(n>=node->totuv)
577                         return NULL;
578
579                 if(name) *name= obr->mtface[n];
580         }
581
582         return node->uv + index*RE_UV_ELEMS;
583 }
584
585 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
586 {
587         StrandTableNode *node;
588         int nr= strand->index>>8, strandindex= (strand->index&255);
589         int index= (n<<8) + strandindex;
590
591         node= &obr->strandnodes[nr];
592
593         if(verify) {
594                 if(n>=node->totmcol) {
595                         MCol *mcol= node->mcol;
596                         int size= (n+1)*256;
597
598                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
599
600                         if(mcol) {
601                                 size= node->totmcol*256;
602                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
603                                 MEM_freeN(mcol);
604                         }
605
606                         node->totmcol= n+1;
607                 }
608         }
609         else {
610                 if(n>=node->totmcol)
611                         return NULL;
612
613                 if(name) *name= obr->mcol[n];
614         }
615
616         return node->mcol + index*RE_MCOL_ELEMS;
617 }
618
619 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
620 {
621         float *simplify;
622         int nr= strand->index>>8;
623         
624         simplify= obr->strandnodes[nr].simplify;
625         if(simplify==NULL) {
626                 if(verify) 
627                         simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
628                 else
629                         return NULL;
630         }
631         return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
632 }
633
634 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
635 {
636         int *face;
637         int nr= strand->index>>8;
638         
639         face= obr->strandnodes[nr].face;
640         if(face==NULL) {
641                 if(verify) 
642                         face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
643                 else
644                         return NULL;
645         }
646         return face + (strand->index & 255)*RE_FACE_ELEMS;
647 }
648
649 /* winspeed is exception, it is stored per instance */
650 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
651 {
652         float *winspeed;
653         int totvector;
654         
655         winspeed= obi->vectors;
656         if(winspeed==NULL) {
657                 if(verify) {
658                         totvector= obi->obr->totvert + obi->obr->totstrand;
659                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
660                 }
661                 else
662                         return NULL;
663         }
664         return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
665 }
666
667 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
668 {
669         StrandTableNode *temp;
670         StrandRen *v;
671         int a;
672
673         if(nr<0) {
674                 printf("error in findOrAddStrand: %d\n",nr);
675                 return obr->strandnodes[0].strand;
676         }
677         a= nr>>8;
678         
679         if (a>=obr->strandnodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
680                 temp= obr->strandnodes;
681                 
682                 obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes");
683                 if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
684                 memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
685
686                 obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
687                 if(temp) MEM_freeN(temp);       
688         }
689
690         v= obr->strandnodes[a].strand;
691         
692         if(v==NULL) {
693                 int i;
694
695                 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
696                 obr->strandnodes[a].strand= v;
697
698                 for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
699                         v[a].index= i;
700         }
701         v+= (nr & 255);
702         return v;
703 }
704
705 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
706 {
707         StrandBuffer *strandbuf;
708
709         strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
710         strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
711         strandbuf->totvert= totvert;
712         strandbuf->obr= obr;
713
714         obr->strandbuf= strandbuf;
715
716         return strandbuf;
717 }
718
719 /* ------------------------------------------------------------------------ */
720
721 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
722 {
723         ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
724         
725         BLI_addtail(&re->objecttable, obr);
726         obr->ob= ob;
727         obr->par= par;
728         obr->index= index;
729         obr->psysindex= psysindex;
730         obr->lay= lay;
731
732         return obr;
733 }
734
735 void free_renderdata_vertnodes(VertTableNode *vertnodes)
736 {
737         int a;
738         
739         if(vertnodes==NULL) return;
740         
741         for(a=0; vertnodes[a].vert; a++) {
742                 MEM_freeN(vertnodes[a].vert);
743                 
744                 if(vertnodes[a].rad)
745                         MEM_freeN(vertnodes[a].rad);
746                 if(vertnodes[a].sticky)
747                         MEM_freeN(vertnodes[a].sticky);
748                 if(vertnodes[a].strand)
749                         MEM_freeN(vertnodes[a].strand);
750                 if(vertnodes[a].tangent)
751                         MEM_freeN(vertnodes[a].tangent);
752                 if(vertnodes[a].stress)
753                         MEM_freeN(vertnodes[a].stress);
754                 if(vertnodes[a].winspeed)
755                         MEM_freeN(vertnodes[a].winspeed);
756         }
757         
758         MEM_freeN(vertnodes);
759 }
760
761 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
762 {
763         int a;
764         
765         if(vlaknodes==NULL) return;
766         
767         for(a=0; vlaknodes[a].vlak; a++) {
768                 MEM_freeN(vlaknodes[a].vlak);
769                 
770                 if(vlaknodes[a].mtface)
771                         MEM_freeN(vlaknodes[a].mtface);
772                 if(vlaknodes[a].mcol)
773                         MEM_freeN(vlaknodes[a].mcol);
774                 if(vlaknodes[a].surfnor)
775                         MEM_freeN(vlaknodes[a].surfnor);
776                 if(vlaknodes[a].tangent)
777                         MEM_freeN(vlaknodes[a].tangent);
778                 if(vlaknodes[a].radface)
779                         MEM_freeN(vlaknodes[a].radface);
780         }
781         
782         MEM_freeN(vlaknodes);
783 }
784
785 void free_renderdata_strandnodes(StrandTableNode *strandnodes)
786 {
787         int a;
788         
789         if(strandnodes==NULL) return;
790         
791         for(a=0; strandnodes[a].strand; a++) {
792                 MEM_freeN(strandnodes[a].strand);
793                 
794                 if(strandnodes[a].uv)
795                         MEM_freeN(strandnodes[a].uv);
796                 if(strandnodes[a].mcol)
797                         MEM_freeN(strandnodes[a].mcol);
798                 if(strandnodes[a].winspeed)
799                         MEM_freeN(strandnodes[a].winspeed);
800                 if(strandnodes[a].surfnor)
801                         MEM_freeN(strandnodes[a].surfnor);
802                 if(strandnodes[a].simplify)
803                         MEM_freeN(strandnodes[a].simplify);
804                 if(strandnodes[a].face)
805                         MEM_freeN(strandnodes[a].face);
806         }
807         
808         MEM_freeN(strandnodes);
809 }
810
811 void free_renderdata_tables(Render *re)
812 {
813         ObjectInstanceRen *obi;
814         ObjectRen *obr;
815         StrandBuffer *strandbuf;
816         int a=0;
817         
818         for(obr=re->objecttable.first; obr; obr=obr->next) {
819                 if(obr->vertnodes) {
820                         free_renderdata_vertnodes(obr->vertnodes);
821                         obr->vertnodes= NULL;
822                         obr->vertnodeslen= 0;
823                 }
824
825                 if(obr->vlaknodes) {
826                         free_renderdata_vlaknodes(obr->vlaknodes);
827                         obr->vlaknodes= NULL;
828                         obr->vlaknodeslen= 0;
829                         obr->totvlak= 0;
830                 }
831
832                 if(obr->bloha) {
833                         for(a=0; obr->bloha[a]; a++)
834                                 MEM_freeN(obr->bloha[a]);
835
836                         MEM_freeN(obr->bloha);
837                         obr->bloha= NULL;
838                         obr->blohalen= 0;
839                 }
840
841                 if(obr->strandnodes) {
842                         free_renderdata_strandnodes(obr->strandnodes);
843                         obr->strandnodes= NULL;
844                         obr->strandnodeslen= 0;
845                 }
846
847                 strandbuf= obr->strandbuf;
848                 if(strandbuf) {
849                         if(strandbuf->vert) MEM_freeN(strandbuf->vert);
850                         if(strandbuf->bound) MEM_freeN(strandbuf->bound);
851                         MEM_freeN(strandbuf);
852                 }
853
854                 if(obr->mtface)
855                         MEM_freeN(obr->mtface);
856                 if(obr->mcol)
857                         MEM_freeN(obr->mcol);
858                         
859                 if(obr->rayfaces)
860                 {
861                         MEM_freeN(obr->rayfaces);
862                         obr->rayfaces = NULL;
863                 }
864                 if(obr->rayprimitives)
865                 {
866                         MEM_freeN(obr->rayprimitives);
867                         obr->rayprimitives = NULL;
868                 }
869                 if(obr->raytree)
870                 {
871                         RE_rayobject_free(obr->raytree);
872                         obr->raytree = NULL;
873                 }
874         }
875
876         if(re->objectinstance) {
877                 for(obi=re->instancetable.first; obi; obi=obi->next)
878                 {
879                         if(obi->vectors)
880                                 MEM_freeN(obi->vectors);
881
882                         if(obi->raytree)
883                                 RE_rayobject_free(obi->raytree);
884                 }
885
886                 MEM_freeN(re->objectinstance);
887                 re->objectinstance= NULL;
888                 re->totinstance= 0;
889                 re->instancetable.first= re->instancetable.last= NULL;
890         }
891
892         if(re->sortedhalos) {
893                 MEM_freeN(re->sortedhalos);
894                 re->sortedhalos= NULL;
895         }
896
897         BLI_freelistN(&re->customdata_names);
898         BLI_freelistN(&re->objecttable);
899         BLI_freelistN(&re->instancetable);
900 }
901
902 /* ------------------------------------------------------------------------ */
903
904 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
905 {
906         HaloRen *h, **temp;
907         int a;
908
909         if(nr<0) {
910                 printf("error in findOrAddHalo: %d\n",nr);
911                 return NULL;
912         }
913         a= nr>>8;
914         
915         if (a>=obr->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
916                 //printf("Allocating %i more halo groups.  %i total.\n", 
917                 //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
918                 temp=obr->bloha;
919                 
920                 obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
921                 if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
922                 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
923                 obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
924                 if(temp) MEM_freeN(temp);       
925         }
926         
927         h= obr->bloha[a];
928         if(h==NULL) {
929                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
930                 obr->bloha[a]= h;
931         }
932         h+= (nr & 255);
933         return h;
934 }
935
936 /* ------------------------------------------------------------------------- */
937
938 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   float *vec1, 
939                                   float *orco,   float hasize,   float vectsize, int seed)
940 {
941         HaloRen *har;
942         MTex *mtex;
943         float tin, tr, tg, tb, ta;
944         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
945
946         if(hasize==0.0) return NULL;
947
948         projectverto(vec, re->winmat, hoco);
949         if(hoco[3]==0.0) return NULL;
950         if(vec1) {
951                 projectverto(vec1, re->winmat, hoco1);
952                 if(hoco1[3]==0.0) return NULL;
953         }
954
955         har= RE_findOrAddHalo(obr, obr->tothalo++);
956         VECCOPY(har->co, vec);
957         har->hasize= hasize;
958
959         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
960         /* we do it here for sorting of halos */
961         zn= hoco[3];
962         har->xs= 0.5*re->winx*(hoco[0]/zn);
963         har->ys= 0.5*re->winy*(hoco[1]/zn);
964         har->zs= 0x7FFFFF*(hoco[2]/zn);
965         
966         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
967         
968         /* halovect */
969         if(vec1) {
970
971                 har->type |= HA_VECT;
972
973                 xn=  har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
974                 yn=  har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
975                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
976                 else zn= atan2(yn, xn);
977
978                 har->sin= sin(zn);
979                 har->cos= cos(zn);
980                 zn= len_v3v3(vec1, vec);
981
982                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
983                 
984                 sub_v3_v3v3(har->no, vec, vec1);
985                 normalize_v3(har->no);
986         }
987
988         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
989
990         har->alfa= ma->alpha;
991         har->r= ma->r;
992         har->g= ma->g;
993         har->b= ma->b;
994         har->add= (255.0*ma->add);
995         har->mat= ma;
996         har->hard= ma->har;
997         har->seed= seed % 256;
998
999         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1000         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1001         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1002         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1003
1004
1005         if(ma->mtex[0]) {
1006
1007                 if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
1008                 else if(har->mat->septex & (1<<0));     /* only 1 level textures */
1009                 else {
1010
1011                         mtex= ma->mtex[0];
1012                         VECCOPY(texvec, vec);
1013
1014                         if(mtex->texco & TEXCO_NORM) {
1015                                 ;
1016                         }
1017                         else if(mtex->texco & TEXCO_OBJECT) {
1018                                 /* texvec[0]+= imatbase->ivec[0]; */
1019                                 /* texvec[1]+= imatbase->ivec[1]; */
1020                                 /* texvec[2]+= imatbase->ivec[2]; */
1021                                 /* mul_m3_v3(imatbase->imat, texvec); */
1022                         }
1023                         else {
1024                                 if(orco) {
1025                                         VECCOPY(texvec, orco);
1026                                 }
1027                         }
1028
1029                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1030
1031                         yn= tin*mtex->colfac;
1032                         zn= tin*mtex->alphafac;
1033
1034                         if(mtex->mapto & MAP_COL) {
1035                                 zn= 1.0-yn;
1036                                 har->r= (yn*tr+ zn*ma->r);
1037                                 har->g= (yn*tg+ zn*ma->g);
1038                                 har->b= (yn*tb+ zn*ma->b);
1039                         }
1040                         if(mtex->texco & TEXCO_UV) {
1041                                 har->alfa= tin;
1042                         }
1043                         if(mtex->mapto & MAP_ALPHA)
1044                                 har->alfa= tin;
1045                 }
1046         }
1047
1048         return har;
1049 }
1050
1051 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
1052                                   float *orco, float *uvco, float hasize, float vectsize, int seed, float *pa_co)
1053 {
1054         HaloRen *har;
1055         MTex *mtex;
1056         float tin, tr, tg, tb, ta;
1057         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
1058         int i, hasrgb;
1059
1060         if(hasize==0.0) return NULL;
1061
1062         projectverto(vec, re->winmat, hoco);
1063         if(hoco[3]==0.0) return NULL;
1064         if(vec1) {
1065                 projectverto(vec1, re->winmat, hoco1);
1066                 if(hoco1[3]==0.0) return NULL;
1067         }
1068
1069         har= RE_findOrAddHalo(obr, obr->tothalo++);
1070         VECCOPY(har->co, vec);
1071         har->hasize= hasize;
1072
1073         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1074         /* we do it here for sorting of halos */
1075         zn= hoco[3];
1076         har->xs= 0.5*re->winx*(hoco[0]/zn);
1077         har->ys= 0.5*re->winy*(hoco[1]/zn);
1078         har->zs= 0x7FFFFF*(hoco[2]/zn);
1079         
1080         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1081         
1082         /* halovect */
1083         if(vec1) {
1084
1085                 har->type |= HA_VECT;
1086
1087                 xn=  har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
1088                 yn=  har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
1089                 if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
1090                 else zn= atan2(yn, xn);
1091
1092                 har->sin= sin(zn);
1093                 har->cos= cos(zn);
1094                 zn= len_v3v3(vec1, vec)*0.5;
1095
1096                 har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
1097                 
1098                 sub_v3_v3v3(har->no, vec, vec1);
1099                 normalize_v3(har->no);
1100         }
1101
1102         if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1103
1104         har->alfa= ma->alpha;
1105         har->r= ma->r;
1106         har->g= ma->g;
1107         har->b= ma->b;
1108         har->add= (255.0*ma->add);
1109         har->mat= ma;
1110         har->hard= ma->har;
1111         har->seed= seed % 256;
1112
1113         if(ma->mode & MA_STAR) har->starpoints= ma->starc;
1114         if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1115         if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1116         if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1117
1118         if((ma->mode & MA_HALOTEX) && ma->mtex[0]){
1119                 har->tex= 1;
1120                 i=1;
1121         }
1122         
1123         for(i=0; i<MAX_MTEX; i++)
1124                 if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
1125                         mtex= ma->mtex[i];
1126                         VECCOPY(texvec, vec);
1127
1128                         if(mtex->texco & TEXCO_NORM) {
1129                                 ;
1130                         }
1131                         else if(mtex->texco & TEXCO_OBJECT) {
1132                                 if(mtex->object)
1133                                         mul_m4_v3(mtex->object->imat_ren,texvec);
1134                         }
1135                         else if(mtex->texco & TEXCO_GLOB){
1136                                 VECCOPY(texvec,vec);
1137                         }
1138                         else if(mtex->texco & TEXCO_UV && uvco){
1139                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
1140                                 if(uv_index<0)
1141                                         uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
1142
1143                                 uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
1144
1145                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1146                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1147                                 texvec[2]=0.0f;
1148                         }
1149                         else if(mtex->texco & TEXCO_PARTICLE) {
1150                                 /* particle coordinates in range [0,1] */
1151                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1152                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1153                                 texvec[2] = pa_co[2];
1154                         }
1155                         else if(orco) {
1156                                 VECCOPY(texvec, orco);
1157                         }
1158
1159                         hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
1160
1161                         //yn= tin*mtex->colfac;
1162                         //zn= tin*mtex->alphafac;
1163                         if(mtex->mapto & MAP_COL) {
1164                                 tex[0]=tr;
1165                                 tex[1]=tg;
1166                                 tex[2]=tb;
1167                                 out[0]=har->r;
1168                                 out[1]=har->g;
1169                                 out[2]=har->b;
1170
1171                                 texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
1172                         //      zn= 1.0-yn;
1173                                 //har->r= (yn*tr+ zn*ma->r);
1174                                 //har->g= (yn*tg+ zn*ma->g);
1175                                 //har->b= (yn*tb+ zn*ma->b);
1176                                 har->r= in[0];
1177                                 har->g= in[1];
1178                                 har->b= in[2];
1179                         }
1180
1181                         /* alpha returned, so let's use it instead of intensity */
1182                         if(hasrgb)
1183                                 tin = ta;
1184
1185                         if(mtex->mapto & MAP_ALPHA)
1186                                 har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->alphafac,mtex->blendtype);
1187                         if(mtex->mapto & MAP_HAR)
1188                                 har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->hardfac,mtex->blendtype);
1189                         if(mtex->mapto & MAP_RAYMIRR)
1190                                 har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->raymirrfac,mtex->blendtype);
1191                         if(mtex->mapto & MAP_TRANSLU) {
1192                                 float add = texture_value_blend(mtex->def_var,(float)har->add/255.0,tin,mtex->translfac,mtex->blendtype);
1193                                 CLAMP(add, 0.f, 1.f);
1194                                 har->add = 255.0*add;
1195                         }
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                 copy_m4_m4(obi->mat, mat);
1344                 copy_m3_m4(mat3, mat);
1345                 invert_m3_m3(obi->nmat, mat3);
1346                 transpose_m3(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         copy_m4_m4(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                 mul_m4_v4(mat, vec);
1397
1398                 fl= 0;
1399                 if(bounds) {
1400                         if(vec[0] < bounds[0]*vec[3]) fl |= 1;
1401                         else if(vec[0] > bounds[1]*vec[3]) fl |= 2;
1402                         
1403                         if(vec[1] > bounds[3]*vec[3]) fl |= 4;
1404                         else if(vec[1]< bounds[2]*vec[3]) fl |= 8;
1405                 }
1406                 else {
1407                         if(vec[0] < -vec[3]) fl |= 1;
1408                         else if(vec[0] > vec[3]) fl |= 2;
1409                         
1410                         if(vec[1] > vec[3]) fl |= 4;
1411                         else if(vec[1] < -vec[3]) fl |= 8;
1412                 }
1413                 if(vec[2] < -vec[3]) fl |= 16;
1414                 else if(vec[2] > vec[3]) fl |= 32;
1415
1416                 flag &= fl;
1417                 if(flag==0) return 0;
1418         }
1419
1420         return flag;
1421 }
1422