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