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