e8db096c9a557c01ec577eae4f0028a1d0d46043
[blender.git] / source / blender / render / intern / source / renderdatabase.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): 2004-2006, Blender Foundation, full recode
22  *
23  * ***** END GPL/BL DUAL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/renderdatabase.c
27  *  \ingroup render
28  */
29
30
31 /*
32  * Storage, retrieval and query of render specific data.
33  *
34  * All data from a Blender scene is converted by the renderconverter/
35  * into a special format that is used by the render module to make
36  * images out of. These functions interface to the render-specific
37  * database.  
38  *
39  * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data
40  * entries each.
41  *
42  * The index of an entry is >>8 (the highest 24 * bits), to find an
43  * offset in a 256-entry block.
44  *
45  * - If the 256-entry block entry has an entry in the
46  * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in
47  * that block is allocated to this entry.
48  *
49  * - If the entry has no block allocated for it yet, memory is
50  * allocated.
51  *
52  * The pointer to the correct entry is returned. Memory is guaranteed
53  * to exist (as long as the malloc does not break). Since guarded
54  * allocation is used, memory _must_ be available. Otherwise, an
55  * exit(0) would occur.
56  * 
57  */
58
59 #include <limits.h>
60 #include <math.h>
61 #include <string.h>
62
63 #include "MEM_guardedalloc.h"
64
65
66 #include "BLI_math.h"
67 #include "BLI_blenlib.h"
68 #include "BLI_utildefines.h"
69
70 #include "DNA_material_types.h" 
71 #include "DNA_meshdata_types.h" 
72 #include "DNA_texture_types.h"
73 #include "DNA_particle_types.h"
74
75 #include "BKE_customdata.h"
76 #include "BKE_DerivedMesh.h"
77
78 #include "RE_render_ext.h"      /* externtex */
79
80 #include "rayintersection.h"
81 #include "rayobject.h"
82 #include "render_types.h"
83 #include "renderdatabase.h"
84 #include "zbuf.h"
85
86 /* ------------------------------------------------------------------------- */
87
88 /* More dynamic allocation of options for render vertices and faces, so we don't
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 #define RE_STRESS_ELEMS         1
96 #define RE_RAD_ELEMS            4
97 #define RE_STRAND_ELEMS         1
98 #define RE_TANGENT_ELEMS        3
99 #define RE_WINSPEED_ELEMS       4
100 #define RE_MTFACE_ELEMS         1
101 #define RE_MCOL_ELEMS           4
102 #define RE_UV_ELEMS                     2
103 #define RE_VLAK_ORIGINDEX_ELEMS 1
104 #define RE_VERT_ORIGINDEX_ELEMS 1
105 #define RE_SURFNOR_ELEMS        3
106 #define RE_RADFACE_ELEMS        1
107 #define RE_SIMPLIFY_ELEMS       2
108 #define RE_FACE_ELEMS           1
109 #define RE_NMAP_TANGENT_ELEMS   16
110
111 float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
112 {
113         float *stress;
114         int nr= ver->index>>8;
115         
116         stress= obr->vertnodes[nr].stress;
117         if (stress==NULL) {
118                 if (verify) 
119                         stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
120                 else
121                         return NULL;
122         }
123         return stress + (ver->index & 255)*RE_STRESS_ELEMS;
124 }
125
126 /* this one callocs! */
127 float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
128 {
129         float *rad;
130         int nr= ver->index>>8;
131         
132         rad= obr->vertnodes[nr].rad;
133         if (rad==NULL) {
134                 if (verify) 
135                         rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
136                 else
137                         return NULL;
138         }
139         return rad + (ver->index & 255)*RE_RAD_ELEMS;
140 }
141
142 float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
143 {
144         float *strand;
145         int nr= ver->index>>8;
146         
147         strand= obr->vertnodes[nr].strand;
148         if (strand==NULL) {
149                 if (verify) 
150                         strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
151                 else
152                         return NULL;
153         }
154         return strand + (ver->index & 255)*RE_STRAND_ELEMS;
155 }
156
157 /* needs calloc */
158 float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
159 {
160         float *tangent;
161         int nr= ver->index>>8;
162         
163         tangent= obr->vertnodes[nr].tangent;
164         if (tangent==NULL) {
165                 if (verify) 
166                         tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
167                 else
168                         return NULL;
169         }
170         return tangent + (ver->index & 255)*RE_TANGENT_ELEMS;
171 }
172
173 /* needs calloc! not all renderverts have them */
174 /* also winspeed is exception, it is stored per instance */
175 float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
176 {
177         float *winspeed;
178         int totvector;
179         
180         winspeed= obi->vectors;
181         if (winspeed==NULL) {
182                 if (verify) {
183                         totvector= obi->obr->totvert + obi->obr->totstrand;
184                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
185                 }
186                 else
187                         return NULL;
188         }
189         return winspeed + ver->index*RE_WINSPEED_ELEMS;
190 }
191
192 int *RE_vertren_get_origindex(ObjectRen *obr, VertRen *ver, int verify)
193 {
194         int *origindex;
195         int nr= ver->index>>8;
196
197         origindex= obr->vertnodes[nr].origindex;
198         if (origindex==NULL) {
199                 if (verify)
200                         origindex= obr->vertnodes[nr].origindex= MEM_mallocN(256*RE_VERT_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
201                 else
202                         return NULL;
203         }
204         return origindex + (ver->index & 255)*RE_VERT_ORIGINDEX_ELEMS;
205 }
206
207 VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
208 {
209         VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
210         float *fp1, *fp2;
211         int *int1, *int2;
212         int index= v1->index;
213         
214         *v1= *ver;
215         v1->index= index;
216
217         fp1= RE_vertren_get_stress(obr, ver, 0);
218         if (fp1) {
219                 fp2= RE_vertren_get_stress(obr, v1, 1);
220                 memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
221         }
222         fp1= RE_vertren_get_rad(obr, ver, 0);
223         if (fp1) {
224                 fp2= RE_vertren_get_rad(obr, v1, 1);
225                 memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
226         }
227         fp1= RE_vertren_get_strand(obr, ver, 0);
228         if (fp1) {
229                 fp2= RE_vertren_get_strand(obr, v1, 1);
230                 memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
231         }
232         fp1= RE_vertren_get_tangent(obr, ver, 0);
233         if (fp1) {
234                 fp2= RE_vertren_get_tangent(obr, v1, 1);
235                 memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
236         }
237         int1= RE_vertren_get_origindex(obr, ver, 0);
238         if (int1) {
239                 int2= RE_vertren_get_origindex(obr, v1, 1);
240                 memcpy(int2, int1, RE_VERT_ORIGINDEX_ELEMS*sizeof(int));
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= (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 int *RE_vlakren_get_origindex(ObjectRen *obr, VlakRen *vlak, int verify)
354 {
355         int *origindex;
356         int nr= vlak->index>>8;
357
358         origindex= obr->vlaknodes[nr].origindex;
359         if (origindex==NULL) {
360                 if (verify)
361                         origindex= obr->vlaknodes[nr].origindex= MEM_callocN(256*RE_VLAK_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
362                 else
363                         return NULL;
364         }
365         return origindex + (vlak->index & 255)*RE_VLAK_ORIGINDEX_ELEMS;
366 }
367
368 float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
369 {
370         float *surfnor;
371         int nr= vlak->index>>8;
372         
373         surfnor= obr->vlaknodes[nr].surfnor;
374         if (surfnor==NULL) {
375                 if (verify) 
376                         surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
377                 else
378                         return NULL;
379         }
380         return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
381 }
382
383 float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
384 {
385         float *tangent;
386         int nr= vlak->index>>8;
387
388         tangent= obr->vlaknodes[nr].tangent;
389         if (tangent==NULL) {
390                 if (verify) 
391                         tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
392                 else
393                         return NULL;
394         }
395         return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
396 }
397
398 RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
399 {
400         RadFace **radface;
401         int nr= vlak->index>>8;
402         
403         radface= obr->vlaknodes[nr].radface;
404         if (radface==NULL) {
405                 if (verify) 
406                         radface = obr->vlaknodes[nr].radface= MEM_callocN(256 * RE_RADFACE_ELEMS * sizeof(void *), "radface table");
407                 else
408                         return NULL;
409         }
410         return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
411 }
412
413 VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
414 {
415         VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
416         MTFace *mtface, *mtface1;
417         MCol *mcol, *mcol1;
418         float *surfnor, *surfnor1, *tangent, *tangent1;
419         int *origindex, *origindex1;
420         RadFace **radface, **radface1;
421         int i, index = vlr1->index;
422         char *name;
423
424         *vlr1= *vlr;
425         vlr1->index= index;
426
427         for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
428                 mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
429                 memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
430         }
431
432         for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
433                 mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
434                 memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
435         }
436
437         origindex= RE_vlakren_get_origindex(obr, vlr, 0);
438         if (origindex) {
439                 origindex1= RE_vlakren_get_origindex(obr, vlr1, 1);
440                 /* Just an int, but memcpy for consistency. */
441                 memcpy(origindex1, origindex, sizeof(int)*RE_VLAK_ORIGINDEX_ELEMS);
442         }
443
444         surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
445         if (surfnor) {
446                 surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
447                 copy_v3_v3(surfnor1, surfnor);
448         }
449
450         tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
451         if (tangent) {
452                 tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
453                 memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
454         }
455
456         radface= RE_vlakren_get_radface(obr, vlr, 0);
457         if (radface) {
458                 radface1= RE_vlakren_get_radface(obr, vlr1, 1);
459                 *radface1= *radface;
460         }
461
462         return vlr1;
463 }
464
465 void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float r_nor[3])
466 {
467         float (*nmat)[3]= obi->nmat;
468
469         if (obi->flag & R_TRANSFORMED) {
470                 mul_v3_m3v3(r_nor, nmat, vlr->n);
471                 normalize_v3(r_nor);
472         }
473         else {
474                 copy_v3_v3(r_nor, vlr->n);
475         }
476 }
477
478 void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
479 {
480         /* CustomData layer names are stored per object here, because the
481          * DerivedMesh which stores the layers is freed */
482         
483         CustomDataLayer *layer;
484         int numtf = 0, numcol = 0, i, mtfn, mcn;
485
486         if (CustomData_has_layer(data, CD_MTFACE)) {
487                 numtf= CustomData_number_of_layers(data, CD_MTFACE);
488                 obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
489         }
490
491         if (CustomData_has_layer(data, CD_MCOL)) {
492                 numcol= CustomData_number_of_layers(data, CD_MCOL);
493                 obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
494         }
495
496         for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
497                 layer= &data->layers[i];
498
499                 if (layer->type == CD_MTFACE) {
500                         BLI_strncpy(obr->mtface[mtfn++], layer->name, sizeof(layer->name));
501                         obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
502                         obr->bakemtface= layer->active;
503                 }
504                 else if (layer->type == CD_MCOL) {
505                         BLI_strncpy(obr->mcol[mcn++], layer->name, sizeof(layer->name));
506                         obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
507                 }
508         }
509 }
510
511 VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
512 {
513         VlakTableNode *temp;
514         VlakRen *v;
515         int a;
516
517         if (nr<0) {
518                 printf("error in findOrAddVlak: %d\n", nr);
519                 return obr->vlaknodes[0].vlak;
520         }
521         a= nr>>8;
522         
523         if (a>=obr->vlaknodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
524                 temp= obr->vlaknodes;
525                 
526                 obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE), "vlaknodes");
527                 if (temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
528                 memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
529
530                 obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
531                 if (temp) MEM_freeN(temp);
532         }
533
534         v= obr->vlaknodes[a].vlak;
535         
536         if (v==NULL) {
537                 int i;
538
539                 v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen), "findOrAddVlak");
540                 obr->vlaknodes[a].vlak= v;
541
542                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
543                         v[a].index= i;
544         }
545         v+= (nr & 255);
546         return v;
547 }
548
549 /* ------------------------------------------------------------------------ */
550
551 float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
552 {
553         float *surfnor;
554         int nr= strand->index>>8;
555         
556         surfnor= obr->strandnodes[nr].surfnor;
557         if (surfnor==NULL) {
558                 if (verify) 
559                         surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
560                 else
561                         return NULL;
562         }
563         return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
564 }
565
566 float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
567 {
568         StrandTableNode *node;
569         int nr= strand->index>>8, strandindex= (strand->index&255);
570         int index= (n<<8) + strandindex;
571
572         node= &obr->strandnodes[nr];
573
574         if (verify) {
575                 if (n>=node->totuv) {
576                         float *uv= node->uv;
577                         int size= (n+1)*256;
578
579                         node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
580
581                         if (uv) {
582                                 size= node->totuv*256;
583                                 memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
584                                 MEM_freeN(uv);
585                         }
586
587                         node->totuv= n+1;
588                 }
589         }
590         else {
591                 if (n>=node->totuv)
592                         return NULL;
593
594                 if (name) *name= obr->mtface[n];
595         }
596
597         return node->uv + index*RE_UV_ELEMS;
598 }
599
600 MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
601 {
602         StrandTableNode *node;
603         int nr= strand->index>>8, strandindex= (strand->index&255);
604         int index= (n<<8) + strandindex;
605
606         node= &obr->strandnodes[nr];
607
608         if (verify) {
609                 if (n>=node->totmcol) {
610                         MCol *mcol= node->mcol;
611                         int size= (n+1)*256;
612
613                         node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
614
615                         if (mcol) {
616                                 size= node->totmcol*256;
617                                 memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
618                                 MEM_freeN(mcol);
619                         }
620
621                         node->totmcol= n+1;
622                 }
623         }
624         else {
625                 if (n>=node->totmcol)
626                         return NULL;
627
628                 if (name) *name= obr->mcol[n];
629         }
630
631         return node->mcol + index*RE_MCOL_ELEMS;
632 }
633
634 float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
635 {
636         float *simplify;
637         int nr= strand->index>>8;
638         
639         simplify= obr->strandnodes[nr].simplify;
640         if (simplify==NULL) {
641                 if (verify) 
642                         simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
643                 else
644                         return NULL;
645         }
646         return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
647 }
648
649 int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
650 {
651         int *face;
652         int nr= strand->index>>8;
653         
654         face= obr->strandnodes[nr].face;
655         if (face==NULL) {
656                 if (verify) 
657                         face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
658                 else
659                         return NULL;
660         }
661         return face + (strand->index & 255)*RE_FACE_ELEMS;
662 }
663
664 /* winspeed is exception, it is stored per instance */
665 float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
666 {
667         float *winspeed;
668         int totvector;
669         
670         winspeed= obi->vectors;
671         if (winspeed==NULL) {
672                 if (verify) {
673                         totvector= obi->obr->totvert + obi->obr->totstrand;
674                         winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
675                 }
676                 else
677                         return NULL;
678         }
679         return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
680 }
681
682 StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
683 {
684         StrandTableNode *temp;
685         StrandRen *v;
686         int a;
687
688         if (nr<0) {
689                 printf("error in findOrAddStrand: %d\n", nr);
690                 return obr->strandnodes[0].strand;
691         }
692         a= nr>>8;
693         
694         if (a>=obr->strandnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
695                 temp= obr->strandnodes;
696                 
697                 obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE), "strandnodes");
698                 if (temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
699                 memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
700
701                 obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
702                 if (temp) MEM_freeN(temp);
703         }
704
705         v= obr->strandnodes[a].strand;
706         
707         if (v==NULL) {
708                 int i;
709
710                 v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen), "findOrAddStrand");
711                 obr->strandnodes[a].strand= v;
712
713                 for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
714                         v[a].index= i;
715         }
716         v+= (nr & 255);
717         return v;
718 }
719
720 StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
721 {
722         StrandBuffer *strandbuf;
723
724         strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
725         strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
726         strandbuf->totvert= totvert;
727         strandbuf->obr= obr;
728
729         obr->strandbuf= strandbuf;
730
731         return strandbuf;
732 }
733
734 /* ------------------------------------------------------------------------ */
735
736 ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
737 {
738         ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
739         
740         BLI_addtail(&re->objecttable, obr);
741         obr->ob= ob;
742         obr->par= par;
743         obr->index= index;
744         obr->psysindex= psysindex;
745         obr->lay= lay;
746
747         return obr;
748 }
749
750 void free_renderdata_vertnodes(VertTableNode *vertnodes)
751 {
752         int a;
753         
754         if (vertnodes==NULL) return;
755         
756         for (a=0; vertnodes[a].vert; a++) {
757                 MEM_freeN(vertnodes[a].vert);
758                 
759                 if (vertnodes[a].rad)
760                         MEM_freeN(vertnodes[a].rad);
761                 if (vertnodes[a].strand)
762                         MEM_freeN(vertnodes[a].strand);
763                 if (vertnodes[a].tangent)
764                         MEM_freeN(vertnodes[a].tangent);
765                 if (vertnodes[a].stress)
766                         MEM_freeN(vertnodes[a].stress);
767                 if (vertnodes[a].winspeed)
768                         MEM_freeN(vertnodes[a].winspeed);
769                 if (vertnodes[a].origindex)
770                         MEM_freeN(vertnodes[a].origindex);
771         }
772         
773         MEM_freeN(vertnodes);
774 }
775
776 void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
777 {
778         int a;
779         
780         if (vlaknodes==NULL) return;
781         
782         for (a=0; vlaknodes[a].vlak; a++) {
783                 MEM_freeN(vlaknodes[a].vlak);
784                 
785                 if (vlaknodes[a].mtface)
786                         MEM_freeN(vlaknodes[a].mtface);
787                 if (vlaknodes[a].mcol)
788                         MEM_freeN(vlaknodes[a].mcol);
789                 if (vlaknodes[a].origindex)
790                         MEM_freeN(vlaknodes[a].origindex);
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 static 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
874                 if (obr->mcol)
875                         MEM_freeN(obr->mcol);
876                         
877                 if (obr->rayfaces) {
878                         MEM_freeN(obr->rayfaces);
879                         obr->rayfaces = NULL;
880                 }
881
882                 if (obr->rayprimitives) {
883                         MEM_freeN(obr->rayprimitives);
884                         obr->rayprimitives = NULL;
885                 }
886
887                 if (obr->raytree) {
888                         RE_rayobject_free(obr->raytree);
889                         obr->raytree = NULL;
890                 }
891         }
892
893         if (re->objectinstance) {
894                 for (obi=re->instancetable.first; obi; obi=obi->next) {
895                         if (obi->vectors)
896                                 MEM_freeN(obi->vectors);
897
898                         if (obi->raytree)
899                                 RE_rayobject_free(obi->raytree);
900                 }
901
902                 MEM_freeN(re->objectinstance);
903                 re->objectinstance= NULL;
904                 re->totinstance= 0;
905                 re->instancetable.first= re->instancetable.last= NULL;
906         }
907
908         if (re->sortedhalos) {
909                 MEM_freeN(re->sortedhalos);
910                 re->sortedhalos= NULL;
911         }
912
913         BLI_freelistN(&re->customdata_names);
914         BLI_freelistN(&re->objecttable);
915         BLI_freelistN(&re->instancetable);
916 }
917
918 /* ------------------------------------------------------------------------ */
919
920 HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
921 {
922         HaloRen *h, **temp;
923         int a;
924
925         if (nr<0) {
926                 printf("error in findOrAddHalo: %d\n", nr);
927                 return NULL;
928         }
929         a= nr>>8;
930         
931         if (a>=obr->blohalen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
932                 //printf("Allocating %i more halo groups.  %i total.\n", 
933                 //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
934                 temp=obr->bloha;
935                 
936                 obr->bloha = (HaloRen **)MEM_callocN(sizeof(void *) * (obr->blohalen + TABLEINITSIZE), "Bloha");
937                 if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void *));
938                 memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE * sizeof(void *));
939                 obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
940                 if (temp) MEM_freeN(temp);
941         }
942         
943         h= obr->bloha[a];
944         if (h==NULL) {
945                 h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen), "findOrAdHalo");
946                 obr->bloha[a]= h;
947         }
948         h+= (nr & 255);
949         return h;
950 }
951
952 /* ------------------------------------------------------------------------- */
953
954 HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
955                      const float vec[3], const float vec1[3],
956                      const float *orco, float hasize, float vectsize, int seed)
957 {
958         const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
959         const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0;
960         HaloRen *har;
961         MTex *mtex;
962         float tin, tr, tg, tb, ta;
963         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
964
965         if (hasize==0.0f) return NULL;
966
967         projectverto(vec, re->winmat, hoco);
968         if (hoco[3]==0.0f) return NULL;
969         if (vec1) {
970                 projectverto(vec1, re->winmat, hoco1);
971                 if (hoco1[3]==0.0f) return NULL;
972         }
973
974         har= RE_findOrAddHalo(obr, obr->tothalo++);
975         copy_v3_v3(har->co, vec);
976         har->hasize= hasize;
977
978         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
979         /* we do it here for sorting of halos */
980         zn= hoco[3];
981         har->xs= 0.5f*re->winx*(hoco[0]/zn);
982         har->ys= 0.5f*re->winy*(hoco[1]/zn);
983         har->zs= 0x7FFFFF*(hoco[2]/zn);
984         
985         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
986         
987         /* halovect */
988         if (vec1) {
989
990                 har->type |= HA_VECT;
991
992                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
993                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
994                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
995                 else zn = atan2f(yn, xn);
996
997                 har->sin = sinf(zn);
998                 har->cos = cosf(zn);
999                 zn= len_v3v3(vec1, vec);
1000
1001                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1002                 
1003                 sub_v3_v3v3(har->no, vec, vec1);
1004                 normalize_v3(har->no);
1005         }
1006
1007         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1008
1009         har->alfa= ma->alpha;
1010         har->r= ma->r;
1011         har->g= ma->g;
1012         har->b= ma->b;
1013         har->add= (255.0f*ma->add);
1014         har->mat= ma;
1015         har->hard= ma->har;
1016         har->seed= seed % 256;
1017
1018         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1019         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1020         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1021         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1022
1023
1024         if (ma->mtex[0]) {
1025
1026                 if (ma->mode & MA_HALOTEX) {
1027                         har->tex = 1;
1028                 }
1029                 else if (har->mat->septex & (1 << 0)) {
1030                         /* only 1 level textures */
1031                 }
1032                 else {
1033                         mtex= ma->mtex[0];
1034                         copy_v3_v3(texvec, vec);
1035
1036                         if (mtex->texco & TEXCO_NORM) {
1037                                 ;
1038                         }
1039                         else if (mtex->texco & TEXCO_OBJECT) {
1040                                 /* texvec[0]+= imatbase->ivec[0]; */
1041                                 /* texvec[1]+= imatbase->ivec[1]; */
1042                                 /* texvec[2]+= imatbase->ivec[2]; */
1043                                 /* mul_m3_v3(imatbase->imat, texvec); */
1044                         }
1045                         else {
1046                                 if (orco) {
1047                                         copy_v3_v3(texvec, orco);
1048                                 }
1049                         }
1050
1051                         externtex(mtex,
1052                                   texvec,
1053                                   &tin, &tr, &tg, &tb, &ta,
1054                                   0,
1055                                   re->pool,
1056                                   skip_load_image,
1057                                   texnode_preview);
1058
1059                         yn= tin*mtex->colfac;
1060                         //zn= tin*mtex->alphafac;
1061
1062                         if (mtex->mapto & MAP_COL) {
1063                                 zn= 1.0f-yn;
1064                                 har->r= (yn*tr+ zn*ma->r);
1065                                 har->g= (yn*tg+ zn*ma->g);
1066                                 har->b= (yn*tb+ zn*ma->b);
1067                         }
1068                         if (mtex->texco & TEXCO_UV) {
1069                                 har->alfa= tin;
1070                         }
1071                         if (mtex->mapto & MAP_ALPHA)
1072                                 har->alfa= tin;
1073                 }
1074         }
1075
1076         har->pool = re->pool;
1077         har->skip_load_image = skip_load_image;
1078         har->texnode_preview = texnode_preview;
1079
1080         return har;
1081 }
1082
1083 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,
1084                               const float vec[3], const float vec1[3],
1085                               const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3])
1086 {
1087         const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
1088         const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0;
1089         HaloRen *har;
1090         MTex *mtex;
1091         float tin, tr, tg, tb, ta;
1092         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3];
1093         int i, hasrgb;
1094
1095         if (hasize==0.0f) return NULL;
1096
1097         projectverto(vec, re->winmat, hoco);
1098         if (hoco[3]==0.0f) return NULL;
1099         if (vec1) {
1100                 projectverto(vec1, re->winmat, hoco1);
1101                 if (hoco1[3]==0.0f) return NULL;
1102         }
1103
1104         har= RE_findOrAddHalo(obr, obr->tothalo++);
1105         copy_v3_v3(har->co, vec);
1106         har->hasize= hasize;
1107
1108         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1109         /* we do it here for sorting of halos */
1110         zn= hoco[3];
1111         har->xs= 0.5f*re->winx*(hoco[0]/zn);
1112         har->ys= 0.5f*re->winy*(hoco[1]/zn);
1113         har->zs= 0x7FFFFF*(hoco[2]/zn);
1114         
1115         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1116         
1117         /* halovect */
1118         if (vec1) {
1119
1120                 har->type |= HA_VECT;
1121
1122                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1123                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1124                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1125                 else zn = atan2f(yn, xn);
1126
1127                 har->sin = sinf(zn);
1128                 har->cos = cosf(zn);
1129                 zn= len_v3v3(vec1, vec)*0.5f;
1130
1131                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1132                 
1133                 sub_v3_v3v3(har->no, vec, vec1);
1134                 normalize_v3(har->no);
1135         }
1136
1137         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1138
1139         har->alfa= ma->alpha;
1140         har->r= ma->r;
1141         har->g= ma->g;
1142         har->b= ma->b;
1143         har->add= (255.0f*ma->add);
1144         har->mat= ma;
1145         har->hard= ma->har;
1146         har->seed= seed % 256;
1147
1148         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1149         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1150         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1151         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1152
1153         if ((ma->mode & MA_HALOTEX) && ma->mtex[0])
1154                 har->tex= 1;
1155         
1156         for (i=0; i<MAX_MTEX; i++)
1157                 if (ma->mtex[i] && (ma->septex & (1<<i))==0) {
1158                         mtex= ma->mtex[i];
1159                         copy_v3_v3(texvec, vec);
1160
1161                         if (mtex->texco & TEXCO_NORM) {
1162                                 ;
1163                         }
1164                         else if (mtex->texco & TEXCO_OBJECT) {
1165                                 if (mtex->object)
1166                                         mul_m4_v3(mtex->object->imat_ren, texvec);
1167                         }
1168                         else if (mtex->texco & TEXCO_GLOB) {
1169                                 copy_v3_v3(texvec, vec);
1170                         }
1171                         else if (mtex->texco & TEXCO_UV && uvco) {
1172                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname);
1173                                 if (uv_index<0)
1174                                         uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
1175
1176                                 uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
1177
1178                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1179                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1180                                 texvec[2]=0.0f;
1181                         }
1182                         else if (mtex->texco & TEXCO_PARTICLE) {
1183                                 /* particle coordinates in range [0, 1] */
1184                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1185                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1186                                 texvec[2] = pa_co[2];
1187                         }
1188                         else if (orco) {
1189                                 copy_v3_v3(texvec, orco);
1190                         }
1191
1192                         hasrgb = externtex(mtex,
1193                                            texvec,
1194                                            &tin, &tr, &tg, &tb, &ta,
1195                                            0,
1196                                            re->pool,
1197                                            skip_load_image,
1198                                            texnode_preview);
1199
1200                         //yn= tin*mtex->colfac;
1201                         //zn= tin*mtex->alphafac;
1202                         if (mtex->mapto & MAP_COL) {
1203                                 tex[0]=tr;
1204                                 tex[1]=tg;
1205                                 tex[2]=tb;
1206                                 out[0]=har->r;
1207                                 out[1]=har->g;
1208                                 out[2]=har->b;
1209
1210                                 texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype);
1211                         //      zn= 1.0-yn;
1212                                 //har->r= (yn*tr+ zn*ma->r);
1213                                 //har->g= (yn*tg+ zn*ma->g);
1214                                 //har->b= (yn*tb+ zn*ma->b);
1215                                 har->r= in[0];
1216                                 har->g= in[1];
1217                                 har->b= in[2];
1218                         }
1219
1220                         /* alpha returned, so let's use it instead of intensity */
1221                         if (hasrgb)
1222                                 tin = ta;
1223
1224                         if (mtex->mapto & MAP_ALPHA)
1225                                 har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype);
1226                         if (mtex->mapto & MAP_HAR)
1227                                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype);
1228                         if (mtex->mapto & MAP_RAYMIRR)
1229                                 har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype);
1230                         if (mtex->mapto & MAP_TRANSLU) {
1231                                 float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype);
1232                                 CLAMP(add, 0.f, 1.f);
1233                                 har->add = 255.0f*add;
1234                         }
1235                         /* now what on earth is this good for?? */
1236                         //if (mtex->texco & 16) {
1237                         //      har->alfa= tin;
1238                         //}
1239                 }
1240
1241         har->pool = re->pool;
1242         har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
1243         har->texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0;
1244
1245         return har;
1246 }
1247
1248 /* -------------------------- operations on entire database ----------------------- */
1249
1250 /* ugly function for halos in panorama */
1251 static int panotestclip(Render *re, bool do_pano, float v[4])
1252 {
1253         /* part size (ensure we run RE_parts_clamp first) */
1254         BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx));
1255         BLI_assert(re->party == min_ii(re->r.tiley, re->recty));
1256
1257         if (do_pano == false) {
1258                 return testclip(v);
1259         }
1260         else {
1261                 /* to be used for halos en infos */
1262                 float abs4;
1263                 short c = 0;
1264
1265                 int xparts = (re->rectx + re->partx - 1) / re->partx;
1266
1267                 abs4= fabsf(v[3]);
1268
1269                 if (v[2]< -abs4) c=16;          /* this used to be " if (v[2]<0) ", see clippz() */
1270                 else if (v[2]> abs4) c+= 32;
1271
1272                 if ( v[1]>abs4) c+=4;
1273                 else if ( v[1]< -abs4) c+=8;
1274
1275                 abs4*= xparts;
1276                 if ( v[0]>abs4) c+=2;
1277                 else if ( v[0]< -abs4) c+=1;
1278
1279                 return c;
1280         }
1281 }
1282
1283 /**
1284  * This adds the hcs coordinates to vertices. It iterates over all
1285  * vertices, halos and faces. After the conversion, we clip in hcs.
1286  *
1287  * Elsewhere, all primites are converted to vertices.
1288  * Called in
1289  * - envmapping (envmap.c)
1290  * - shadow buffering (shadbuf.c)
1291  */
1292
1293 void project_renderdata(Render *re,
1294                         void (*projectfunc)(const float *, float mat[4][4], float *),
1295                         bool do_pano, float xoffs, bool UNUSED(do_buckets))
1296 {
1297         ObjectRen *obr;
1298         HaloRen *har = NULL;
1299         float zn, vec[3], hoco[4];
1300         int a;
1301
1302         if (do_pano) {
1303                 float panophi= xoffs;
1304                 
1305                 re->panosi = sinf(panophi);
1306                 re->panoco = cosf(panophi);
1307         }
1308
1309         for (obr=re->objecttable.first; obr; obr=obr->next) {
1310                 /* calculate view coordinates (and zbuffer value) */
1311                 for (a=0; a<obr->tothalo; a++) {
1312                         if ((a & 255)==0) har= obr->bloha[a>>8];
1313                         else har++;
1314
1315                         if (do_pano) {
1316                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1317                                 vec[1]= har->co[1];
1318                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1319                         }
1320                         else {
1321                                 copy_v3_v3(vec, har->co);
1322                         }
1323
1324                         projectfunc(vec, re->winmat, hoco);
1325                         
1326                         /* we clip halos less critical, but not for the Z */
1327                         hoco[0]*= 0.5f;
1328                         hoco[1]*= 0.5f;
1329                         
1330                         if ( panotestclip(re, do_pano, hoco) ) {
1331                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1332                         }
1333                         else if (hoco[3]<0.0f) {
1334                                 har->miny= har->maxy= -10000;   /* render clips it */
1335                         }
1336                         else { /* do the projection...*/
1337                                 /* bring back hocos */
1338                                 hoco[0]*= 2.0f;
1339                                 hoco[1]*= 2.0f;
1340                                 
1341                                 zn= hoco[3];
1342                                 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1343                                 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
1344                         
1345                                 /* this should be the zbuffer coordinate */
1346                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1347                                 /* taking this from the face clip functions? seems ok... */
1348                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1349                                 
1350                                 vec[0]+= har->hasize;
1351                                 projectfunc(vec, re->winmat, hoco);
1352                                 vec[0]-= har->hasize;
1353                                 zn= hoco[3];
1354                                 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
1355                         
1356                                 /* this clip is not really OK, to prevent stars to become too large */
1357                                 if (har->type & HA_ONLYSKY) {
1358                                         if (har->rad>3.0f) har->rad= 3.0f;
1359                                 }
1360                         
1361                                 har->radsq= har->rad*har->rad;
1362                         
1363                                 har->miny= har->ys - har->rad/re->ycor;
1364                                 har->maxy= har->ys + har->rad/re->ycor;
1365                         
1366                                 /* the Zd value is still not really correct for pano */
1367                         
1368                                 vec[2] -= har->hasize;  /* z negative, otherwise it's clipped */
1369                                 projectfunc(vec, re->winmat, hoco);
1370                                 zn = hoco[3];
1371                                 zn = fabsf((float)har->zs - 0x7FFFFF * (hoco[2] / zn));
1372                                 har->zd = CLAMPIS(zn, 0, INT_MAX);
1373                         
1374                         }
1375                         
1376                 }
1377         }
1378 }
1379
1380 /* ------------------------------------------------------------------------- */
1381
1382 void RE_updateRenderInstance(Render *re, ObjectInstanceRen *obi, int flag)
1383 {
1384         /* flag specifies what things have changed. */
1385         if (flag & RE_OBJECT_INSTANCES_UPDATE_OBMAT) {
1386                 copy_m4_m4(obi->obmat, obi->ob->obmat);
1387                 invert_m4_m4(obi->obinvmat, obi->obmat);
1388         }
1389         if (flag & RE_OBJECT_INSTANCES_UPDATE_VIEW) {
1390                 mul_m4_m4m4(obi->localtoviewmat, re->viewmat, obi->obmat);
1391                 mul_m4_m4m4(obi->localtoviewinvmat, obi->obinvmat, re->viewinv);
1392         }
1393 }
1394
1395 void RE_updateRenderInstances(Render *re, int flag)
1396 {
1397         int i = 0;
1398         for (i = 0; i < re->totinstance; i++)
1399                 RE_updateRenderInstance(re, &re->objectinstance[i], flag);
1400 }
1401
1402 ObjectInstanceRen *RE_addRenderInstance(
1403         Render *re, ObjectRen *obr, Object *ob, Object *par,
1404         int index, int psysindex, float mat[4][4], int lay, const DupliObject *dob)
1405 {
1406         ObjectInstanceRen *obi;
1407         float mat3[3][3];
1408
1409         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1410         obi->obr= obr;
1411         obi->ob= ob;
1412         obi->par= par;
1413         obi->index= index;
1414         obi->psysindex= psysindex;
1415         obi->lay= lay;
1416
1417         /* Fill particle info */
1418         if (par && dob) {
1419                 const ParticleSystem *psys = dob->particle_system;
1420                 if (psys) {
1421                         int part_index;
1422                         if (obi->index < psys->totpart) {
1423                                 part_index = obi->index;
1424                         }
1425                         else if (psys->child) {
1426                                 part_index = psys->child[obi->index - psys->totpart].parent;
1427                         }
1428                         else {
1429                                 part_index = -1;
1430                         }
1431
1432                         if (part_index >= 0) {
1433                                 const ParticleData *p = &psys->particles[part_index];
1434                                 obi->part_index = part_index;
1435                                 obi->part_size = p->size;
1436                                 obi->part_age = RE_GetStats(re)->cfra - p->time;
1437                                 obi->part_lifetime = p->lifetime;
1438
1439                                 copy_v3_v3(obi->part_co, p->state.co);
1440                                 copy_v3_v3(obi->part_vel, p->state.vel);
1441                                 copy_v3_v3(obi->part_avel, p->state.ave);
1442                         }
1443                 }
1444         }
1445
1446         RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW);
1447
1448         if (mat) {
1449                 copy_m4_m4(obi->mat, mat);
1450                 copy_m3_m4(mat3, mat);
1451                 invert_m3_m3(obi->nmat, mat3);
1452                 transpose_m3(obi->nmat);
1453                 obi->flag |= R_DUPLI_TRANSFORMED;
1454         }
1455
1456         BLI_addtail(&re->instancetable, obi);
1457
1458         return obi;
1459 }
1460
1461 void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
1462 {
1463         *index = obi->part_index;
1464         *age = obi->part_age;
1465         *lifetime = obi->part_lifetime;
1466         copy_v3_v3(co, obi->part_co);
1467         *size = obi->part_size;
1468         copy_v3_v3(vel, obi->part_vel);
1469         copy_v3_v3(angvel, obi->part_avel);
1470 }
1471
1472
1473 void RE_makeRenderInstances(Render *re)
1474 {
1475         ObjectInstanceRen *obi, *oldobi;
1476         ListBase newlist;
1477         int tot;
1478
1479         /* convert list of object instances to an array for index based lookup */
1480         tot= BLI_listbase_count(&re->instancetable);
1481         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1482         re->totinstance= tot;
1483         newlist.first= newlist.last= NULL;
1484
1485         obi= re->objectinstance;
1486         for (oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1487                 *obi= *oldobi;
1488
1489                 if (obi->obr) {
1490                         obi->prev= obi->next= NULL;
1491                         BLI_addtail(&newlist, obi);
1492                         obi++;
1493                 }
1494                 else
1495                         re->totinstance--;
1496         }
1497
1498         BLI_freelistN(&re->instancetable);
1499         re->instancetable= newlist;
1500 }
1501
1502 /* four functions to facilitate envmap rotation for raytrace */
1503 void RE_instance_rotate_ray_start(ObjectInstanceRen *obi, Isect *is)
1504 {
1505         if (obi && (obi->flag & R_ENV_TRANSFORMED)) {
1506                 copy_v3_v3(is->origstart, is->start);
1507                 mul_m4_v3(obi->imat, is->start);
1508         }
1509 }
1510
1511 void RE_instance_rotate_ray_dir(ObjectInstanceRen *obi, Isect *is)
1512 {
1513         if (obi && (obi->flag & R_ENV_TRANSFORMED)) {
1514                 float end[3];
1515
1516                 copy_v3_v3(is->origdir, is->dir);
1517                 add_v3_v3v3(end, is->origstart, is->dir);
1518
1519                 mul_m4_v3(obi->imat, end);
1520                 sub_v3_v3v3(is->dir, end, is->start);
1521         }
1522 }
1523
1524 void RE_instance_rotate_ray(ObjectInstanceRen *obi, Isect *is)
1525 {
1526         RE_instance_rotate_ray_start(obi, is);
1527         RE_instance_rotate_ray_dir(obi, is);
1528 }
1529
1530 void RE_instance_rotate_ray_restore(ObjectInstanceRen *obi, Isect *is)
1531 {
1532         if (obi && (obi->flag & R_ENV_TRANSFORMED)) {
1533                 copy_v3_v3(is->start, is->origstart);
1534                 copy_v3_v3(is->dir, is->origdir);
1535         }
1536 }
1537
1538 int clip_render_object(float boundbox[2][3], float bounds[4], float winmat[4][4])
1539 {
1540         float mat[4][4], vec[4];
1541         int a, fl, flag = -1;
1542
1543         copy_m4_m4(mat, winmat);
1544
1545         for (a=0; a < 8; a++) {
1546                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1547                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1548                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1549                 vec[3]= 1.0;
1550                 mul_m4_v4(mat, vec);
1551
1552                 fl = 0;
1553                 if (bounds) {
1554                         if      (vec[0] < bounds[0] * vec[3]) fl |= 1;
1555                         else if (vec[0] > bounds[1] * vec[3]) fl |= 2;
1556                         
1557                         if      (vec[1] > bounds[3] * vec[3]) fl |= 4;
1558                         else if (vec[1] < bounds[2] * vec[3]) fl |= 8;
1559                 }
1560                 else {
1561                         if      (vec[0] < -vec[3]) fl |= 1;
1562                         else if (vec[0] >  vec[3]) fl |= 2;
1563                         
1564                         if      (vec[1] >  vec[3]) fl |= 4;
1565                         else if (vec[1] < -vec[3]) fl |= 8;
1566                 }
1567                 if      (vec[2] < -vec[3]) fl |= 16;
1568                 else if (vec[2] >  vec[3]) fl |= 32;
1569
1570                 flag &= fl;
1571                 if (flag == 0) {
1572                         return 0;
1573                 }
1574         }
1575
1576         return flag;
1577 }
1578