32ea28d2b9cc6f968ae70cb0d03a31d7b2dffa7d
[blender.git] / source / blender / renderconverter / intern / convertBlenderScene.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Interface to transform the Blender scene into renderable data.
32  */
33
34 /* check for dl->flag, 1 or 2 should be replaced be the def's below */
35 #define STRUBI hack
36 #define DL_CYCLIC_U 1
37 #define DL_CYCLIC_V 2
38
39
40 #include <math.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <limits.h>          /* for INT_MAX                 */
45
46 #include "blendef.h"
47 #include "MTC_matrixops.h"
48
49 #include "MEM_guardedalloc.h"
50
51 #include "BLI_arithb.h"
52 #include "BLI_blenlib.h"
53 #include "BLI_rand.h"
54 #include "BLI_memarena.h"
55
56 #include "DNA_armature_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_material_types.h"
59 #include "DNA_curve_types.h"
60 #include "DNA_effect_types.h"
61 #include "DNA_ika_types.h"
62 #include "DNA_lamp_types.h"
63 #include "DNA_lattice_types.h"
64 #include "DNA_mesh_types.h"
65 #include "DNA_meshdata_types.h"
66 #include "DNA_meta_types.h"
67 #include "DNA_object_types.h"
68 #include "DNA_object_force.h"
69 #include "DNA_scene_types.h"
70 #include "DNA_texture_types.h"
71 #include "DNA_view3d_types.h"
72
73 #include "BKE_anim.h"
74 #include "BKE_armature.h"
75 #include "BKE_action.h"
76 #include "BKE_curve.h"
77 #include "BKE_constraint.h"
78 #include "BKE_displist.h"
79 #include "BKE_deform.h"
80 #include "BKE_DerivedMesh.h"
81 #include "BKE_effect.h"
82 #include "BKE_global.h"
83 #include "BKE_key.h"
84 #include "BKE_ipo.h"
85 #include "BKE_ika.h"
86 #include "BKE_lattice.h"
87 #include "BKE_material.h"
88 #include "BKE_main.h"
89 #include "BKE_mball.h"
90 #include "BKE_mesh.h"
91 #include "BKE_object.h"
92 #include "BKE_subsurf.h"
93 #include "BKE_texture.h"
94 #include "BKE_utildefines.h"
95 #include "BKE_world.h"
96
97 #include "render.h"
98
99 #include "RE_renderconverter.h"
100
101 #include "BIF_space.h"
102 #include "BIF_screen.h"
103 #include "BIF_editkey.h"
104
105 #include "BSE_sequence.h"
106
107 #include "nla.h"
108
109 #include "BPY_extern.h"
110
111 #include "butspace.h"
112
113 #include "radio.h"
114 #include "YafRay_Api.h"
115
116 extern void error (char *fmt, ...);  /* defined in BIF_toolbox.h, but we dont need to include the rest */ 
117
118 /* yafray: Identity transform 'hack' removed, exporter now transforms vertices back to world.
119  * Same is true for lamp coords & vec.
120  * Duplicated data objects & dupliframe/duplivert objects are only stored once,
121  * only the matrix is stored for all others, in yafray these objects are instances of the original.
122  * The main changes are in RE_rotateBlenderScene().
123  */
124
125 /* ------------------------------------------------------------------------- */
126 /* Local functions                                                           */
127 /* ------------------------------------------------------------------------- */
128 static Material *give_render_material(Object *ob, int nr);
129
130
131
132 /* blenderWorldManipulation.c */
133 /*static void split_u_renderfaces(int startvlak, int startvert, int usize, int plek, int cyclu);*/
134 static void split_v_renderfaces(int startvlak, int startvert, int usize, int vsize, int plek, int cyclu, int cyclv);
135 static int contrpuntnormr(float *n, float *puno);
136 static void as_addvert(VertRen *v1, VlakRen *vlr);
137 static void as_freevert(VertRen *ver);
138 static void autosmooth(int startvert, int startvlak, int degr);
139 static void render_particle_system(Object *ob, PartEff *paf);
140 static void render_static_particle_system(Object *ob, PartEff *paf);
141 static int verghalo(const void *a1, const void *a2);
142 static void sort_halos(void);
143 static void init_render_mball(Object *ob);
144 static void init_render_mesh(Object *ob);
145 static void init_render_surf(Object *ob);
146 static void init_render_curve(Object *ob);
147 static void init_render_object(Object *ob);
148 static HaloRen *initstar(float *vec, float hasize);
149
150 /* Displacement Texture */
151 static void displace_render_face(VlakRen *vlr, float *scale);
152 static void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert);
153 static short test_for_displace(Object *ob);
154 static void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale);
155
156 /* more prototypes for autosmoothing below */
157
158
159 /* ------------------------------------------------------------------------- */
160 /* tool functions/defines for ad hoc simplification and possible future 
161    cleanup      */
162 /* ------------------------------------------------------------------------- */
163
164 #define UVTOINDEX(u,v) (startvlak + (u) * sizev + (v))
165 /*
166
167 NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !!
168         
169 ^       ()----p4----p3----()
170 |       |     |     |     |
171 u       |     |  F1 |  F2 |
172         |     |     |     |
173         ()----p1----p2----()
174                v ->
175 */
176
177 /* ------------------------------------------------------------------------- */
178
179 /* Stuff for stars. This sits here because it uses gl-things. Part of
180    this code may move down to the converter.  */
181 /* ------------------------------------------------------------------------- */
182 /* this is a bad beast, since it is misused by the 3d view drawing as well. */
183
184 extern unsigned char hash[512];
185
186 /* there must be a 'fixed' amount of stars generated between
187  *         near and far
188  * all stars must by preference lie on the far and solely
189  *        differ in clarity/color
190  */
191
192 void RE_make_stars(void (*initfunc)(void),
193                                    void (*vertexfunc)(float*),
194                                    void (*termfunc)(void))
195 {
196         HaloRen *har;
197         double dblrand, hlfrand;
198         float vec[4], fx, fy, fz;
199         float fac, starmindist, clipend;
200         float mat[4][4], stargrid, maxrand, maxjit, force, alpha;
201 /*      float loc_far_var, loc_near_var; */
202         int x, y, z, sx, sy, sz, ex, ey, ez, done = 0;
203         Camera * camera;
204
205         if(initfunc) R.wrld= *(G.scene->world);
206
207         stargrid = R.wrld.stardist;             /* distance between stars */
208         maxrand = 2.0;                                          /* amount a star can be shifted (in grid units) */
209         maxjit = (R.wrld.starcolnoise);                 /* amount a color is being shifted */
210
211 /*      loc_far_var = R.far; */
212 /*      loc_near_var = R.near; */
213
214
215         /* size of stars */
216         force = ( R.wrld.starsize );
217
218         /* minimal free space (starting at camera) */
219         starmindist= R.wrld.starmindist;
220
221         if (stargrid <= 0.10) return;
222
223         if (!initfunc) R.flag |= R_HALO;
224         else stargrid *= 1.0;                           /* then it draws fewer */
225
226
227         MTC_Mat4Invert(mat, R.viewmat);
228
229         /* BOUNDING BOX CALCULATION
230          * bbox goes from z = loc_near_var | loc_far_var,
231          * x = -z | +z,
232          * y = -z | +z
233          */
234
235         camera = G.scene->camera->data;
236         clipend = camera->clipend;
237
238         /* convert to grid coordinates */
239
240         sx = ((mat[3][0] - clipend) / stargrid) - maxrand;
241         sy = ((mat[3][1] - clipend) / stargrid) - maxrand;
242         sz = ((mat[3][2] - clipend) / stargrid) - maxrand;
243
244         ex = ((mat[3][0] + clipend) / stargrid) + maxrand;
245         ey = ((mat[3][1] + clipend) / stargrid) + maxrand;
246         ez = ((mat[3][2] + clipend) / stargrid) + maxrand;
247
248         dblrand = maxrand * stargrid;
249         hlfrand = 2.0 * dblrand;
250
251         if (initfunc) {
252                 initfunc();     
253         }
254
255         for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) {
256                 for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) {
257                         for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) {
258
259                                 BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8));
260                                 vec[0] = fx + (hlfrand * BLI_drand()) - dblrand;
261                                 vec[1] = fy + (hlfrand * BLI_drand()) - dblrand;
262                                 vec[2] = fz + (hlfrand * BLI_drand()) - dblrand;
263                                 vec[3] = 1.0;
264
265                                 if (vertexfunc) {
266                                         if(done & 1) vertexfunc(vec);
267                                         done++;
268                                 }
269                                 else {
270                                         MTC_Mat4MulVecfl(R.viewmat, vec);
271
272                                         /* in vec are global coordinates
273                                          * calculate distance to camera
274                                          * and using that, define the alpha
275                                          */
276
277                                         {
278                                                 float tx, ty, tz;
279
280                                                 tx = vec[0];
281                                                 ty = vec[1];
282                                                 tz = vec[2];
283
284                                                 alpha = sqrt(tx * tx + ty * ty + tz * tz);
285
286                                                 if (alpha >= clipend) alpha = 0.0;
287                                                 else if (alpha <= starmindist) alpha = 0.0;
288                                                 else if (alpha <= 2.0 * starmindist) {
289                                                         alpha = (alpha - starmindist) / starmindist;
290                                                 } else {
291                                                         alpha -= 2.0 * starmindist;
292                                                         alpha /= (clipend - 2.0 * starmindist);
293                                                         alpha = 1.0 - alpha;
294                                                 }
295                                         }
296
297
298                                         if (alpha != 0.0) {
299                                                 fac = force * BLI_drand();
300
301                                                 har = initstar(vec, fac);
302
303                                                 if (har) {
304                                                         har->alfa = sqrt(sqrt(alpha));
305                                                         har->add= 255;
306                                                         har->r = har->g = har->b = 1.0;
307                                                         if (maxjit) {
308                                                                 har->r += ((maxjit * BLI_drand()) ) - maxjit;
309                                                                 har->g += ((maxjit * BLI_drand()) ) - maxjit;
310                                                                 har->b += ((maxjit * BLI_drand()) ) - maxjit;
311                                                         }
312                                                         har->hard = 32;
313
314                                                         har->type |= HA_ONLYSKY;
315                                                         done++;
316                                                 }
317                                         }
318                                 }
319                         }
320 //                      if(done > MAXVERT) {
321 //                              printf("Too many stars\n");
322 //                              break;
323 //                      }
324                         if(blender_test_break()) break;
325                 }
326 //              if(done > MAXVERT) break;
327
328                 if(blender_test_break()) break;
329         }
330         if (termfunc) termfunc();
331 }
332
333 /* ------------------------------------------------------------------------ */
334 /* more star stuff, here used to be a cliptest, removed for envmap render or panorama... */
335 static HaloRen *initstar(float *vec, float hasize)
336 {
337         HaloRen *har;
338         float hoco[4];
339
340         RE_projectverto(vec, hoco);
341
342         har= RE_findOrAddHalo(R.tothalo++);
343
344         /* projectvert is done in function zbufvlaggen again, because of parts */
345         VECCOPY(har->co, vec);
346         har->hasize= hasize;
347
348         har->zd= 0.0;
349
350         return har;
351 }
352
353
354
355 /* ------------------------------------------------------------------------- */
356
357 #if 0
358 static void split_u_renderfaces(int startvlak, int startvert, int usize, int plek, int cyclu)
359 {
360         VlakRen *vlr;
361         VertRen *v1, *v2;
362         int a, v;
363
364         if(cyclu) cyclu= 1;
365
366         /* first give all involved vertices a pointer to the new one */
367         v= startvert+ plek*usize;
368         for(a=0; a<usize; a++) {
369                 v2= RE_findOrAddVert(R.totvert++);
370                 v1= RE_findOrAddVert(v++);
371                 *v2= *v1;
372                 v1->sticky= (float *)v2;
373         }
374
375         /* check involved faces and replace pointers */
376         v= startvlak+plek*(usize-1+cyclu);
377         for(a=1-cyclu; a<usize; a++) {
378                 vlr= RE_findOrAddVlak(v++);
379                 vlr->v1= (VertRen *)(vlr->v1->sticky);
380                 vlr->v2= (VertRen *)(vlr->v2->sticky);
381         }
382
383 }
384 #endif 
385
386 /* ------------------------------------------------------------------------- */
387
388 static void split_v_renderfaces(int startvlak, int startvert, int usize, int vsize, int plek, int cyclu, int cyclv)
389 {
390         VlakRen *vlr;
391         VertRen *v1=0;
392         int a, vlak, ofs;
393
394         if(vsize<2) return;
395
396         /* check involved faces and create doubles */
397         /* because (evt) split_u already has been done, you cannot work with vertex->sticky pointers */
398         /* because faces do not share vertices anymore */
399
400         if(plek+cyclu==usize) plek= -1;
401
402         vlak= startvlak+(plek+cyclu);
403         ofs= (usize-1+cyclu);
404
405         for(a=1; a<vsize; a++) {
406
407                 vlr= RE_findOrAddVlak(vlak);
408                 if (vlr->v1 == 0) return; /* OOPS, when not cyclic */
409
410                 v1= RE_findOrAddVert(R.totvert++);
411                 *v1= *(vlr->v1);
412
413                 vlr->v1= v1;
414
415                 /* vlr= findOrAddVlak(vlak+1); */
416                 /* vlr->v1= v1; */
417
418                 if(a>1) {
419                         vlr= RE_findOrAddVlak(vlak-ofs);
420                         if(vlr->v4->sticky) {
421                                 v1= RE_findOrAddVert(R.totvert++);
422                                 *v1= *(vlr->v4);
423                                 vlr->v4= v1;
424                         }
425                         else vlr->v4= v1;
426                 }
427
428                 if(a== vsize-1) {
429                         if(cyclv) {
430                                 ;
431                         }
432                         else {
433                                 vlr= RE_findOrAddVlak(vlak);
434                                 v1= RE_findOrAddVert(R.totvert++);
435                                 *v1= *(vlr->v4);
436                                 vlr->v4= v1;
437                         }
438                 }
439
440                 vlak+= ofs;
441         }
442
443 }
444
445 /* ------------------------------------------------------------------------- */
446
447 static int contrpuntnormr(float *n, float *puno)
448 {
449         float inp;
450
451         inp=n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
452         if(inp<0.0) return 1;
453         return 0;
454 }
455
456 /* ------------------------------------------------------------------------- */
457
458 static void calc_vertexnormals(int startvert, int startvlak)
459 {
460         VlakRen *vlr;
461         VertRen *ver, *adrve1, *adrve2, *adrve3, *adrve4;
462         float n1[3], n2[3], n3[3], n4[3], *adrco, *tfl, fac, *temp;
463         int a;
464
465         if(R.totvlak==0 || R.totvert==0) return;
466         if(startvert==R.totvert || startvlak==R.totvlak) return;
467
468         adrco= (float *)MEM_callocN(12+4*sizeof(float)*(R.totvlak-startvlak), "normalen1");
469
470         tfl= adrco;
471         /* calculate cos of angles and point-masses */
472         for(a= startvlak; a<R.totvlak; a++) {
473                 vlr= RE_findOrAddVlak(a);
474                 if(vlr->flag & ME_SMOOTH) {
475                         adrve1= vlr->v1;
476                         adrve2= vlr->v2;
477                         adrve3= vlr->v3;
478                         adrve4= vlr->v4;
479
480                         VecSubf(n1, adrve2->co, adrve1->co);
481                         Normalise(n1);
482                         VecSubf(n2, adrve3->co, adrve2->co);
483                         Normalise(n2);
484                         if(adrve4==0) {
485                                 VecSubf(n3, adrve1->co, adrve3->co);
486                                 Normalise(n3);
487
488                                 *(tfl++)= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
489                                 *(tfl++)= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
490                                 *(tfl++)= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
491                         }
492                         else {
493                                 VecSubf(n3, adrve4->co, adrve3->co);
494                                 Normalise(n3);
495                                 VecSubf(n4, adrve1->co, adrve4->co);
496                                 Normalise(n4);
497
498                                 *(tfl++)= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
499                                 *(tfl++)= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
500                                 *(tfl++)= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
501                                 *(tfl++)= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
502                         }
503                 }
504         }
505
506         /* clear all vertex normals */
507         for(a=startvert; a<R.totvert; a++) {
508                 ver= RE_findOrAddVert(a);
509
510                 ver->n[0]=ver->n[1]=ver->n[2]= 0.0;
511         }
512
513         /* calculate normals and add it to the vertex normals (dutch: punt normaal) */
514         tfl= adrco;
515         for(a=startvlak; a<R.totvlak; a++) {
516                 vlr= RE_findOrAddVlak(a);
517                 
518                 if(vlr->flag & ME_SMOOTH) {
519
520                         adrve1= vlr->v1;
521                         adrve2= vlr->v2;
522                         adrve3= vlr->v3;
523                         adrve4= vlr->v4;
524
525                         temp= adrve1->n;
526                         fac= *(tfl++);
527                         if( vlr->flag & R_NOPUNOFLIP);
528                         else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
529                         *(temp++) +=fac*vlr->n[0];
530                         *(temp++) +=fac*vlr->n[1];
531                         *(temp)   +=fac*vlr->n[2];
532
533                         temp= adrve2->n;
534                         fac= *(tfl++);
535                         if( vlr->flag & R_NOPUNOFLIP);
536                         else  if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
537                         *(temp++) +=fac*vlr->n[0];
538                         *(temp++) +=fac*vlr->n[1];
539                         *(temp)   +=fac*vlr->n[2];
540
541                         temp= adrve3->n;
542                         fac= *(tfl++);
543                         if( vlr->flag & R_NOPUNOFLIP);
544                         else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
545                         *(temp++) +=fac*vlr->n[0];
546                         *(temp++) +=fac*vlr->n[1];
547                         *(temp)   +=fac*vlr->n[2];
548
549                         if(adrve4) {
550                                 temp= adrve4->n;
551                                 fac= *(tfl++);
552                                 if( vlr->flag & R_NOPUNOFLIP);
553                                 else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ;
554                                 *(temp++) +=fac*vlr->n[0];
555                                 *(temp++) +=fac*vlr->n[1];
556                                 *(temp)   +=fac*vlr->n[2];
557                         }
558                 }
559         }
560         /* do solid faces */
561         for(a=startvlak; a<R.totvlak; a++) {
562                 vlr= RE_findOrAddVlak(a);
563                 if((vlr->flag & ME_SMOOTH)==0) {
564                         float *f1= vlr->v1->n;
565                         if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
566                         f1= vlr->v2->n;
567                         if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
568                         f1= vlr->v3->n;
569                         if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
570                         if(vlr->v4) {
571                                 f1= vlr->v4->n;
572                                 if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
573                         }                       
574                 }
575         }
576         
577         /* normalise vertex normals */
578         for(a=startvert; a<R.totvert; a++) {
579                 ver= RE_findOrAddVert(a);
580
581                 Normalise(ver->n);
582         }
583
584         /* vertex normal (puno) switch flags for during render */
585         for(a=startvlak; a<R.totvlak; a++) {
586                 vlr= RE_findOrAddVlak(a);
587
588                 if((vlr->flag & R_NOPUNOFLIP)==0) {
589                         adrve1= vlr->v1;
590                         adrve2= vlr->v2;
591                         adrve3= vlr->v3;
592                         adrve4= vlr->v4;
593         
594                         vlr->puno &= ~15;
595                         fac= vlr->n[0]*adrve1->n[0]+vlr->n[1]*adrve1->n[1]+vlr->n[2]*adrve1->n[2];
596                         if(fac<0.0) vlr->puno= 1;
597                         fac= vlr->n[0]*adrve2->n[0]+vlr->n[1]*adrve2->n[1]+vlr->n[2]*adrve2->n[2];
598                         if(fac<0.0) vlr->puno+= 2;
599                         fac= vlr->n[0]*adrve3->n[0]+vlr->n[1]*adrve3->n[1]+vlr->n[2]*adrve3->n[2];
600                         if(fac<0.0) vlr->puno+= 4;
601         
602                         if(adrve4) {
603                                 fac= vlr->n[0]*adrve4->n[0]+vlr->n[1]*adrve4->n[1]+vlr->n[2]*adrve4->n[2];
604                                 if(fac<0.0) vlr->puno+= 8;
605                         }
606                 }
607         }
608
609         MEM_freeN(adrco);
610 }
611
612 /* ------------------------------------------------------------------------- */
613 /* Autosmoothing:                                                            */
614 /* ------------------------------------------------------------------------- */
615
616 typedef struct ASvert {
617         int totface;
618         ListBase faces;
619 } ASvert;
620
621 typedef struct ASface {
622         struct ASface *next, *prev;
623         VlakRen *vlr[4];
624         VertRen *nver[4];
625 } ASface;
626
627 /* prototypes: */
628 static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh);
629 static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh);
630
631
632 static void as_addvert(VertRen *v1, VlakRen *vlr)
633 {
634         ASvert *asv;
635         ASface *asf;
636         int a;
637         
638         if(v1 == NULL) return;
639         
640         if(v1->svert==0) {
641                 v1->svert= MEM_callocN(sizeof(ASvert), "asvert");
642                 asv= v1->svert;
643                 asf= MEM_callocN(sizeof(ASface), "asface");
644                 BLI_addtail(&asv->faces, asf);
645         }
646         
647         asv= v1->svert;
648         asf= asv->faces.last;
649         for(a=0; a<4; a++) {
650                 if(asf->vlr[a]==0) {
651                         asf->vlr[a]= vlr;
652                         asv->totface++;
653                         break;
654                 }
655         }
656         
657         /* new face struct */
658         if(a==4) {
659                 asf= MEM_callocN(sizeof(ASface), "asface");
660                 BLI_addtail(&asv->faces, asf);
661                 asf->vlr[0]= vlr;
662                 asv->totface++;
663         }
664 }
665
666 static void as_freevert(VertRen *ver)
667 {
668         ASvert *asv;
669
670         asv= ver->svert;
671         BLI_freelistN(&asv->faces);
672         MEM_freeN(asv);
673         ver->svert= NULL;
674 }
675
676 static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh) 
677 {
678         /* return 1: vertex needs a copy */
679         ASface *asf;
680         float inp;
681         int a;
682         
683         if(vlr==0) return 0;
684         
685         asf= asv->faces.first;
686         while(asf) {
687                 for(a=0; a<4; a++) {
688                         if(asf->vlr[a] && asf->vlr[a]!=vlr) {
689                                 inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] );
690                                 if(inp < thresh) return 1;
691                         }
692                 }
693                 asf= asf->next;
694         }
695         
696         return 0;
697 }
698
699 static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh) 
700 {
701         /* return when new vertex already was made */
702         ASface *asf;
703         float inp;
704         int a;
705         
706         asf= asv->faces.first;
707         while(asf) {
708                 for(a=0; a<4; a++) {
709                         if(asf->vlr[a] && asf->vlr[a]!=vlr) {
710                                 /* this face already made a copy for this vertex! */
711                                 if(asf->nver[a]) {
712                                         inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] );
713                                         if(inp >= thresh) {
714                                                 return asf->nver[a];
715                                         }
716                                 }
717                         }
718                 }
719                 asf= asf->next;
720         }
721         
722         return NULL;
723 }
724
725 static void autosmooth(int startvert, int startvlak, int degr)
726 {
727         ASvert *asv;
728         ASface *asf;
729         VertRen *ver, *v1;
730         VlakRen *vlr;
731         float thresh;
732         int a, b, totvert;
733         
734         thresh= cos( M_PI*((float)degr)/180.0 );
735         
736         /* initialize */
737         for(a=startvert; a<R.totvert; a++) {
738                 ver= RE_findOrAddVert(a);
739                 ver->svert= 0;
740         }
741         
742         /* step one: construct listbase of all vertices and pointers to faces */
743         for(a=startvlak; a<R.totvlak; a++) {
744                 vlr= RE_findOrAddVlak(a);
745                 
746                 as_addvert(vlr->v1, vlr);
747                 as_addvert(vlr->v2, vlr);
748                 as_addvert(vlr->v3, vlr);
749                 as_addvert(vlr->v4, vlr);
750         }
751         
752         /* we now test all vertices, when faces have a normal too much different: they get a new vertex */
753         totvert= R.totvert;
754         for(a=startvert; a<totvert; a++) {
755                 ver= RE_findOrAddVert(a);
756                 asv= ver->svert;
757                 if(asv && asv->totface>1) {
758                         
759                         asf= asv->faces.first;
760                         while(asf) {
761                                 for(b=0; b<4; b++) {
762                                 
763                                         /* is there a reason to make a new vertex? */
764                                         vlr= asf->vlr[b];
765                                         if( as_testvertex(vlr, ver, asv, thresh) ) {
766                                                 
767                                                 /* already made a new vertex within threshold? */
768                                                 v1= as_findvertex(vlr, ver, asv, thresh);
769                                                 if(v1==0) {
770                                                         /* make a new vertex */
771                                                         v1= RE_findOrAddVert(R.totvert++);
772                                                         *v1= *ver;
773                                                         v1->svert= 0;
774                                                 }
775                                                 asf->nver[b]= v1;
776                                                 if(vlr->v1==ver) vlr->v1= v1;
777                                                 if(vlr->v2==ver) vlr->v2= v1;
778                                                 if(vlr->v3==ver) vlr->v3= v1;
779                                                 if(vlr->v4==ver) vlr->v4= v1;
780                                         }
781                                 }
782                                 asf= asf->next;
783                         }
784                 }
785         }
786         
787         /* free */
788         for(a=startvert; a<R.totvert; a++) {
789                 ver= RE_findOrAddVert(a);
790                 if(ver->svert) as_freevert(ver);
791         }
792         
793 }
794
795 /* ------------------------------------------------------------------------- */
796 /* End of autosmoothing:                                                     */
797 /* ------------------------------------------------------------------------- */
798
799 static void make_render_halos(Object *ob, Mesh *me, int totvert, MVert *mvert, Material *ma, float *extverts)
800 {
801         HaloRen *har;
802         float xn, yn, zn, nor[3], view[3];
803         float *orco, vec[3], hasize, mat[4][4], imat[3][3];
804         int start, end, a, ok, seed= ma->seed1;
805
806         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
807         MTC_Mat3CpyMat4(imat, ob->imat);
808
809         R.flag |= R_HALO;
810
811         orco= me->orco;
812
813         start= 0;
814         end= totvert;
815         set_buildvars(ob, &start, &end);
816         mvert+= start;
817         if(extverts) extverts+= 3*start;
818
819         for(a=start; a<end; a++, mvert++) {
820                 ok= 1;
821
822                 if(ok) {
823                         hasize= ma->hasize;
824
825                         if(extverts) {
826                                 VECCOPY(vec, extverts);
827                                 extverts+= 3;
828                         }
829                         else {
830                                 VECCOPY(vec, mvert->co);
831                         }
832                         MTC_Mat4MulVecfl(mat, vec);
833
834                         if(ma->mode & MA_HALOPUNO) {
835                                 xn= mvert->no[0];
836                                 yn= mvert->no[1];
837                                 zn= mvert->no[2];
838
839                                 /* transpose ! */
840                                 nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
841                                 nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
842                                 nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
843                                 Normalise(nor);
844
845                                 VECCOPY(view, vec);
846                                 Normalise(view);
847
848                                 zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
849                                 if(zn>=0.0) hasize= 0.0;
850                                 else hasize*= zn*zn*zn*zn;
851                         }
852
853                         if(orco) har= RE_inithalo(ma, vec, NULL, orco, hasize, 0.0, seed);
854                         else har= RE_inithalo(ma, vec, NULL, mvert->co, hasize, 0.0, seed);
855                         if(har) har->lay= ob->lay;
856                 }
857                 if(orco) orco+= 3;
858                 seed++;
859         }
860 }
861
862 /* ------------------------------------------------------------------------- */
863
864
865 static void render_particle_system(Object *ob, PartEff *paf)
866 {
867         Particle *pa=0;
868         HaloRen *har=0;
869         Material *ma=0;
870         float xn, yn, zn, imat[3][3], mat[4][4], hasize, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
871         int a, mat_nr=1, seed;
872
873         pa= paf->keys;
874         if(pa==NULL) {
875                 build_particle_system(ob);
876                 pa= paf->keys;
877                 if(pa==NULL) return;
878         }
879
880         ma= give_render_material(ob, 1);
881
882         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
883         MTC_Mat4Invert(ob->imat, mat);  /* this is correct, for imat texture */
884
885         MTC_Mat4Invert(mat, R.viewmat); /* particles do not have a ob transform anymore */
886         MTC_Mat3CpyMat4(imat, mat);
887
888         R.flag |= R_HALO;
889
890         if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
891         else ptime= 0.0;
892         ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, ptime);
893         seed= ma->seed1;
894
895         for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
896
897                 if(ctime > pa->time) {
898                         if(ctime < pa->time+pa->lifetime) {
899
900                                 /* watch it: also calculate the normal of a particle */
901                                 if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
902                                         where_is_particle(paf, pa, ctime, vec);
903                                         MTC_Mat4MulVecfl(R.viewmat, vec);
904                                         where_is_particle(paf, pa, ctime+1.0, vec1);
905                                         MTC_Mat4MulVecfl(R.viewmat, vec1);
906                                 }
907                                 else {
908                                         where_is_particle(paf, pa, ctime, vec);
909                                         MTC_Mat4MulVecfl(R.viewmat, vec);
910                                 }
911
912                                 if(pa->mat_nr != mat_nr) {
913                                         mat_nr= pa->mat_nr;
914                                         ma= give_render_material(ob, mat_nr);
915                                 }
916
917                                 if(ma->ipo) {
918                                         /* correction for lifetime */
919                                         ptime= 100.0*(ctime-pa->time)/pa->lifetime;
920                                         calc_ipo(ma->ipo, ptime);
921                                         execute_ipo((ID *)ma, ma->ipo);
922                                 }
923
924                                 hasize= ma->hasize;
925
926                                 if(ma->mode & MA_HALOPUNO) {
927                                         xn= pa->no[0];
928                                         yn= pa->no[1];
929                                         zn= pa->no[2];
930
931                                         /* transpose ! */
932                                         nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
933                                         nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
934                                         nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
935                                         Normalise(nor);
936
937                                         VECCOPY(view, vec);
938                                         Normalise(view);
939
940                                         zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
941                                         if(zn>=0.0) hasize= 0.0;
942                                         else hasize*= zn*zn*zn*zn;
943                                 }
944
945                                 if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
946                                 else {
947                                         har= RE_inithalo(ma, vec, NULL, pa->co, hasize, 0.0, seed);
948                                         if(har && ma->mode & MA_HALO_SHADE) {
949                                                 VecSubf(har->no, vec, vec1);
950                                                 Normalise(har->no);
951                                         }
952                                 }
953                                 if(har) har->lay= ob->lay;
954                         }
955                 }
956                 seed++;
957         }
958
959         /* restore material */
960         for(a=1; a<=ob->totcol; a++) {
961                 ma= give_render_material(ob, a);
962                 if(ma) do_mat_ipo(ma);
963         }
964         
965 }
966
967
968 /* ------------------------------------------------------------------------- */
969
970 /* when objects are duplicated, they are freed immediate, but still might be
971 in use for render... */
972 static Object *vlr_set_ob(Object *ob)
973 {
974         if(ob->flag & OB_FROMDUPLI) return (Object *)ob->id.newid;
975         return ob;
976 }
977
978 static void render_static_particle_system(Object *ob, PartEff *paf)
979 {
980         Particle *pa=0;
981         HaloRen *har=0;
982         Material *ma=0;
983         VertRen *v1= NULL;
984         VlakRen *vlr;
985         float xn, yn, zn, imat[3][3], mat[4][4], hasize;
986         float mtime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
987         int a, mat_nr=1, seed;
988
989         pa= paf->keys;
990         if(pa==NULL || (paf->flag & PAF_ANIMATED)) {
991                 build_particle_system(ob);
992                 pa= paf->keys;
993                 if(pa==NULL) return;
994         }
995
996         ma= give_render_material(ob, 1);
997
998         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
999         MTC_Mat4Invert(ob->imat, mat);  /* need to be that way, for imat texture */
1000
1001         MTC_Mat3CpyMat4(imat, ob->imat);
1002
1003         R.flag |= R_HALO;
1004
1005         if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
1006         else ptime= 0.0;
1007         ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, ptime);
1008         seed= ma->seed1;
1009
1010         for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
1011
1012                 where_is_particle(paf, pa, pa->time, vec1);
1013                 MTC_Mat4MulVecfl(mat, vec1);
1014                 
1015                 mtime= pa->time+pa->lifetime+paf->staticstep-1;
1016                 
1017                 for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
1018                         
1019                         /* make sure hair grows until the end.. */
1020                         if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
1021                         
1022                         /* watch it: also calc the normal of a particle */
1023                         if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
1024                                 where_is_particle(paf, pa, ctime+1.0, vec);
1025                                 MTC_Mat4MulVecfl(mat, vec);
1026                         }
1027                         else {
1028                                 where_is_particle(paf, pa, ctime, vec);
1029                                 MTC_Mat4MulVecfl(mat, vec);
1030                         }
1031
1032                         if(pa->mat_nr != mat_nr) {
1033                                 mat_nr= pa->mat_nr;
1034                                 ma= give_render_material(ob, mat_nr);
1035                         }
1036
1037                         if(ma->mode & MA_WIRE) {
1038                                 if(ctime == pa->time) {
1039                                         v1= RE_findOrAddVert(R.totvert++);
1040                                         VECCOPY(v1->co, vec);
1041                                 }
1042                                 else {
1043 //                                      float cvec[3]={-1.0, 0.0, 0.0};
1044                                         
1045                                         vlr= RE_findOrAddVlak(R.totvlak++);
1046                                         vlr->ob= vlr_set_ob(ob);
1047                                         vlr->v1= v1;
1048                                         vlr->v2= RE_findOrAddVert(R.totvert++);
1049                                         vlr->v3= vlr->v2;
1050                                         vlr->v4= NULL;
1051                                         
1052                                         v1= vlr->v2; // cycle
1053                                         VECCOPY(v1->co, vec);
1054                                         
1055                                         VecSubf(vlr->n, vec, vec1);
1056                                         Normalise(vlr->n);
1057                                         VECCOPY(v1->n, vlr->n);
1058                                         
1059                                         vlr->mat= ma;
1060                                         vlr->ec= ME_V1V2;
1061                                         vlr->lay= ob->lay;
1062                                 }
1063                         }
1064                         else {
1065                                 if(ma->ipo) {
1066                                         /* correction for lifetime */
1067                                         ptime= 100.0*(ctime-pa->time)/pa->lifetime;
1068                                         calc_ipo(ma->ipo, ptime);
1069                                         execute_ipo((ID *)ma, ma->ipo);
1070                                 }
1071
1072                                 hasize= ma->hasize;
1073
1074                                 if(ma->mode & MA_HALOPUNO) {
1075                                         xn= pa->no[0];
1076                                         yn= pa->no[1];
1077                                         zn= pa->no[2];
1078
1079                                         /* transpose ! */
1080                                         nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1081                                         nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1082                                         nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1083                                         Normalise(nor);
1084
1085                                         VECCOPY(view, vec);
1086                                         Normalise(view);
1087
1088                                         zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
1089                                         if(zn>=0.0) hasize= 0.0;
1090                                         else hasize*= zn*zn*zn*zn;
1091                                 }
1092
1093                                 if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
1094                                 else {
1095                                         har= RE_inithalo(ma, vec, NULL, pa->co, hasize, 0.0, seed);
1096                                         if(har && (ma->mode & MA_HALO_SHADE)) {
1097                                                 VecSubf(har->no, vec, vec1);
1098                                                 Normalise(har->no);
1099                                                 har->lay= ob->lay;
1100                                         }
1101                                 }
1102                                 if(har) har->lay= ob->lay;
1103                         }
1104                         
1105                         VECCOPY(vec1, vec);
1106                 }
1107                 seed++;
1108         }
1109
1110 }
1111
1112
1113 /* ------------------------------------------------------------------------- */
1114
1115 static int verghalo(const void *a1, const void *a2)
1116 {
1117         const struct halosort *x1=a1, *x2=a2;
1118         
1119         if( x1->z < x2->z ) return 1;
1120         else if( x1->z > x2->z) return -1;
1121         return 0;
1122 }
1123
1124 /* ------------------------------------------------------------------------- */
1125 extern int rblohalen;
1126 static void sort_halos(void)
1127 {
1128         struct halosort *hablock, *haso;
1129         HaloRen *har = NULL, **bloha;
1130         int a;
1131
1132         if(R.tothalo==0) return;
1133
1134         /* make datablock with halo pointers, sort */
1135         haso= hablock= MEM_mallocN(sizeof(struct halosort)*R.tothalo, "hablock");
1136
1137         for(a=0; a<R.tothalo; a++) {
1138                 if((a & 255)==0) har= R.bloha[a>>8];
1139                 else har++;
1140                 haso->har= har;
1141                 haso->z= har->zs;
1142                 haso++;
1143         }
1144
1145         qsort(hablock, R.tothalo, sizeof(struct halosort), verghalo);
1146
1147         /* re-assamble R.bloha */
1148
1149         bloha= R.bloha;
1150         R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(rblohalen),"Bloha");
1151
1152         haso= hablock;
1153         for(a=0; a<R.tothalo; a++) {
1154                 har= RE_findOrAddHalo(a);
1155                 *har= *(haso->har);
1156
1157                 haso++;
1158         }
1159
1160         /* free */
1161         a= 0;
1162         while(bloha[a]) {
1163                 MEM_freeN(bloha[a]);
1164                 a++;
1165         }
1166         MEM_freeN(bloha);
1167         MEM_freeN(hablock);
1168
1169 }
1170
1171
1172
1173 static Material *give_render_material(Object *ob, int nr)
1174 {
1175         extern Material defmaterial;    // initrender.c
1176         Object *temp;
1177         Material *ma;
1178
1179         if(ob->flag & OB_FROMDUPLI) {
1180                 temp= (Object *)ob->id.newid;
1181                 if(temp && temp->type==OB_FONT) {
1182                         ob= temp;
1183                 }
1184         }
1185
1186         ma= give_current_material(ob, nr);
1187         if(ma==NULL) ma= &defmaterial;
1188         
1189         return ma;
1190 }
1191
1192 /* ------------------------------------------------------------------------- */
1193 static void init_render_mball(Object *ob)
1194 {
1195         DispList *dl, *dlo;
1196         VertRen *ver;
1197         VlakRen *vlr, *vlr1;
1198         Material *ma;
1199         float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn;
1200         int a, need_orco, startvert, *index;
1201
1202         if (ob!=find_basis_mball(ob))
1203                 return;
1204
1205         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
1206         MTC_Mat4Invert(ob->imat, mat);
1207         MTC_Mat3CpyMat4(imat, ob->imat);
1208
1209         ma= give_render_material(ob, 1);
1210
1211         need_orco= 0;
1212         if(ma->texco & TEXCO_ORCO) {
1213                 need_orco= 1;
1214         }
1215
1216         dlo= ob->disp.first;
1217         if(dlo) BLI_remlink(&ob->disp, dlo);
1218
1219         makeDispList(ob);
1220         dl= ob->disp.first;
1221         if(dl==0) return;
1222
1223         startvert= R.totvert;
1224         data= dl->verts;
1225         nors= dl->nors;
1226
1227         for(a=0; a<dl->nr; a++, data+=3, nors+=3) {
1228
1229                 ver= RE_findOrAddVert(R.totvert++);
1230                 VECCOPY(ver->co, data);
1231                 MTC_Mat4MulVecfl(mat, ver->co);
1232
1233                 xn= nors[0];
1234                 yn= nors[1];
1235                 zn= nors[2];
1236
1237                 /* transpose ! */
1238                 ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1239                 ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1240                 ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1241                 Normalise(ver->n);
1242                 //if(ob->transflag & OB_NEG_SCALE) VecMulf(ver->n. -1.0);
1243                 
1244                 if(need_orco) ver->orco= data;
1245         }
1246
1247         index= dl->index;
1248         for(a=0; a<dl->parts; a++, index+=4) {
1249
1250                 vlr= RE_findOrAddVlak(R.totvlak++);
1251                 vlr->ob= vlr_set_ob(ob);
1252                 vlr->v1= RE_findOrAddVert(startvert+index[0]);
1253                 vlr->v2= RE_findOrAddVert(startvert+index[1]);
1254                 vlr->v3= RE_findOrAddVert(startvert+index[2]);
1255                 vlr->v4= 0;
1256
1257                 if(ob->transflag & OB_NEG_SCALE) 
1258                         CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
1259                 else
1260                         CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
1261
1262                 vlr->mat= ma;
1263                 vlr->flag= ME_SMOOTH+R_NOPUNOFLIP;
1264                 vlr->ec= 0;
1265                 vlr->lay= ob->lay;
1266
1267                 /* mball -too bad- always has triangles, because quads can be non-planar */
1268                 if(index[3]) {
1269                         vlr1= RE_findOrAddVlak(R.totvlak++);
1270                         *vlr1= *vlr;
1271                         vlr1->v2= vlr1->v3;
1272                         vlr1->v3= RE_findOrAddVert(startvert+index[3]);
1273                         if(ob->transflag & OB_NEG_SCALE) 
1274                                 CalcNormFloat(vlr1->v1->co, vlr1->v2->co, vlr1->v3->co, vlr1->n);
1275                         else
1276                                 CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n);
1277                 }
1278         }
1279
1280         if(need_orco) {
1281                 /* store displist and scale */
1282                 make_orco_mball(ob);
1283                 if(dlo) BLI_addhead(&ob->disp, dlo);
1284
1285         }
1286         else {
1287                 freedisplist(&ob->disp);
1288                 if(dlo) BLI_addtail(&ob->disp, dlo);
1289         }
1290 }
1291 /* ------------------------------------------------------------------------- */
1292 /* convert */
1293 static void init_render_mesh(Object *ob)
1294 {
1295         Mesh *me;
1296         MVert *mvert = NULL;
1297         MFace *mface;
1298         VlakRen *vlr; //, *vlr1;
1299         VertRen *ver;
1300         Material *ma;
1301         MSticky *ms = NULL;
1302         PartEff *paf;
1303         unsigned int *vertcol;
1304         float xn, yn, zn,  imat[3][3], mat[4][4];  //nor[3],
1305         float *extverts=0, *orco;
1306         int a, a1, ok, do_puno, need_orco=0, totvlako, totverto, vertofs;
1307         int start, end, do_autosmooth=0, totvert = 0;
1308         DispListMesh *dlm = NULL;
1309
1310         me= ob->data;
1311
1312         paf = give_parteff(ob);
1313         if(paf) {
1314                 /* warning; build_particle_system does modifier calls itself */
1315                 if(paf->flag & PAF_STATIC) render_static_particle_system(ob, paf);
1316                 else render_particle_system(ob, paf);
1317                 return;
1318         }
1319
1320         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
1321         MTC_Mat4Invert(ob->imat, mat);
1322         MTC_Mat3CpyMat4(imat, ob->imat);
1323
1324         if(me->totvert==0) {
1325                 return;
1326         }
1327         
1328         totvlako= R.totvlak;
1329         totverto= R.totvert;
1330
1331         if(me->key) do_puno= 1;
1332
1333         if(me->orco==0) {
1334                 need_orco= 0;
1335                 for(a=1; a<=ob->totcol; a++) {
1336                         ma= give_render_material(ob, a);
1337                         if(ma) {
1338                                 if(ma->texco & TEXCO_ORCO) {
1339                                         need_orco= 1;
1340                                         break;
1341                                 }
1342                         }
1343                 }
1344         }
1345         
1346         /* we do this before deform */
1347         if(need_orco) {
1348                 if ((me->flag&ME_SUBSURF) && me->subdivr) 
1349                         make_orco_displist_mesh(ob, me->subdivr);
1350                 else
1351                         make_orco_mesh(me);
1352         }                       
1353         
1354         /* after orco, because this changes mesh vertices (too) */
1355         do_puno= mesh_modifier(ob, 's');
1356         
1357         if ((me->flag&ME_SUBSURF) && me->subdivr) {
1358                 int needsFree;
1359                 DerivedMesh *dm = mesh_get_derived_render(ob, &needsFree);
1360                 dlm = dm->convertToDispListMesh(dm);
1361                 if (needsFree) {
1362                         dm->release(dm);
1363                 }
1364
1365                 mvert= dlm->mvert;
1366                 totvert= dlm->totvert;
1367
1368                 ms= NULL; // no stick in displistmesh
1369         } else {
1370                 DispList *dl;
1371
1372                 dlm= NULL;
1373                 mvert= me->mvert;
1374                 totvert= me->totvert;
1375
1376                 dl= find_displist(&ob->disp, DL_VERTS);
1377                 if(dl) extverts= dl->verts;
1378         
1379                 ms= me->msticky;
1380         }
1381         
1382         orco= me->orco;
1383
1384         ma= give_render_material(ob, 1);
1385
1386         if(ma->mode & MA_HALO) {
1387                 make_render_halos(ob, me, totvert, mvert, ma, extverts);
1388         }
1389         else {
1390
1391                 for(a=0; a<totvert; a++, mvert++) {
1392
1393                         ver= RE_findOrAddVert(R.totvert++);
1394                         if(extverts) {
1395                                 VECCOPY(ver->co, extverts);
1396                                 extverts+= 3;
1397                         }
1398                         else {
1399                                 VECCOPY(ver->co, mvert->co);
1400                         }
1401                         MTC_Mat4MulVecfl(mat, ver->co);
1402
1403                         xn= mvert->no[0];
1404                         yn= mvert->no[1];
1405                         zn= mvert->no[2];
1406                         if(do_puno==0) {
1407                                 /* transpose ! */
1408                                 ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1409                                 ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1410                                 ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1411                                 Normalise(ver->n);
1412                         }
1413                         if(orco) {
1414                                 ver->orco= orco;
1415                                 orco+=3;
1416                         }
1417                         if(ms) {
1418                                 ver->sticky= (float *)ms;
1419                                 ms++;
1420                         }
1421                 }
1422                 /* still to do for keys: the correct local texture coordinate */
1423
1424                 /* faces in order of color blocks */
1425                 vertofs= R.totvert - totvert;
1426                 for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
1427
1428                         ma= give_render_material(ob, a1+1);
1429                         
1430                         /* test for 100% transparant */
1431                         ok= 1;
1432                         if(ma->alpha==0.0 && ma->spectra==0.0) {
1433                                 ok= 0;
1434                                 /* texture on transparency? */
1435                                 for(a=0; a<MAX_MTEX; a++) {
1436                                         if(ma->mtex[a] && ma->mtex[a]->tex) {
1437                                                 if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1;
1438                                         }
1439                                 }
1440                         }
1441                         
1442                         /* if wire material, and we got edges, don't do the faces */
1443                         if(ma->mode & MA_WIRE) {
1444                                 end= dlm?dlm->totedge:me->totedge;
1445                                 if(end) ok= 0;
1446                         }
1447
1448                         if(ok) {
1449                                 TFace *tface= NULL;
1450
1451                                 /* radio faces need autosmooth, to separate shared vertices in corners */
1452                                 if(R.r.mode & R_RADIO)
1453                                         if(ma->mode & MA_RADIO) 
1454                                                 do_autosmooth= 1;
1455                                 
1456                                 start= 0;
1457                                 end= dlm?dlm->totface:me->totface;
1458                                 set_buildvars(ob, &start, &end);
1459                                 if (dlm) {
1460                                         mface= dlm->mface + start;
1461                                         if (dlm->tface) {
1462                                                 tface= dlm->tface + start;
1463                                                 vertcol= NULL;
1464                                         } else if (dlm->mcol) {
1465                                                 vertcol= (unsigned int *)dlm->mcol;
1466                                         } else {
1467                                                 vertcol= NULL;
1468                                         }
1469                                 } else {
1470                                         mface= ((MFace*) me->mface) + start;
1471                                         if (me->tface) {
1472                                                 tface= ((TFace*) me->tface) + start;
1473                                                 vertcol= NULL;
1474                                         } else if (me->mcol) {
1475                                                 vertcol= (unsigned int *)me->mcol;
1476                                         } else {
1477                                                 vertcol= NULL;
1478                                         }
1479                                 }
1480
1481                                 for(a=start; a<end; a++) {
1482                                         int v1, v2, v3, v4, edcode, flag;
1483                                         
1484                                         if( mface->mat_nr==a1 ) {
1485                                                 v1= mface->v1;
1486                                                 v2= mface->v2;
1487                                                 v3= mface->v3;
1488                                                 v4= mface->v4;
1489                                                 flag= mface->flag;
1490                                                 edcode= mface->edcode;
1491                                                 
1492                                                 if(v3) {
1493                                                         float len;
1494                                                         
1495                                                         vlr= RE_findOrAddVlak(R.totvlak++);
1496                                                         vlr->ob= vlr_set_ob(ob);
1497                                                         vlr->v1= RE_findOrAddVert(vertofs+v1);
1498                                                         vlr->v2= RE_findOrAddVert(vertofs+v2);
1499                                                         vlr->v3= RE_findOrAddVert(vertofs+v3);
1500                                                         if(v4) vlr->v4= RE_findOrAddVert(vertofs+v4);
1501                                                         else vlr->v4= 0;
1502
1503                                                         /* render normals are inverted in render */
1504                                                         if(vlr->v4) len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co,
1505                                                             vlr->v1->co, vlr->n);
1506                                                         else len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co,
1507                                                             vlr->n);
1508
1509                                                         vlr->mat= ma;
1510                                                         vlr->flag= flag;
1511                                                         if((me->flag & ME_NOPUNOFLIP) ) {
1512                                                                 vlr->flag |= R_NOPUNOFLIP;
1513                                                         }
1514                                                         vlr->ec= edcode;
1515                                                         vlr->lay= ob->lay;
1516
1517                                                         if(len==0) R.totvlak--;
1518                                                         else {
1519                                                                 if(dlm) {
1520                                                                         if(tface) {
1521                                                                                 vlr->tface= BLI_memarena_alloc(R.memArena, sizeof(*vlr->tface));
1522                                                                                 vlr->vcol= vlr->tface->col;
1523                                                                                 memcpy(vlr->tface, tface, sizeof(*tface));
1524                                                                         } 
1525                                                                         else if (vertcol) {
1526                                                                                 vlr->vcol= BLI_memarena_alloc(R.memArena, sizeof(int)*16);
1527                                                                                 memcpy(vlr->vcol, vertcol+4*a, sizeof(int)*16);
1528                                                                         }
1529                                                                 } else {
1530                                                                         if(tface) {
1531                                                                                 vlr->vcol= tface->col;
1532                                                                                 vlr->tface= tface;
1533                                                                         } 
1534                                                                         else if (vertcol) {
1535                                                                                 vlr->vcol= vertcol+4*a;
1536                                                                         }
1537                                                                 }
1538                                                         }
1539                                                 }
1540                                                 else if(v2 && (ma->mode & MA_WIRE)) {
1541                                                         vlr= RE_findOrAddVlak(R.totvlak++);
1542                                                         vlr->ob= vlr_set_ob(ob);
1543                                                         vlr->v1= RE_findOrAddVert(vertofs+v1);
1544                                                         vlr->v2= RE_findOrAddVert(vertofs+v2);
1545                                                         vlr->v3= vlr->v2;
1546                                                         vlr->v4= 0;
1547
1548                                                         vlr->n[0]=vlr->n[1]=vlr->n[2]= 0.0;
1549
1550                                                         vlr->mat= ma;
1551                                                         vlr->flag= flag;
1552                                                         vlr->ec= ME_V1V2;
1553                                                         vlr->lay= ob->lay;
1554                                                 }
1555                                         }
1556
1557                                         mface++;
1558                                         if(tface) tface++;
1559                                 }
1560                         }
1561                 }
1562                 
1563                 /* exception... we do edges for wire mode. potential conflict when faces exist... */
1564                 end= dlm?dlm->totedge:me->totedge;
1565                 mvert= dlm?dlm->mvert:me->mvert;
1566                 ma= give_render_material(ob, 1);
1567                 if(end && (ma->mode & MA_WIRE)) {
1568                         MEdge *medge;
1569                         medge= dlm?dlm->medge:me->medge;
1570                         
1571                         for(a1=0; a1<end; a1++, medge++) {
1572                                 
1573                                 if( (me->flag & ME_OPT_EDGES)==0 || (medge->flag & ME_EDGEDRAW)) {
1574                                         MVert *v0 = &mvert[medge->v1];
1575                                         MVert *v1 = &mvert[medge->v2];
1576
1577                                         vlr= RE_findOrAddVlak(R.totvlak++);
1578                                         vlr->ob= vlr_set_ob(ob);
1579                                         vlr->v1= RE_findOrAddVert(vertofs+medge->v1);
1580                                         vlr->v2= RE_findOrAddVert(vertofs+medge->v2);
1581                                         vlr->v3= vlr->v2;
1582                                         vlr->v4= NULL;
1583                                         
1584                                         xn= (v0->no[0]+v1->no[0]);
1585                                         yn= (v0->no[1]+v1->no[1]);
1586                                         zn= (v0->no[2]+v1->no[2]);
1587                                         if(do_puno==0) {
1588                                                 /* transpose ! */
1589                                                 vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1590                                                 vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1591                                                 vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1592                                                 Normalise(vlr->n);
1593                                         }
1594                                         
1595                                         vlr->mat= ma;
1596                                         vlr->flag= 0;
1597                                         vlr->ec= ME_V1V2;
1598                                         vlr->lay= ob->lay;
1599                                 }
1600                         }
1601                 }
1602         }
1603         
1604         if(do_puno) {
1605                 calc_vertexnormals(totverto, totvlako);
1606                 do_puno= 0;
1607         }
1608         
1609         if (test_for_displace( ob ) ) 
1610                 do_displacement(ob, totvlako, R.totvlak-totvlako, totverto, R.totvert-totverto);
1611
1612         if(do_autosmooth || (me->flag & ME_AUTOSMOOTH)) {
1613                 autosmooth(totverto, totvlako, me->smoothresh);
1614                 do_puno= 1;
1615         }
1616         
1617         if(do_puno) calc_vertexnormals(totverto, totvlako);
1618         
1619         mesh_modifier(ob, 'e');  // end
1620
1621         if(dlm) displistmesh_free(dlm);
1622 }
1623
1624 /* ------------------------------------------------------------------------- */
1625
1626 static void area_lamp_vectors(LampRen *lar)
1627 {
1628         float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey;
1629
1630         /* corner vectors */
1631         lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
1632         lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
1633         lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
1634
1635         /* corner vectors */
1636         lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
1637         lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
1638         lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
1639
1640         /* corner vectors */
1641         lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
1642         lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
1643         lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
1644
1645         /* corner vectors */
1646         lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
1647         lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
1648         lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
1649         /* only for correction button size, matrix size works on energy */
1650         lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
1651 }
1652
1653 /* If lar takes more lamp data, the decoupling will be better. */
1654 void RE_add_render_lamp(Object *ob, int doshadbuf)
1655 {
1656         Lamp *la;
1657         LampRen *lar, **temp;
1658         float mat[4][4], hoek, xn, yn;
1659         int c;
1660         static int rlalen=LAMPINITSIZE; /*number of currently allocated lampren pointers*/
1661         
1662         if(R.totlamp>=rlalen) { /* Need more Lamp pointers....*/
1663                 printf("Alocating %i more lamp groups, %i total.\n", 
1664                         LAMPINITSIZE, rlalen+LAMPINITSIZE);
1665                 temp=R.la;
1666                 R.la=(LampRen**)MEM_callocN(sizeof(void*)*(rlalen+LAMPINITSIZE) , "renderlamparray");
1667                 memcpy(R.la, temp, rlalen*sizeof(void*));
1668                 memset(&(R.la[R.totlamp]), 0, LAMPINITSIZE*sizeof(void*));
1669                 rlalen+=LAMPINITSIZE;  
1670                 MEM_freeN(temp);        
1671         }
1672         
1673         la= ob->data;
1674         lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
1675         R.la[R.totlamp++]= lar;
1676
1677         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
1678         MTC_Mat4Invert(ob->imat, mat);
1679
1680         MTC_Mat3CpyMat4(lar->mat, mat);
1681         MTC_Mat3CpyMat4(lar->imat, ob->imat);
1682
1683         lar->bufsize = la->bufsize;
1684         lar->samp = la->samp;
1685         lar->soft = la->soft;
1686         lar->shadhalostep = la->shadhalostep;
1687         lar->clipsta = la->clipsta;
1688         lar->clipend = la->clipend;
1689         lar->bias = la->bias;
1690
1691         lar->type= la->type;
1692         lar->mode= la->mode;
1693
1694         lar->energy= la->energy;
1695         lar->energy= la->energy;
1696         if(la->mode & LA_NEG) lar->energy= -lar->energy;
1697
1698         lar->vec[0]= -mat[2][0];
1699         lar->vec[1]= -mat[2][1];
1700         lar->vec[2]= -mat[2][2];
1701         Normalise(lar->vec);
1702         lar->co[0]= mat[3][0];
1703         lar->co[1]= mat[3][1];
1704         lar->co[2]= mat[3][2];
1705         lar->dist= la->dist;
1706         lar->haint= la->haint;
1707         lar->distkw= lar->dist*lar->dist;
1708         lar->r= lar->energy*la->r;
1709         lar->g= lar->energy*la->g;
1710         lar->b= lar->energy*la->b;
1711         lar->k= la->k;
1712
1713         // area
1714         lar->ray_samp= la->ray_samp;
1715         lar->ray_sampy= la->ray_sampy;
1716         lar->ray_sampz= la->ray_sampz;
1717
1718         lar->area_size= la->area_size;
1719         lar->area_sizey= la->area_sizey;
1720         lar->area_sizez= la->area_sizez;
1721
1722         lar->area_shape= la->area_shape;
1723         lar->ray_samp_type= la->ray_samp_type;
1724
1725         if(lar->type==LA_AREA) {
1726                 switch(lar->area_shape) {
1727                 case LA_AREA_SQUARE:
1728                         lar->ray_totsamp= lar->ray_samp*lar->ray_samp;
1729                         lar->ray_sampy= lar->ray_samp;
1730                         lar->area_sizey= lar->area_size;
1731                         break;
1732                 case LA_AREA_RECT:
1733                         lar->ray_totsamp= lar->ray_samp*lar->ray_sampy;
1734                         break;
1735                 case LA_AREA_CUBE:
1736                         lar->ray_totsamp= lar->ray_samp*lar->ray_samp*lar->ray_samp;
1737                         lar->ray_sampy= lar->ray_samp;
1738                         lar->ray_sampz= lar->ray_samp;
1739                         lar->area_sizey= lar->area_size;
1740                         lar->area_sizez= lar->area_size;
1741                         break;
1742                 case LA_AREA_BOX:
1743                         lar->ray_totsamp= lar->ray_samp*lar->ray_sampy*lar->ray_sampz;
1744                         break;
1745                 }
1746
1747                 area_lamp_vectors(lar);
1748         }
1749         else lar->ray_totsamp= 0;
1750         
1751         /* yafray: photonlight and other params */
1752         if (R.r.renderer==R_YAFRAY) {
1753                 lar->YF_numphotons = la->YF_numphotons;
1754                 lar->YF_numsearch = la->YF_numsearch;
1755                 lar->YF_phdepth = la->YF_phdepth;
1756                 lar->YF_useqmc = la->YF_useqmc;
1757                 lar->YF_causticblur = la->YF_causticblur;
1758                 lar->YF_ltradius = la->YF_ltradius;
1759                 lar->YF_bufsize = la->YF_bufsize;
1760                 lar->YF_glowint = la->YF_glowint;
1761                 lar->YF_glowofs = la->YF_glowofs;
1762                 lar->YF_glowtype = la->YF_glowtype;
1763         }
1764
1765         lar->spotsi= la->spotsize;
1766         if(lar->mode & LA_HALO) {
1767                 if(lar->spotsi>170.0) lar->spotsi= 170.0;
1768         }
1769         lar->spotsi= cos( M_PI*lar->spotsi/360.0 );
1770         lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
1771
1772         memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *));
1773
1774         lar->lay= ob->lay & 0xFFFFFF;   // higher 8 bits are localview layers
1775
1776         lar->ld1= la->att1;
1777         lar->ld2= la->att2;
1778
1779         if(lar->type==LA_SPOT) {
1780
1781                 Normalise(lar->imat[0]);
1782                 Normalise(lar->imat[1]);
1783                 Normalise(lar->imat[2]);
1784
1785                 xn= saacos(lar->spotsi);
1786                 xn= sin(xn)/cos(xn);
1787                 lar->spottexfac= 1.0/(xn);
1788
1789                 if(lar->mode & LA_ONLYSHADOW) {
1790                         if((lar->mode & (LA_SHAD|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW;
1791                 }
1792
1793         }
1794
1795         /* set flag for spothalo en initvars */
1796         if(la->type==LA_SPOT && (la->mode & LA_HALO)) {
1797                 if(la->haint>0.0) {
1798                         R.flag |= R_LAMPHALO;
1799
1800                         /* camera position (0,0,0) rotate around lamp */
1801                         lar->sh_invcampos[0]= -lar->co[0];
1802                         lar->sh_invcampos[1]= -lar->co[1];
1803                         lar->sh_invcampos[2]= -lar->co[2];
1804                         MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
1805
1806                         /* z factor, for a normalized volume */
1807                         hoek= saacos(lar->spotsi);
1808                         xn= lar->spotsi;
1809                         yn= sin(hoek);
1810                         lar->sh_zfac= yn/xn;
1811                         /* pre-scale */
1812                         lar->sh_invcampos[2]*= lar->sh_zfac;
1813
1814                 }
1815         }
1816
1817         for(c=0; c<MAX_MTEX; c++) {
1818                 if(la->mtex[c] && la->mtex[c]->tex) {
1819                         lar->mode |= LA_TEXTURE;
1820
1821                         if(R.flag & R_RENDERING) {
1822                                 if(R.osa) {
1823                                         if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX;
1824                                 }
1825                         }
1826                 }
1827         }
1828
1829         /* yafray: shadowbuffers only needed for internal render */
1830         if (R.r.renderer==R_INTERN)
1831         {
1832                 if( (R.r.mode & R_SHADOW) && (lar->mode & LA_SHAD) && (la->type==LA_SPOT) && doshadbuf ) {
1833                 /* Per lamp, one shadow buffer is made. */
1834                         RE_initshadowbuf(lar, ob->obmat);
1835                 }
1836         }
1837         
1838         /* yafray: shadow flag should not be cleared, only used with internal renderer */
1839         if (R.r.renderer==R_INTERN) {
1840                 /* to make sure we can check ray shadow easily in the render code */
1841                 if(lar->mode & LA_SHAD_RAY) {
1842                         if( (R.r.mode & R_RAYTRACE)==0)
1843                                 lar->mode &= ~LA_SHAD_RAY;
1844                 }
1845         }
1846 }
1847
1848 /* ------------------------------------------------------------------------- */
1849 static void init_render_surf(Object *ob)
1850 {
1851         extern Material defmaterial;    // initrender.c
1852         Nurb *nu=0;
1853         Curve *cu;
1854         ListBase displist;
1855         DispList *dl;
1856         VertRen *ver, *v1, *v2, *v3, *v4;
1857         VlakRen *vlr;
1858         Material *matar[32];
1859         float *data, *fp, *orco, n1[3], flen, mat[4][4];
1860         int len, a, need_orco=0, startvlak, startvert, p1, p2, p3, p4;
1861 #ifdef STRUBI
1862         int u, v;
1863         int sizeu, sizev;
1864         VlakRen *vlr1, *vlr2, *vlr3;
1865         float  vn[3]; // n2[3],
1866 #endif
1867
1868         cu= ob->data;
1869         nu= cu->nurb.first;
1870         if(nu==0) return;
1871
1872         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
1873         MTC_Mat4Invert(ob->imat, mat);
1874
1875         /* material array */
1876         memset(matar, 0, 4*32);
1877         matar[0]= &defmaterial;
1878         for(a=0; a<ob->totcol; a++) {
1879                 matar[a]= give_render_material(ob, a+1);
1880                 if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
1881                         need_orco= 1;
1882                 }
1883         }
1884
1885         if(ob->parent && (ob->parent->type==OB_IKA || ob->parent->type==OB_LATTICE)) need_orco= 1;
1886
1887         if(cu->orco==0 && need_orco) make_orco_surf(cu);
1888         orco= cu->orco;
1889
1890         curve_modifier(ob, 's');
1891
1892         /* make a complete new displist, the base-displist can be different */
1893         displist.first= displist.last= 0;
1894         nu= cu->nurb.first;
1895         while(nu) {
1896                 if(nu->pntsv>1) {
1897         //              if (dl->flag & DL_CYCLIC_V) {
1898                         len= nu->resolu*nu->resolv;
1899                         /* makeNurbfaces wants zeros */
1900
1901                         dl= MEM_callocN(sizeof(DispList)+len*3*sizeof(float), "makeDispList1");
1902                         dl->verts= MEM_callocN(len*3*sizeof(float), "makeDispList01");
1903                         BLI_addtail(&displist, dl);
1904
1905                         dl->parts= nu->resolu;  /* switched order, makeNurbfaces works that way... */
1906                         dl->nr= nu->resolv;
1907                         dl->col= nu->mat_nr;
1908                         dl->rt= nu->flag;
1909
1910                         data= dl->verts;
1911                         dl->type= DL_SURF;
1912                         /* if nurbs cyclic (u/v) set flags in displist accordingly */
1913                         if(nu->flagv & 1) dl->flag |= DL_CYCLIC_V;      
1914                         if(nu->flagu & 1) dl->flag |= DL_CYCLIC_U;
1915
1916                         makeNurbfaces(nu, data);
1917                 }
1918                 nu= nu->next;
1919         }
1920
1921         if(ob->parent && ob->parent->type==OB_LATTICE) {
1922                 init_latt_deform(ob->parent, ob);
1923                 dl= displist.first;
1924                 while(dl) {
1925
1926                         fp= dl->verts;
1927                         len= dl->nr*dl->parts;
1928                         for(a=0; a<len; a++, fp+=3)  calc_latt_deform(fp);
1929
1930                         dl= dl->next;
1931                 }
1932                 end_latt_deform();
1933         }
1934         
1935         /* note; deform will be included in modifier() later */
1936         curve_modifier(ob, 'e');
1937
1938         if(ob->partype==PARSKEL && ob->parent && ob->parent->type==OB_ARMATURE) {
1939 /*              bArmature *arm= ob->parent->data; */
1940                 init_armature_deform(ob->parent, ob);
1941                 dl= displist.first;
1942                 while(dl) {
1943
1944                         fp= dl->verts;
1945                         len= dl->nr*dl->parts;
1946                         for(a=0; a<len; a++, fp+=3)
1947                                 calc_armature_deform(ob->parent, fp, a);
1948
1949                         dl= dl->next;
1950                 }
1951         }
1952
1953         if(ob->parent && ob->parent->type==OB_IKA) {
1954                 Ika *ika= ob->parent->data;
1955                 
1956                 init_skel_deform(ob->parent, ob);
1957                 dl= displist.first;
1958                 while(dl) {
1959
1960                         fp= dl->verts;
1961                         len= dl->nr*dl->parts;
1962                         for(a=0; a<len; a++, fp+=3)  calc_skel_deform(ika, fp);
1963
1964                         dl= dl->next;
1965                 }
1966         }
1967
1968         dl= displist.first;
1969         /* walk along displaylist and create rendervertices/-faces */
1970         while(dl) {
1971 #ifdef STRUBI
1972 /* watch out: u ^= y, v ^= x !! */
1973                 if(dl->type==DL_SURF) {
1974                         startvert= R.totvert;
1975                         sizeu = dl->parts; sizev = dl->nr; 
1976
1977                         data= dl->verts;
1978                         for (u = 0; u < sizeu; u++) {
1979                                 v1 = RE_findOrAddVert(R.totvert++); /* save this for possible V wrapping */
1980                                 VECCOPY(v1->co, data); data += 3;
1981                                 if(orco) {
1982                                         v1->orco= orco; orco+= 3;
1983                                 }       
1984                                 MTC_Mat4MulVecfl(mat, v1->co);
1985
1986                                 for (v = 1; v < sizev; v++) {
1987                                         ver= RE_findOrAddVert(R.totvert++);
1988                                         VECCOPY(ver->co, data); data += 3;
1989                                         if(orco) {
1990                                                 ver->orco= orco; orco+= 3;
1991                                         }       
1992                                         MTC_Mat4MulVecfl(mat, ver->co);
1993                                 }
1994                                 /* if V-cyclic, add extra vertices at end of the row */
1995                                 if (dl->flag & DL_CYCLIC_V) {
1996                                         ver= RE_findOrAddVert(R.totvert++);
1997                                         VECCOPY(ver->co, v1->co);
1998                                         if(orco) {
1999                                                 ver->orco= orco;
2000                                                 orco+= 3;
2001                                         }
2002                                 }       
2003                         }       
2004
2005                         if (dl->flag & DL_CYCLIC_V)  sizev++; /* adapt U dimension */
2006
2007
2008                         /* if U cyclic, add extra row at end of column */
2009                         if (dl->flag & DL_CYCLIC_U) {
2010                                 for (v = 0; v < sizev; v++) {
2011                                         v1= RE_findOrAddVert(startvert + v);
2012                                         ver= RE_findOrAddVert(R.totvert++);
2013                                         VECCOPY(ver->co, v1->co);
2014                                         if(orco) {
2015                                                 ver->orco= orco;
2016                                                 orco +=3;
2017                                         }
2018                                 }
2019                                 sizeu++;
2020                         }       
2021                                         
2022
2023
2024
2025                         startvlak= R.totvlak;
2026
2027                         /* process generic surface */
2028                         for(u = 0; u < sizeu - 1; u++) {
2029 /*
2030                                 
2031                         ^       ()----p4----p3----()
2032                         |       |     |     |     |
2033                         u       |     |     |     |
2034                                 |     |     |     |
2035                                 ()----p1----p2----()
2036                                        v ->
2037 */
2038
2039                                 p1 = startvert + u * sizev; /* walk through face list */
2040                                 p2 = p1 + 1;
2041                                 p3 = p2 + sizev;
2042                                 p4 = p3 - 1;
2043
2044
2045                                 for(v = 0; v < sizev - 1; v++) {
2046                                         v1= RE_findOrAddVert(p1);
2047                                         v2= RE_findOrAddVert(p2);
2048                                         v3= RE_findOrAddVert(p3);
2049                                         v4= RE_findOrAddVert(p4);
2050
2051 /* normal len can be 0 if there are double nurbs control vertices 
2052         so zero area faces can be generated
2053         ->> there is at the moment no proper way to fix this except
2054         generating empty render faces */
2055
2056
2057                                         vlr= RE_findOrAddVlak(R.totvlak++);
2058                                         vlr->ob= vlr_set_ob(ob);
2059                                         vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
2060                                         
2061                                         flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
2062                                         VECCOPY(vlr->n, n1);
2063                                         
2064                                         vlr->lay= ob->lay;
2065                                         vlr->mat= matar[ dl->col];
2066                                         vlr->ec= ME_V1V2+ME_V2V3;
2067                                         vlr->flag= dl->rt;
2068                                         if( (cu->flag & CU_NOPUNOFLIP) ) {
2069                                                 vlr->flag |= R_NOPUNOFLIP;
2070                                         }
2071
2072                                         VecAddf(v1->n, v1->n, n1);
2073                                         VecAddf(v2->n, v2->n, n1);
2074                                         VecAddf(v3->n, v3->n, n1);
2075                                         VecAddf(v4->n, v4->n, n1);
2076
2077                                         p1++; p2++; p3++; p4++;
2078                                 }
2079                         }       
2080                         /* fix normals for U resp. V cyclic faces */
2081                         sizeu--; sizev--;  /* dec size for face array */
2082                         if (dl->flag & DL_CYCLIC_U) {
2083
2084                                 for (v = 0; v < sizev; v++)
2085                                 {
2086                                         /* optimize! :*/
2087                                         vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, v));
2088                                         vlr1= RE_findOrAddVlak(UVTOINDEX(0, v));
2089                                         VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
2090                                         VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
2091                                         VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
2092                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
2093                                 }
2094                         }
2095                         if (dl->flag & DL_CYCLIC_V) {
2096
2097                                 for (u = 0; u < sizeu; u++)
2098                                 {
2099                                         /* optimize! :*/
2100                                         vlr= RE_findOrAddVlak(UVTOINDEX(u, 0));
2101                                         vlr1= RE_findOrAddVlak(UVTOINDEX(u, sizev-1));
2102                                         VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
2103                                         VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
2104                                         VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
2105                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
2106                                 }
2107                         }
2108                         /* last vertex is an extra case: 
2109
2110                         ^       ()----()----()----()
2111                         |       |     |     ||     |
2112                         u       |     |(0,n)||(0,0)|
2113                                 |     |     ||     |
2114                                 ()====()====[]====()
2115                                 |     |     ||     |
2116                                 |     |(m,n)||(m,0)|
2117                                 |     |     ||     |
2118                                 ()----()----()----()
2119                                        v ->
2120
2121                         vertex [] is no longer shared, therefore distribute
2122                         normals of the surrounding faces to all of the duplicates of []
2123                         */
2124
2125                         if ((dl->flag & DL_CYCLIC_U) && (dl->flag & DL_CYCLIC_V))
2126                         {
2127                                 vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
2128                                 vlr1= RE_findOrAddVlak(UVTOINDEX(0,0));  /* (0,0) */
2129                                 VecAddf(vn, vlr->n, vlr1->n);
2130                                 vlr2= RE_findOrAddVlak(UVTOINDEX(0, sizev-1)); /* (0,n) */
2131                                 VecAddf(vn, vn, vlr2->n);
2132                                 vlr3= RE_findOrAddVlak(UVTOINDEX(sizeu-1, 0)); /* (m,0) */
2133                                 VecAddf(vn, vn, vlr3->n);
2134                                 VECCOPY(vlr->v3->n, vn);
2135                                 VECCOPY(vlr1->v1->n, vn);
2136                                 VECCOPY(vlr2->v2->n, vn);
2137                                 VECCOPY(vlr3->v4->n, vn);
2138                         }
2139                         for(a = startvert; a < R.totvert; a++) {
2140                                 ver= RE_findOrAddVert(a);
2141                                 Normalise(ver->n);
2142                         }
2143
2144
2145                 }
2146 #else
2147
2148                 if(dl->type==DL_SURF) {
2149                         startvert= R.totvert;
2150                         a= dl->nr*dl->parts;
2151                         data= dl->verts;
2152                         while(a--) {
2153                                 ver= RE_findOrAddVert(R.totvert++);
2154                                 VECCOPY(ver->co, data);
2155                                 if(orco) {
2156                                         ver->orco= orco;
2157                                         orco+= 3;
2158                                 }
2159                                 MTC_Mat4MulVecfl(mat, ver->co);
2160                                 data+= 3;
2161                         }
2162
2163                         startvlak= R.totvlak;
2164
2165                         for(a=0; a<dl->parts; a++) {
2166
2167                                 DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts);
2168                                 p1+= startvert;
2169                                 p2+= startvert;
2170                                 p3+= startvert;
2171                                 p4+= startvert;
2172
2173                                 for(; b<dl->nr; b++) {
2174                                         v1= RE_findOrAddVert(p1);
2175                                         v2= RE_findOrAddVert(p2);
2176                                         v3= RE_findOrAddVert(p3);
2177                                         v4= RE_findOrAddVert(p4);
2178
2179                                         flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
2180                                         if(flen!=0.0) {
2181                                                 vlr= RE_findOrAddVlak(R.totvlak++);
2182                                                 vlr->ob= vlr_set_ob(ob);
2183                                                 vlr->v1= v1;
2184                                                 vlr->v2= v3;
2185                                                 vlr->v3= v4;
2186                                                 vlr->v4= v2;
2187                                                 VECCOPY(vlr->n, n1);
2188                                                 vlr->lay= ob->lay;
2189                                                 vlr->mat= matar[ dl->col];
2190                                                 vlr->ec= ME_V1V2+ME_V2V3;
2191                                                 vlr->flag= dl->rt;
2192                                                 if( (cu->flag & CU_NOPUNOFLIP) ) {
2193                                                         vlr->flag |= R_NOPUNOFLIP;
2194                                                 }
2195                                         }
2196
2197                                         VecAddf(v1->n, v1->n, n1);
2198                                         VecAddf(v2->n, v2->n, n1);
2199                                         VecAddf(v3->n, v3->n, n1);
2200                                         VecAddf(v4->n, v4->n, n1);
2201
2202                                         p4= p3;
2203                                         p3++;
2204                                         p2= p1;
2205                                         p1++;
2206                                 }
2207                         }
2208
2209                         for(a=startvert; a<R.totvert; a++) {
2210                                 ver= RE_findOrAddVert(a);
2211                                 Normalise(ver->n);
2212                         }
2213
2214
2215                 }
2216 #endif
2217                 dl= dl->next;
2218         }
2219         freedisplist(&displist);
2220 }
2221
2222 static void init_render_curve(Object *ob)
2223 {
2224         extern Material defmaterial;    // initrender.c
2225         Ika *ika=0;
2226         Lattice *lt=0;
2227         Curve *cu;
2228         VertRen *ver;
2229         VlakRen *vlr;
2230         ListBase dlbev;
2231         Nurb *nu=0;
2232         DispList *dlb, *dl;
2233         BevList *bl;
2234         BevPoint *bevp;
2235         Material *matar[32];
2236         float len, *data, *fp, *fp1, fac;
2237         float n[3], vec[3], widfac, size[3], mat[4][4];
2238         int nr, startvert, startvlak, a, b, p1, p2, p3, p4;
2239         int totvert, frontside, need_orco=0, firststartvert, *index;
2240
2241         cu= ob->data;
2242         if(cu->nurb.first==NULL) return;
2243
2244         /* no modifier call here, is in makedisp */
2245
2246         /* test displist */
2247         if(cu->disp.first==0) makeDispList(ob);
2248         dl= cu->disp.first;
2249         if(cu->disp.first==0) return;
2250         
2251         if(dl->type!=DL_INDEX3) {
2252                 curve_to_filledpoly(cu, &cu->nurb, &cu->disp);
2253         }
2254
2255         if(cu->bev.first==0) makeBevelList(ob);
2256
2257         firststartvert= R.totvert;
2258
2259         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
2260         MTC_Mat4Invert(ob->imat, mat);
2261
2262         /* material array */
2263         memset(matar, 0, 4*32);
2264         matar[0]= &defmaterial;
2265         for(a=0; a<ob->totcol; a++) {
2266                 matar[a]= give_render_material(ob, a+1);
2267                 if(matar[a]->texco & TEXCO_ORCO) {
2268                         need_orco= 1;
2269                 }
2270         }
2271
2272         /* bevelcurve in displist */
2273         dlbev.first= dlbev.last= 0;
2274
2275         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj!=NULL) {
2276                 makebevelcurve(ob, &dlbev);
2277         }
2278
2279         /* uv orcos? count amount of points and malloc */
2280         if(need_orco && (cu->flag & CU_UV_ORCO)) {
2281                 if(cu->flag & CU_PATH);
2282                 else {
2283                         totvert= 0;
2284                         bl= cu->bev.first;
2285                         while(bl) {
2286                                 dlb= dlbev.first;
2287                                 while(dlb) {
2288                                         totvert+= dlb->nr*bl->nr;
2289                                         dlb= dlb->next;
2290                                 }
2291                                 bl= bl->next;
2292                         }
2293
2294                         if(totvert) {
2295                                 fp= cu->orco= MEM_mallocN(3*sizeof(float)*totvert, "cu->orco");
2296         
2297                                 bl= cu->bev.first;
2298                                 while(bl) {
2299                                         dlb= dlbev.first;
2300                                         while(dlb) {
2301                                                 for(b=0; b<dlb->nr; b++) {
2302                                                         fac= (2.0*b/(float)(dlb->nr-1)) - 1.0;
2303                                                         for(a=0; a<bl->nr; a++, fp+=3) {
2304                                                                 fp[0]= (2.0*a/(float)(bl->nr-1)) - 1.0;
2305                                                                 fp[1]= fac;
2306                                                                 fp[2]= 0.0;
2307                                                         }
2308                                                 }
2309                                                 dlb= dlb->next;
2310                                         }
2311                                         bl= bl->next;
2312                                 }
2313                         }
2314                 }
2315         }
2316
2317         if(ob->parent && ob->parent->type==OB_LATTICE) {
2318                 lt= ob->parent->data;
2319                 init_latt_deform(ob->parent, ob);
2320                 need_orco= 1;
2321         }
2322         
2323         if(ob->parent && ob->parent->type==OB_IKA) {
2324                 ika= ob->parent->data;
2325                 init_skel_deform(ob->parent, ob);
2326                 need_orco= 1;
2327         }
2328
2329         if(ob->parent && ob->parent->type==OB_ARMATURE) {
2330                 init_armature_deform(ob->parent, ob);
2331                 need_orco= 1;
2332         }
2333
2334         /* do keypos? NOTE: watch it : orcos */
2335
2336         /* effect on text? */
2337
2338         /* boundboxclip still todo */
2339
2340         /* side faces of poly:  work with bevellist */
2341         widfac= (cu->width-1.0);
2342
2343         bl= cu->bev.first;
2344         nu= cu->nurb.first;
2345         while(bl) {
2346
2347                 if(dlbev.first) {    /* otherwise just a poly */
2348
2349                         dlb= dlbev.first;   /* bevel loop */
2350                         while(dlb) {
2351                                 data= MEM_mallocN(3*sizeof(float)*dlb->nr*bl->nr, "init_render_curve3");
2352                                 fp= data;
2353
2354                                 /* for each point at bevelcurve do the entire poly */
2355                                 fp1= dlb->verts;
2356                                 b= dlb->nr;
2357                                 while(b--) {
2358
2359                                         bevp= (BevPoint *)(bl+1);
2360                                         for(a=0; a<bl->nr; a++) {
2361                                                 float fac;
2362                                                 
2363                                                 /* returns 1.0 if no taper, of course */
2364                                                 fac= calc_taper(cu->taperobj, a, bl->nr);
2365
2366                                                 if(cu->flag & CU_3D) {
2367                                                         vec[0]= fp1[1]+widfac;
2368                                                         vec[1]= fp1[2];
2369                                                         vec[2]= 0.0;
2370
2371                                                         MTC_Mat3MulVecfl(bevp->mat, vec);
2372
2373                                                         fp[0]= bevp->x+ fac*vec[0];
2374                                                         fp[1]= bevp->y+ fac*vec[1];
2375                                                         fp[2]= bevp->z+ fac*vec[2];
2376                                                 }
2377                                                 else {
2378
2379                                                         fp[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina;
2380                                                         fp[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa;
2381                                                         fp[2]= bevp->z+ fac*fp1[2];
2382                                                         /* do not MatMul here: polyfill should work uniform, independent which frame */
2383                                                 }
2384                                                 fp+= 3;
2385                                                 bevp++;
2386                                         }
2387                                         fp1+=3;
2388                                 }
2389
2390                                 /* make render vertices */
2391                                 fp= data;
2392                                 startvert= R.totvert;
2393                                 nr= dlb->nr*bl->nr;
2394
2395                                 while(nr--) {
2396                                         ver= RE_findOrAddVert(R.totvert++);
2397                                         
2398                                         if(lt) calc_latt_deform(fp);
2399                                         else if(ika) calc_skel_deform(ika, fp);
2400                                         
2401                                         VECCOPY(ver->co, fp);
2402                                         MTC_Mat4MulVecfl(mat, ver->co);
2403                                         fp+= 3;
2404                                 }
2405
2406                                 startvlak= R.totvlak;
2407
2408                                 for(a=0; a<dlb->nr; a++) {
2409
2410                                         frontside= (a >= dlb->nr/2);
2411
2412                                         DL_SURFINDEX(bl->poly>0, dlb->type==DL_POLY, bl->nr, dlb->nr);
2413                                         p1+= startvert;
2414                                         p2+= startvert;
2415                                         p3+= startvert;
2416                                         p4+= startvert;
2417
2418                                         for(; b<bl->nr; b++) {
2419
2420                                                 vlr= RE_findOrAddVlak(R.totvlak++);
2421                                                 vlr->ob= vlr_set_ob(ob);
2422                                                 vlr->v1= RE_findOrAddVert(p2);
2423                                                 vlr->v2= RE_findOrAddVert(p1);
2424                                                 vlr->v3= RE_findOrAddVert(p3);
2425                                                 vlr->v4= RE_findOrAddVert(p4);
2426                                                 vlr->ec= ME_V2V3+ME_V3V4;
2427                                                 if(a==0) vlr->ec+= ME_V1V2;
2428
2429                                                 vlr->flag= nu->flag;
2430                                                 vlr->lay= ob->lay;
2431
2432                                                 /* this is not really scientific: the vertices
2433                                                  * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
2434                                                  * front and backside treated different!!
2435                                                  */
2436
2437                                                 if(frontside)
2438                                                         CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
2439                                                 else 
2440                                                         CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
2441
2442                                                 vlr->mat= matar[ nu->mat_nr ];
2443
2444                                                 p4= p3;
2445                                                 p3++;
2446                                                 p2= p1;
2447                                                 p1++;
2448
2449                                         }
2450
2451                                 }
2452
2453                                 /* here was split_u before, for split off standard bevels, not needed anymore */
2454                                 /* but it could check on the bevel-curve BevPoints for u-split though... */
2455                                 
2456                                 /* make double points: SPLIT BEVELS */
2457                                 bevp= (BevPoint *)(bl+1);
2458                                 for(a=0; a<bl->nr; a++) {
2459                                         if(bevp->f1)
2460                                                 split_v_renderfaces(startvlak, startvert, bl->nr, dlb->nr, a, bl->poly>0,
2461                                                     dlb->type==DL_POLY);
2462                                         bevp++;
2463                                 }
2464
2465                                 /* vertex normals */
2466                                 for(a= startvlak; a<R.totvlak; a++) {
2467                                         vlr= RE_findOrAddVlak(a);
2468
2469                                         VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
2470                                         VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
2471                                         VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
2472                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
2473                                 }
2474                                 for(a=startvert; a<R.totvert; a++) {
2475                                         ver= RE_findOrAddVert(a);
2476                                         len= Normalise(ver->n);
2477                                         if(len==0.0) ver->sticky= (float *)1;
2478                                         else ver->sticky= 0;
2479                                 }
2480                                 for(a= startvlak; a<R.totvlak; a++) {
2481                                         vlr= RE_findOrAddVlak(a);
2482                                         if(vlr->v1->sticky) VECCOPY(vlr->v1->n, vlr->n);
2483                                         if(vlr->v2->sticky) VECCOPY(vlr->v2->n, vlr->n);
2484                                         if(vlr->v3->sticky) VECCOPY(vlr->v3->n, vlr->n);
2485                                         if(vlr->v4->sticky) VECCOPY(vlr->v4->n, vlr->n);
2486                                 }
2487
2488                                 dlb= dlb->next;
2489
2490                                 MEM_freeN(data);
2491                         }
2492
2493                 }
2494                 bl= bl->next;
2495                 nu= nu->next;
2496         }
2497
2498         if(dlbev.first) {
2499                 freedisplist(&dlbev);
2500         }
2501
2502         if(cu->flag & CU_PATH) return;
2503
2504         /* from displist the filled faces can be extracted */
2505         dl= cu->disp.first;
2506
2507         while(dl) {
2508                 if(dl->type==DL_INDEX3) {
2509                         startvert= R.totvert;
2510                         data= dl->verts;
2511
2512                         n[0]= ob->imat[0][2];
2513                         n[1]= ob->imat[1][2];
2514                         n[2]= ob->imat[2][2];
2515                         Normalise(n);
2516
2517                         /* copy first, rotate later for comparision trick */
2518                         for(a=0; a<dl->nr; a++, data+=3) {
2519                                 ver= RE_findOrAddVert(R.totvert++);
2520                                 VECCOPY(ver->co, data);
2521
2522                                 if(ver->co[2] < 0.0) {
2523                                         VECCOPY(ver->n, n);
2524                                 }
2525                                 else {
2526                                         ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
2527                                 }
2528                         }
2529
2530                         startvlak= R.totvlak;
2531                         index= dl->index;
2532                         for(a=0; a<dl->parts; a++, index+=3) {
2533
2534                                 vlr= RE_findOrAddVlak(R.totvlak++);
2535                                 vlr->ob = vlr_set_ob(ob);       /* yafray: correction for curve rendering, obptr was not set */
2536                                 vlr->v1= RE_findOrAddVert(startvert+index[0]);
2537                                 vlr->v2= RE_findOrAddVert(startvert+index[1]);
2538                                 vlr->v3= RE_findOrAddVert(startvert+index[2]);
2539                                 vlr->v4= NULL;
2540                                 
2541                                 if(vlr->v1->co[2] < 0.0) {
2542                                         VECCOPY(vlr->n, n);
2543                                 }
2544                                 else {
2545                                         vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
2546                                 }
2547                                 
2548                                 vlr->mat= matar[ dl->col ];
2549                                 vlr->flag= 0;
2550                                 if( (cu->flag & CU_NOPUNOFLIP) ) {
2551                                         vlr->flag |= R_NOPUNOFLIP;
2552                                 }
2553                                 vlr->ec= 0;
2554                                 vlr->lay= ob->lay;
2555                         }
2556                         /* rotate verts */
2557                         for(a=0; a<dl->nr; a++) {
2558                                 ver= RE_findOrAddVert(startvert+a);
2559                                 MTC_Mat4MulVecfl(mat, ver->co);
2560                         }
2561                         
2562                 }
2563                 dl= dl->next;
2564         }
2565
2566         if(lt) {
2567                 end_latt_deform();
2568         }
2569
2570         if(need_orco) { /* the stupid way: should be replaced; taking account for keys! */
2571
2572                 VECCOPY(size, cu->size);
2573
2574                 nr= R.totvert-firststartvert;
2575                 if(nr) {
2576                         if(cu->orco) {
2577                                 fp= cu->orco;
2578                                 while(nr--) {
2579                                         ver= RE_findOrAddVert(firststartvert++);
2580                                         ver->orco= fp;
2581                                         fp+= 3;
2582                                 }
2583                         }
2584                         else {
2585                                 fp= cu->orco= MEM_mallocN(sizeof(float)*3*nr, "cu orco");
2586                                 while(nr--) {
2587                                         ver= RE_findOrAddVert(firststartvert++);
2588                                         ver->orco= fp;
2589
2590                                         VECCOPY(fp, ver->co);
2591                                         MTC_Mat4MulVecfl(ob->imat, fp);
2592
2593                                         fp[0]= (fp[0]-cu->loc[0])/size[0];
2594                                         fp[1]= (fp[1]-cu->loc[1])/size[1];
2595                                         fp[2]= (fp[2]-cu->loc[2])/size[2];
2596                                         fp+= 3;
2597                                 }
2598                         }
2599                 }
2600         }
2601 }
2602
2603 /* prevent phong interpolation for giving ray shadow errors (terminator problem) */
2604 static void set_phong_threshold(Object *ob, int startface, int numface, int startvert, int numvert )
2605 {
2606 //      VertRen *ver;
2607         VlakRen *vlr;
2608         float thresh= 0.0, dot;
2609         int tot=0, i;
2610         
2611         /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger 
2612            are taken into account. This threshold is meant to work on smooth geometry, not
2613            for extreme cases (ton) */
2614         
2615         for(i=startface; i<startface+numface; i++) {
2616                 vlr= RE_findOrAddVlak(i);
2617                 if(vlr->flag & R_SMOOTH) {
2618                         dot= INPR(vlr->n, vlr->v1->n);
2619                         dot= ABS(dot);
2620                         if(dot>0.9) {
2621                                 thresh+= dot; tot++;
2622                         }
2623                         dot= INPR(vlr->n, vlr->v2->n);
2624                         dot= ABS(dot);
2625                         if(dot>0.9) {
2626                                 thresh+= dot; tot++;
2627                         }
2628
2629                         dot= INPR(vlr->n, vlr->v3->n);
2630                         dot= ABS(dot);
2631                         if(dot>0.9) {
2632                                 thresh+= dot; tot++;
2633                         }
2634
2635                         if(vlr->v4) {
2636                                 dot= INPR(vlr->n, vlr->v4->n);
2637                                 dot= ABS(dot);
2638                                 if(dot>0.9) {
2639                                         thresh+= dot; tot++;
2640                                 }
2641                         }
2642                 }
2643         }
2644         
2645         if(tot) {
2646                 thresh/= (float)tot;
2647                 ob->smoothresh= cos(0.5*M_PI-acos(thresh));
2648         }
2649 }
2650
2651 static void init_render_object(Object *ob)
2652 {
2653         float mat[4][4];
2654         int startface, startvert;
2655         
2656         startface=R.totvlak;
2657         startvert=R.totvert;
2658
2659         ob->flag |= OB_DONE;
2660
2661         if(ob->type==OB_LAMP)
2662                 RE_add_render_lamp(ob, 1);
2663         else if ELEM(ob->type, OB_FONT, OB_CURVE)
2664                 init_render_curve(ob);
2665         else if(ob->type==OB_SURF)
2666                 init_render_surf(ob);
2667         else if(ob->type==OB_MESH)
2668                 init_render_mesh(ob);
2669         else if(ob->type==OB_MBALL)
2670                 init_render_mball(ob);
2671         else {
2672                 MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
2673                 MTC_Mat4Invert(ob->imat, mat);
2674         }
2675         
2676         /* generic post process here */
2677         if(startvert!=R.totvert) {
2678         
2679                 /* the exception below is because displace code now is in init_render_mesh call, 
2680                 I will look at means to have autosmooth enabled for all object types 
2681                 and have it as general postprocess, like displace */
2682                 if (ob->type!=OB_MESH && test_for_displace( ob ) ) 
2683                         do_displacement(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
2684         
2685                 /* phong normal interpolation can cause error in tracing (terminator prob) */
2686                 ob->smoothresh= 0.0;
2687                 if( (R.r.mode & R_RAYTRACE) && (R.r.mode & R_SHADOW) ) 
2688                         set_phong_threshold(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
2689         }
2690 }
2691
2692 void RE_freeRotateBlenderScene(void)
2693 {
2694         ShadBuf *shb;
2695         Object *ob = NULL;
2696         Mesh *me;
2697         Curve *cu;
2698         DispList *dl;
2699         unsigned long *ztile;
2700         int a, b, v;
2701         char *ctile;
2702
2703         /* FREE */
2704         
2705         BLI_memarena_free(R.memArena);
2706         R.memArena = NULL;
2707
2708         for(a=0; a<R.totlamp; a++) {
2709                 if(R.la[a]->shb) {
2710                         shb= R.la[a]->shb;
2711                         v= (shb->size*shb->size)/256;
2712                         ztile= shb->zbuf;
2713                         ctile= shb->cbuf;
2714                         for(b=0; b<v; b++, ztile++, ctile++) {
2715                                 if(*ctile) MEM_freeN((void *) *ztile);
2716                         }
2717                         
2718                         MEM_freeN(shb->zbuf);
2719                         MEM_freeN(shb->cbuf);
2720                         MEM_freeN(R.la[a]->shb);
2721                 }
2722                 if(R.la[a]->jitter) MEM_freeN(R.la[a]->jitter);
2723                 MEM_freeN(R.la[a]);
2724         }
2725
2726         /* note; these pointer arrays were allocated, with last element NULL to stop loop */
2727         a=0;
2728         while(R.blove[a]) {
2729                 MEM_freeN(R.blove[a]);
2730                 R.blove[a]= NULL;
2731                 a++;
2732         }
2733
2734         a=0;
2735         while(R.blovl[a]) {
2736                 MEM_freeN(R.blovl[a]);
2737                 R.blovl[a]= NULL;
2738                 a++;
2739         }
2740         a=0;
2741         while(R.bloha[a]) {
2742                 MEM_freeN(R.bloha[a]);
2743                 R.bloha[a]= NULL;
2744                 a++;
2745         }
2746
2747         /* free orco. check all objects because of duplis and sets */
2748         ob= G.main->object.first;
2749         while(ob) {
2750
2751                 if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
2752                         cu= ob->data;
2753                         if(cu->orco) {
2754                                 MEM_freeN(cu->orco);
2755                                 cu->orco= 0;
2756                         }
2757                 }
2758                 else if(ob->type==OB_MESH) {
2759                         me= ob->data;
2760                         if(me->orco) {
2761                                 MEM_freeN(me->orco);
2762                                 me->orco= 0;
2763                         }
2764                         if ((me->flag&ME_SUBSURF) && ((me->subdiv!=me->subdivr) || (ob->effect.first != NULL) || ob==G.obedit) ) { 
2765                             /* Need to recalc for effects since they are time dependant */
2766                                 makeDispList(ob);  /* XXX this should be replaced with proper caching */
2767                         }
2768                 }
2769                 else if(ob->type==OB_MBALL) {
2770                         if(ob->disp.first && ob->disp.first!=ob->disp.last) {
2771                                 dl= ob->disp.first;
2772                                 BLI_remlink(&ob->disp, dl);
2773                                 freedisplist(&ob->disp);
2774                                 BLI_addtail(&ob->disp, dl);
27