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