Vector Transform node support for GLSL mode and the internal renderer
[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         HaloRen *har;
960         MTex *mtex;
961         float tin, tr, tg, tb, ta;
962         float xn, yn, zn, texvec[3], hoco[4], hoco1[4];
963
964         if (hasize==0.0f) return NULL;
965
966         projectverto(vec, re->winmat, hoco);
967         if (hoco[3]==0.0f) return NULL;
968         if (vec1) {
969                 projectverto(vec1, re->winmat, hoco1);
970                 if (hoco1[3]==0.0f) return NULL;
971         }
972
973         har= RE_findOrAddHalo(obr, obr->tothalo++);
974         copy_v3_v3(har->co, vec);
975         har->hasize= hasize;
976
977         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
978         /* we do it here for sorting of halos */
979         zn= hoco[3];
980         har->xs= 0.5f*re->winx*(hoco[0]/zn);
981         har->ys= 0.5f*re->winy*(hoco[1]/zn);
982         har->zs= 0x7FFFFF*(hoco[2]/zn);
983         
984         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
985         
986         /* halovect */
987         if (vec1) {
988
989                 har->type |= HA_VECT;
990
991                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
992                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
993                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f;
994                 else zn = atan2f(yn, xn);
995
996                 har->sin = sinf(zn);
997                 har->cos = cosf(zn);
998                 zn= len_v3v3(vec1, vec);
999
1000                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1001                 
1002                 sub_v3_v3v3(har->no, vec, vec1);
1003                 normalize_v3(har->no);
1004         }
1005
1006         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1007
1008         har->alfa= ma->alpha;
1009         har->r= ma->r;
1010         har->g= ma->g;
1011         har->b= ma->b;
1012         har->add= (255.0f*ma->add);
1013         har->mat= ma;
1014         har->hard= ma->har;
1015         har->seed= seed % 256;
1016
1017         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1018         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1019         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1020         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1021
1022
1023         if (ma->mtex[0]) {
1024
1025                 if (ma->mode & MA_HALOTEX) {
1026                         har->tex = 1;
1027                 }
1028                 else if (har->mat->septex & (1 << 0)) {
1029                         /* only 1 level textures */
1030                 }
1031                 else {
1032                         mtex= ma->mtex[0];
1033                         copy_v3_v3(texvec, vec);
1034
1035                         if (mtex->texco & TEXCO_NORM) {
1036                                 ;
1037                         }
1038                         else if (mtex->texco & TEXCO_OBJECT) {
1039                                 /* texvec[0]+= imatbase->ivec[0]; */
1040                                 /* texvec[1]+= imatbase->ivec[1]; */
1041                                 /* texvec[2]+= imatbase->ivec[2]; */
1042                                 /* mul_m3_v3(imatbase->imat, texvec); */
1043                         }
1044                         else {
1045                                 if (orco) {
1046                                         copy_v3_v3(texvec, orco);
1047                                 }
1048                         }
1049
1050                         externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image);
1051
1052                         yn= tin*mtex->colfac;
1053                         //zn= tin*mtex->alphafac;
1054
1055                         if (mtex->mapto & MAP_COL) {
1056                                 zn= 1.0f-yn;
1057                                 har->r= (yn*tr+ zn*ma->r);
1058                                 har->g= (yn*tg+ zn*ma->g);
1059                                 har->b= (yn*tb+ zn*ma->b);
1060                         }
1061                         if (mtex->texco & TEXCO_UV) {
1062                                 har->alfa= tin;
1063                         }
1064                         if (mtex->mapto & MAP_ALPHA)
1065                                 har->alfa= tin;
1066                 }
1067         }
1068
1069         har->pool = re->pool;
1070         har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
1071
1072         return har;
1073 }
1074
1075 HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,
1076                               const float vec[3], const float vec1[3],
1077                               const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3])
1078 {
1079         const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
1080         HaloRen *har;
1081         MTex *mtex;
1082         float tin, tr, tg, tb, ta;
1083         float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3];
1084         int i, hasrgb;
1085
1086         if (hasize==0.0f) return NULL;
1087
1088         projectverto(vec, re->winmat, hoco);
1089         if (hoco[3]==0.0f) return NULL;
1090         if (vec1) {
1091                 projectverto(vec1, re->winmat, hoco1);
1092                 if (hoco1[3]==0.0f) return NULL;
1093         }
1094
1095         har= RE_findOrAddHalo(obr, obr->tothalo++);
1096         copy_v3_v3(har->co, vec);
1097         har->hasize= hasize;
1098
1099         /* actual projectvert is done in function project_renderdata() because of parts/border/pano */
1100         /* we do it here for sorting of halos */
1101         zn= hoco[3];
1102         har->xs= 0.5f*re->winx*(hoco[0]/zn);
1103         har->ys= 0.5f*re->winy*(hoco[1]/zn);
1104         har->zs= 0x7FFFFF*(hoco[2]/zn);
1105         
1106         har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); 
1107         
1108         /* halovect */
1109         if (vec1) {
1110
1111                 har->type |= HA_VECT;
1112
1113                 xn=  har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]);
1114                 yn=  har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]);
1115                 if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0;
1116                 else zn = atan2f(yn, xn);
1117
1118                 har->sin = sinf(zn);
1119                 har->cos = cosf(zn);
1120                 zn= len_v3v3(vec1, vec)*0.5f;
1121
1122                 har->hasize= vectsize*zn + (1.0f-vectsize)*hasize;
1123                 
1124                 sub_v3_v3v3(har->no, vec, vec1);
1125                 normalize_v3(har->no);
1126         }
1127
1128         if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
1129
1130         har->alfa= ma->alpha;
1131         har->r= ma->r;
1132         har->g= ma->g;
1133         har->b= ma->b;
1134         har->add= (255.0f*ma->add);
1135         har->mat= ma;
1136         har->hard= ma->har;
1137         har->seed= seed % 256;
1138
1139         if (ma->mode & MA_STAR) har->starpoints= ma->starc;
1140         if (ma->mode & MA_HALO_LINES) har->linec= ma->linec;
1141         if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
1142         if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
1143
1144         if ((ma->mode & MA_HALOTEX) && ma->mtex[0])
1145                 har->tex= 1;
1146         
1147         for (i=0; i<MAX_MTEX; i++)
1148                 if (ma->mtex[i] && (ma->septex & (1<<i))==0) {
1149                         mtex= ma->mtex[i];
1150                         copy_v3_v3(texvec, vec);
1151
1152                         if (mtex->texco & TEXCO_NORM) {
1153                                 ;
1154                         }
1155                         else if (mtex->texco & TEXCO_OBJECT) {
1156                                 if (mtex->object)
1157                                         mul_m4_v3(mtex->object->imat_ren, texvec);
1158                         }
1159                         else if (mtex->texco & TEXCO_GLOB) {
1160                                 copy_v3_v3(texvec, vec);
1161                         }
1162                         else if (mtex->texco & TEXCO_UV && uvco) {
1163                                 int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname);
1164                                 if (uv_index<0)
1165                                         uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
1166
1167                                 uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE);
1168
1169                                 texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
1170                                 texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
1171                                 texvec[2]=0.0f;
1172                         }
1173                         else if (mtex->texco & TEXCO_PARTICLE) {
1174                                 /* particle coordinates in range [0, 1] */
1175                                 texvec[0] = 2.f * pa_co[0] - 1.f;
1176                                 texvec[1] = 2.f * pa_co[1] - 1.f;
1177                                 texvec[2] = pa_co[2];
1178                         }
1179                         else if (orco) {
1180                                 copy_v3_v3(texvec, orco);
1181                         }
1182
1183                         hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image);
1184
1185                         //yn= tin*mtex->colfac;
1186                         //zn= tin*mtex->alphafac;
1187                         if (mtex->mapto & MAP_COL) {
1188                                 tex[0]=tr;
1189                                 tex[1]=tg;
1190                                 tex[2]=tb;
1191                                 out[0]=har->r;
1192                                 out[1]=har->g;
1193                                 out[2]=har->b;
1194
1195                                 texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype);
1196                         //      zn= 1.0-yn;
1197                                 //har->r= (yn*tr+ zn*ma->r);
1198                                 //har->g= (yn*tg+ zn*ma->g);
1199                                 //har->b= (yn*tb+ zn*ma->b);
1200                                 har->r= in[0];
1201                                 har->g= in[1];
1202                                 har->b= in[2];
1203                         }
1204
1205                         /* alpha returned, so let's use it instead of intensity */
1206                         if (hasrgb)
1207                                 tin = ta;
1208
1209                         if (mtex->mapto & MAP_ALPHA)
1210                                 har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype);
1211                         if (mtex->mapto & MAP_HAR)
1212                                 har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype);
1213                         if (mtex->mapto & MAP_RAYMIRR)
1214                                 har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype);
1215                         if (mtex->mapto & MAP_TRANSLU) {
1216                                 float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype);
1217                                 CLAMP(add, 0.f, 1.f);
1218                                 har->add = 255.0f*add;
1219                         }
1220                         /* now what on earth is this good for?? */
1221                         //if (mtex->texco & 16) {
1222                         //      har->alfa= tin;
1223                         //}
1224                 }
1225
1226         har->pool = re->pool;
1227         har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
1228
1229         return har;
1230 }
1231
1232 /* -------------------------- operations on entire database ----------------------- */
1233
1234 /* ugly function for halos in panorama */
1235 static int panotestclip(Render *re, bool do_pano, float v[4])
1236 {
1237         /* part size (ensure we run RE_parts_clamp first) */
1238         BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx));
1239         BLI_assert(re->party == min_ii(re->r.tiley, re->recty));
1240
1241         if (do_pano == false) {
1242                 return testclip(v);
1243         }
1244         else {
1245                 /* to be used for halos en infos */
1246                 float abs4;
1247                 short c = 0;
1248
1249                 int xparts = (re->rectx + re->partx - 1) / re->partx;
1250
1251                 abs4= fabsf(v[3]);
1252
1253                 if (v[2]< -abs4) c=16;          /* this used to be " if (v[2]<0) ", see clippz() */
1254                 else if (v[2]> abs4) c+= 32;
1255
1256                 if ( v[1]>abs4) c+=4;
1257                 else if ( v[1]< -abs4) c+=8;
1258
1259                 abs4*= xparts;
1260                 if ( v[0]>abs4) c+=2;
1261                 else if ( v[0]< -abs4) c+=1;
1262
1263                 return c;
1264         }
1265 }
1266
1267 /**
1268  * This adds the hcs coordinates to vertices. It iterates over all
1269  * vertices, halos and faces. After the conversion, we clip in hcs.
1270  *
1271  * Elsewhere, all primites are converted to vertices.
1272  * Called in
1273  * - envmapping (envmap.c)
1274  * - shadow buffering (shadbuf.c)
1275  */
1276
1277 void project_renderdata(Render *re,
1278                         void (*projectfunc)(const float *, float mat[4][4], float *),
1279                         bool do_pano, float xoffs, bool UNUSED(do_buckets))
1280 {
1281         ObjectRen *obr;
1282         HaloRen *har = NULL;
1283         float zn, vec[3], hoco[4];
1284         int a;
1285
1286         if (do_pano) {
1287                 float panophi= xoffs;
1288                 
1289                 re->panosi = sinf(panophi);
1290                 re->panoco = cosf(panophi);
1291         }
1292
1293         for (obr=re->objecttable.first; obr; obr=obr->next) {
1294                 /* calculate view coordinates (and zbuffer value) */
1295                 for (a=0; a<obr->tothalo; a++) {
1296                         if ((a & 255)==0) har= obr->bloha[a>>8];
1297                         else har++;
1298
1299                         if (do_pano) {
1300                                 vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
1301                                 vec[1]= har->co[1];
1302                                 vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
1303                         }
1304                         else {
1305                                 copy_v3_v3(vec, har->co);
1306                         }
1307
1308                         projectfunc(vec, re->winmat, hoco);
1309                         
1310                         /* we clip halos less critical, but not for the Z */
1311                         hoco[0]*= 0.5f;
1312                         hoco[1]*= 0.5f;
1313                         
1314                         if ( panotestclip(re, do_pano, hoco) ) {
1315                                 har->miny= har->maxy= -10000;   /* that way render clips it */
1316                         }
1317                         else if (hoco[3]<0.0f) {
1318                                 har->miny= har->maxy= -10000;   /* render clips it */
1319                         }
1320                         else { /* do the projection...*/
1321                                 /* bring back hocos */
1322                                 hoco[0]*= 2.0f;
1323                                 hoco[1]*= 2.0f;
1324                                 
1325                                 zn= hoco[3];
1326                                 har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
1327                                 har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn);
1328                         
1329                                 /* this should be the zbuffer coordinate */
1330                                 har->zs= 0x7FFFFF*(hoco[2]/zn);
1331                                 /* taking this from the face clip functions? seems ok... */
1332                                 har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
1333                                 
1334                                 vec[0]+= har->hasize;
1335                                 projectfunc(vec, re->winmat, hoco);
1336                                 vec[0]-= har->hasize;
1337                                 zn= hoco[3];
1338                                 har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn));
1339                         
1340                                 /* this clip is not really OK, to prevent stars to become too large */
1341                                 if (har->type & HA_ONLYSKY) {
1342                                         if (har->rad>3.0f) har->rad= 3.0f;
1343                                 }
1344                         
1345                                 har->radsq= har->rad*har->rad;
1346                         
1347                                 har->miny= har->ys - har->rad/re->ycor;
1348                                 har->maxy= har->ys + har->rad/re->ycor;
1349                         
1350                                 /* the Zd value is still not really correct for pano */
1351                         
1352                                 vec[2] -= har->hasize;  /* z negative, otherwise it's clipped */
1353                                 projectfunc(vec, re->winmat, hoco);
1354                                 zn = hoco[3];
1355                                 zn = fabsf((float)har->zs - 0x7FFFFF * (hoco[2] / zn));
1356                                 har->zd = CLAMPIS(zn, 0, INT_MAX);
1357                         
1358                         }
1359                         
1360                 }
1361         }
1362 }
1363
1364 /* ------------------------------------------------------------------------- */
1365
1366 void RE_updateRenderInstance(Render *re, ObjectInstanceRen *obi, int flag)
1367 {
1368         /* flag specifies what things have changed. */
1369         if (flag & RE_OBJECT_INSTANCES_UPDATE_OBMAT) {
1370                 copy_m4_m4(obi->obmat, obi->ob->obmat);
1371                 invert_m4_m4(obi->obinvmat, obi->obmat);
1372         }
1373         if (flag & RE_OBJECT_INSTANCES_UPDATE_VIEW) {
1374                 mul_m4_m4m4(obi->localtoviewmat, re->viewmat, obi->obmat);
1375                 mul_m4_m4m4(obi->localtoviewinvmat, obi->obinvmat, re->viewinv);
1376         }
1377 }
1378
1379 void RE_updateRenderInstances(Render *re, int flag)
1380 {
1381         int i = 0;
1382         for (i = 0; i < re->totinstance; i++)
1383                 RE_updateRenderInstance(re, &re->objectinstance[i], flag);
1384 }
1385
1386 ObjectInstanceRen *RE_addRenderInstance(
1387         Render *re, ObjectRen *obr, Object *ob, Object *par,
1388         int index, int psysindex, float mat[4][4], int lay, const DupliObject *dob)
1389 {
1390         ObjectInstanceRen *obi;
1391         float mat3[3][3];
1392
1393         obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
1394         obi->obr= obr;
1395         obi->ob= ob;
1396         obi->par= par;
1397         obi->index= index;
1398         obi->psysindex= psysindex;
1399         obi->lay= lay;
1400
1401         /* Fill particle info */
1402         if (par && dob) {
1403                 const ParticleSystem *psys = dob->particle_system;
1404                 if (psys) {
1405                         int part_index;
1406                         if (obi->index < psys->totpart) {
1407                                 part_index = obi->index;
1408                         }
1409                         else if (psys->child) {
1410                                 part_index = psys->child[obi->index - psys->totpart].parent;
1411                         }
1412                         else {
1413                                 part_index = -1;
1414                         }
1415
1416                         if (part_index >= 0) {
1417                                 const ParticleData *p = &psys->particles[part_index];
1418                                 obi->part_index = part_index;
1419                                 obi->part_size = p->size;
1420                                 obi->part_age = RE_GetStats(re)->cfra - p->time;
1421                                 obi->part_lifetime = p->lifetime;
1422
1423                                 copy_v3_v3(obi->part_co, p->state.co);
1424                                 copy_v3_v3(obi->part_vel, p->state.vel);
1425                                 copy_v3_v3(obi->part_avel, p->state.ave);
1426                         }
1427                 }
1428         }
1429
1430         RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW);
1431
1432         if (mat) {
1433                 copy_m4_m4(obi->mat, mat);
1434                 copy_m3_m4(mat3, mat);
1435                 invert_m3_m3(obi->nmat, mat3);
1436                 transpose_m3(obi->nmat);
1437                 obi->flag |= R_DUPLI_TRANSFORMED;
1438         }
1439
1440         BLI_addtail(&re->instancetable, obi);
1441
1442         return obi;
1443 }
1444
1445 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])
1446 {
1447         *index = obi->part_index;
1448         *age = obi->part_age;
1449         *lifetime = obi->part_lifetime;
1450         copy_v3_v3(co, obi->part_co);
1451         *size = obi->part_size;
1452         copy_v3_v3(vel, obi->part_vel);
1453         copy_v3_v3(angvel, obi->part_avel);
1454 }
1455
1456
1457 void RE_makeRenderInstances(Render *re)
1458 {
1459         ObjectInstanceRen *obi, *oldobi;
1460         ListBase newlist;
1461         int tot;
1462
1463         /* convert list of object instances to an array for index based lookup */
1464         tot= BLI_listbase_count(&re->instancetable);
1465         re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
1466         re->totinstance= tot;
1467         newlist.first= newlist.last= NULL;
1468
1469         obi= re->objectinstance;
1470         for (oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
1471                 *obi= *oldobi;
1472
1473                 if (obi->obr) {
1474                         obi->prev= obi->next= NULL;
1475                         BLI_addtail(&newlist, obi);
1476                         obi++;
1477                 }
1478                 else
1479                         re->totinstance--;
1480         }
1481
1482         BLI_freelistN(&re->instancetable);
1483         re->instancetable= newlist;
1484 }
1485
1486 /* four functions to facilitate envmap rotation for raytrace */
1487 void RE_instance_rotate_ray_start(ObjectInstanceRen *obi, Isect *is)
1488 {
1489         if (obi && (obi->flag & R_ENV_TRANSFORMED)) {
1490                 copy_v3_v3(is->origstart, is->start);
1491                 mul_m4_v3(obi->imat, is->start);
1492         }
1493 }
1494
1495 void RE_instance_rotate_ray_dir(ObjectInstanceRen *obi, Isect *is)
1496 {
1497         if (obi && (obi->flag & R_ENV_TRANSFORMED)) {
1498                 float end[3];
1499
1500                 copy_v3_v3(is->origdir, is->dir);
1501                 add_v3_v3v3(end, is->origstart, is->dir);
1502
1503                 mul_m4_v3(obi->imat, end);
1504                 sub_v3_v3v3(is->dir, end, is->start);
1505         }
1506 }
1507
1508 void RE_instance_rotate_ray(ObjectInstanceRen *obi, Isect *is)
1509 {
1510         RE_instance_rotate_ray_start(obi, is);
1511         RE_instance_rotate_ray_dir(obi, is);
1512 }
1513
1514 void RE_instance_rotate_ray_restore(ObjectInstanceRen *obi, Isect *is)
1515 {
1516         if (obi && (obi->flag & R_ENV_TRANSFORMED)) {
1517                 copy_v3_v3(is->start, is->origstart);
1518                 copy_v3_v3(is->dir, is->origdir);
1519         }
1520 }
1521
1522 int clip_render_object(float boundbox[2][3], float bounds[4], float winmat[4][4])
1523 {
1524         float mat[4][4], vec[4];
1525         int a, fl, flag = -1;
1526
1527         copy_m4_m4(mat, winmat);
1528
1529         for (a=0; a < 8; a++) {
1530                 vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
1531                 vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
1532                 vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
1533                 vec[3]= 1.0;
1534                 mul_m4_v4(mat, vec);
1535
1536                 fl = 0;
1537                 if (bounds) {
1538                         if      (vec[0] < bounds[0] * vec[3]) fl |= 1;
1539                         else if (vec[0] > bounds[1] * vec[3]) fl |= 2;
1540                         
1541                         if      (vec[1] > bounds[3] * vec[3]) fl |= 4;
1542                         else if (vec[1] < bounds[2] * vec[3]) fl |= 8;
1543                 }
1544                 else {
1545                         if      (vec[0] < -vec[3]) fl |= 1;
1546                         else if (vec[0] >  vec[3]) fl |= 2;
1547                         
1548                         if      (vec[1] >  vec[3]) fl |= 4;
1549                         else if (vec[1] < -vec[3]) fl |= 8;
1550                 }
1551                 if      (vec[2] < -vec[3]) fl |= 16;
1552                 else if (vec[2] >  vec[3]) fl |= 32;
1553
1554                 flag &= fl;
1555                 if (flag == 0) {
1556                         return 0;
1557                 }
1558         }
1559
1560         return flag;
1561 }
1562