Two fixes;
[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                                         ver->orco= orco;
1941                                         orco+= 3;
1942                                 }       
1943                         }       
1944
1945                         if (dl->flag & DL_CYCLIC_V)  sizev++; /* adapt U dimension */
1946
1947
1948                         /* if U cyclic, add extra row at end of column */
1949                         if (dl->flag & DL_CYCLIC_U) {
1950                                 for (v = 0; v < sizev; v++) {
1951                                         v1= RE_findOrAddVert(startvert + v);
1952                                         ver= RE_findOrAddVert(R.totvert++);
1953                                         VECCOPY(ver->co, v1->co);
1954                                         ver->orco= orco;
1955                                         orco +=3;
1956
1957                                 }
1958                                 sizeu++;
1959                         }       
1960                                         
1961
1962
1963
1964                         startvlak= R.totvlak;
1965
1966                         /* process generic surface */
1967                         for(u = 0; u < sizeu - 1; u++) {
1968 /*
1969                                 
1970                         ^       ()----p4----p3----()
1971                         |       |     |     |     |
1972                         u       |     |     |     |
1973                                 |     |     |     |
1974                                 ()----p1----p2----()
1975                                        v ->
1976 */
1977
1978                                 p1 = startvert + u * sizev; /* walk through face list */
1979                                 p2 = p1 + 1;
1980                                 p3 = p2 + sizev;
1981                                 p4 = p3 - 1;
1982
1983
1984                                 for(v = 0; v < sizev - 1; v++) {
1985                                         v1= RE_findOrAddVert(p1);
1986                                         v2= RE_findOrAddVert(p2);
1987                                         v3= RE_findOrAddVert(p3);
1988                                         v4= RE_findOrAddVert(p4);
1989
1990                                         flen= CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, n1);
1991 /* flen can be 0 if there are double nurbs control vertices 
1992         so zero area faces can be generated
1993         ->> there is at the moment no proper way to fix this except
1994         generating empty render faces */
1995
1996 //                                      if(flen!=0.0) {
1997                                                 vlr= RE_findOrAddVlak(R.totvlak++);
1998                                                 vlr->ob= ob;
1999                                                 vlr->v1= v4; vlr->v2= v3; vlr->v3= v2; vlr->v4= v1;             // note, displists for nurbs are again opposite, tsk tsk
2000                                                 VECCOPY(vlr->n, n1);
2001                                                 vlr->lay= ob->lay;
2002                                                 vlr->mat= matar[ dl->col];
2003                                                 vlr->ec= ME_V1V2+ME_V2V3;
2004                                                 vlr->flag= dl->rt;
2005                                                 if( (cu->flag & CU_NOPUNOFLIP) || (vlr->mat->mode & MA_RAYTRANSP)) {
2006                                                         vlr->flag |= R_NOPUNOFLIP;
2007                                                 }
2008 //                                      }
2009
2010                                         VecAddf(v1->n, v1->n, n1);
2011                                         VecAddf(v2->n, v2->n, n1);
2012                                         VecAddf(v3->n, v3->n, n1);
2013                                         VecAddf(v4->n, v4->n, n1);
2014
2015                                         p1++; p2++; p3++; p4++;
2016                                 }
2017                         }       
2018                         /* fix normals for U resp. V cyclic faces */
2019                         sizeu--; sizev--;  /* dec size for face array */
2020                         if (dl->flag & DL_CYCLIC_U) {
2021
2022                                 for (v = 0; v < sizev; v++)
2023                                 {
2024                                         /* optimize! :*/
2025                                         vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, v));
2026                                         GETNORMAL(vlr, n1);
2027                                         vlr1= RE_findOrAddVlak(UVTOINDEX(0, v));
2028                                         GETNORMAL(vlr1, n2);
2029                                         VecAddf(vlr1->v1->n, vlr1->v1->n, n1);
2030                                         VecAddf(vlr1->v2->n, vlr1->v2->n, n1);
2031                                         VecAddf(vlr->v3->n, vlr->v3->n, n2);
2032                                         VecAddf(vlr->v4->n, vlr->v4->n, n2);
2033                                 }
2034                         }
2035                         if (dl->flag & DL_CYCLIC_V) {
2036
2037                                 for (u = 0; u < sizeu; u++)
2038                                 {
2039                                         /* optimize! :*/
2040                                         vlr= RE_findOrAddVlak(UVTOINDEX(u, 0));
2041                                         GETNORMAL(vlr, n1);
2042                                         vlr1= RE_findOrAddVlak(UVTOINDEX(u, sizev-1));
2043                                         GETNORMAL(vlr1, n2);
2044                                         VecAddf(vlr1->v2->n, vlr1->v2->n, n1);
2045                                         VecAddf(vlr1->v3->n, vlr1->v3->n, n1);
2046                                         VecAddf(vlr->v1->n, vlr->v1->n, n2);
2047                                         VecAddf(vlr->v4->n, vlr->v4->n, n2);
2048                                 }
2049                         }
2050                         /* last vertex is an extra case: 
2051
2052                         ^       ()----()----()----()
2053                         |       |     |     ||     |
2054                         u       |     |(0,n)||(0,0)|
2055                                 |     |     ||     |
2056                                 ()====()====[]====()
2057                                 |     |     ||     |
2058                                 |     |(m,n)||(m,0)|
2059                                 |     |     ||     |
2060                                 ()----()----()----()
2061                                        v ->
2062
2063                         vertex [] is no longer shared, therefore distribute
2064                         normals of the surrounding faces to all of the duplicates of []
2065                         */
2066
2067                         if ((dl->flag & DL_CYCLIC_U) && (dl->flag & DL_CYCLIC_V))
2068                         {
2069                                 vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
2070                                 GETNORMAL(vlr, n1);
2071                                 vlr1= RE_findOrAddVlak(UVTOINDEX(0,0));  /* (0,0) */
2072                                 GETNORMAL(vlr1, vn);
2073                                 VecAddf(vn, vn, n1);
2074                                 vlr2= RE_findOrAddVlak(UVTOINDEX(0, sizev-1)); /* (0,n) */
2075                                 GETNORMAL(vlr2, n1);
2076                                 VecAddf(vn, vn, n1);
2077                                 vlr3= RE_findOrAddVlak(UVTOINDEX(sizeu-1, 0)); /* (m,0) */
2078                                 GETNORMAL(vlr3, n1);
2079                                 VecAddf(vn, vn, n1);
2080                                 VECCOPY(vlr->v3->n, vn);
2081                                 VECCOPY(vlr1->v1->n, vn);
2082                                 VECCOPY(vlr2->v2->n, vn);
2083                                 VECCOPY(vlr3->v4->n, vn);
2084                         }
2085                         for(a = startvert; a < R.totvert; a++) {
2086                                 ver= RE_findOrAddVert(a);
2087                                 Normalise(ver->n);
2088                         }
2089
2090
2091                 }
2092 #else
2093
2094                 if(dl->type==DL_SURF) {
2095                         startvert= R.totvert;
2096                         a= dl->nr*dl->parts;
2097                         data= dl->verts;
2098                         while(a--) {
2099                                 ver= RE_findOrAddVert(R.totvert++);
2100                                 VECCOPY(ver->co, data);
2101                                 if(orco) {
2102                                         ver->orco= orco;
2103                                         orco+= 3;
2104                                 }
2105                                 MTC_Mat4MulVecfl(mat, ver->co);
2106                                 data+= 3;
2107                         }
2108
2109                         startvlak= R.totvlak;
2110
2111                         for(a=0; a<dl->parts; a++) {
2112
2113                                 DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts);
2114                                 p1+= startvert;
2115                                 p2+= startvert;
2116                                 p3+= startvert;
2117                                 p4+= startvert;
2118
2119                                 for(; b<dl->nr; b++) {
2120                                         v1= RE_findOrAddVert(p1);
2121                                         v2= RE_findOrAddVert(p2);
2122                                         v3= RE_findOrAddVert(p3);
2123                                         v4= RE_findOrAddVert(p4);
2124
2125                                         flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
2126                                         if(flen!=0.0) {
2127                                                 vlr= RE_findOrAddVlak(R.totvlak++);
2128                                                 vlr->ob= ob;
2129                                                 vlr->v1= v1;
2130                                                 vlr->v2= v3;
2131                                                 vlr->v3= v4;
2132                                                 vlr->v4= v2;
2133                                                 VECCOPY(vlr->n, n1);
2134                                                 vlr->lay= ob->lay;
2135                                                 vlr->mat= matar[ dl->col];
2136                                                 vlr->ec= ME_V1V2+ME_V2V3;
2137                                                 vlr->flag= dl->rt;
2138                                                 if( (cu->flag & CU_NOPUNOFLIP) || (vlr->mat->mode & MA_RAYTRANSP)) {
2139                                                         vlr->flag |= R_NOPUNOFLIP;
2140                                                 }
2141                                         }
2142
2143                                         VecAddf(v1->n, v1->n, n1);
2144                                         VecAddf(v2->n, v2->n, n1);
2145                                         VecAddf(v3->n, v3->n, n1);
2146                                         VecAddf(v4->n, v4->n, n1);
2147
2148                                         p4= p3;
2149                                         p3++;
2150                                         p2= p1;
2151                                         p1++;
2152                                 }
2153                         }
2154
2155                         for(a=startvert; a<R.totvert; a++) {
2156                                 ver= RE_findOrAddVert(a);
2157                                 Normalise(ver->n);
2158                         }
2159
2160
2161                 }
2162 #endif
2163                 dl= dl->next;
2164         }
2165         freedisplist(&displist);
2166 }
2167
2168 static void init_render_curve(Object *ob)
2169 {
2170         Ika *ika=0;
2171
2172         Lattice *lt=0;
2173         Curve *cu;
2174         VertRen *ver;
2175         VlakRen *vlr;
2176         ListBase dlbev;
2177         Nurb *nu=0;
2178         DispList *dlb, *dl;
2179         BevList *bl;
2180         BevPoint *bevp;
2181         Material *matar[32];
2182         float len, *data, *fp, *fp1, fac;
2183         float n[3], vec[3], widfac, size[3], mat[4][4];
2184         int nr, startvert, startvlak, a, b, p1, p2, p3, p4;
2185         int totvert, frontside, need_orco=0, firststartvert, *index;
2186
2187         cu= ob->data;
2188         if(cu->nurb.first==NULL) return;
2189
2190         /* no modifier call here, is in makedisp */
2191
2192         /* test displist */
2193         if(cu->disp.first==0) makeDispList(ob);
2194         dl= cu->disp.first;
2195         if(cu->disp.first==0) return;
2196         
2197         if(dl->type!=DL_INDEX3) {
2198                 curve_to_filledpoly(cu, &cu->nurb, &cu->disp);
2199         }
2200
2201         if(cu->bev.first==0) makeBevelList(ob);
2202
2203         firststartvert= R.totvert;
2204
2205         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
2206         MTC_Mat4Invert(ob->imat, mat);
2207
2208         /* material array */
2209         memset(matar, 0, 4*32);
2210         matar[0]= &defmaterial;
2211         for(a=0; a<ob->totcol; a++) {
2212                 matar[a]= give_render_material(ob, a+1);
2213                 if(matar[a]==0) matar[a]= &defmaterial;
2214                 if(matar[a]->ren->texco & TEXCO_ORCO) {
2215                         need_orco= 1;
2216                 }
2217         }
2218
2219         /* bevelcurve in displist */
2220         dlbev.first= dlbev.last= 0;
2221
2222         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj!=NULL) {
2223                 makebevelcurve(ob, &dlbev);
2224         }
2225
2226         /* uv orcos? count amount of points and malloc */
2227         if(need_orco && (cu->flag & CU_UV_ORCO)) {
2228                 if(cu->flag & CU_PATH);
2229                 else {
2230                         totvert= 0;
2231                         bl= cu->bev.first;
2232                         while(bl) {
2233                                 dlb= dlbev.first;
2234                                 while(dlb) {
2235                                         totvert+= dlb->nr*bl->nr;
2236                                         dlb= dlb->next;
2237                                 }
2238                                 bl= bl->next;
2239                         }
2240
2241                         if(totvert) {
2242                                 fp= cu->orco= MEM_mallocN(3*sizeof(float)*totvert, "cu->orco");
2243         
2244                                 bl= cu->bev.first;
2245                                 while(bl) {
2246                                         dlb= dlbev.first;
2247                                         while(dlb) {
2248                                                 for(b=0; b<dlb->nr; b++) {
2249                                                         fac= (2.0*b/(float)(dlb->nr-1)) - 1.0;
2250                                                         for(a=0; a<bl->nr; a++, fp+=3) {
2251                                                                 fp[0]= (2.0*a/(float)(bl->nr-1)) - 1.0;
2252                                                                 fp[1]= fac;
2253                                                                 fp[2]= 0.0;
2254                                                         }
2255                                                 }
2256                                                 dlb= dlb->next;
2257                                         }
2258                                         bl= bl->next;
2259                                 }
2260                         }
2261                 }
2262         }
2263
2264         if(ob->parent && ob->parent->type==OB_LATTICE) {
2265                 lt= ob->parent->data;
2266                 init_latt_deform(ob->parent, ob);
2267                 need_orco= 1;
2268         }
2269         
2270         if(ob->parent && ob->parent->type==OB_IKA) {
2271                 ika= ob->parent->data;
2272                 init_skel_deform(ob->parent, ob);
2273                 need_orco= 1;
2274         }
2275
2276         if(ob->parent && ob->parent->type==OB_ARMATURE) {
2277                 init_armature_deform(ob->parent, ob);
2278                 need_orco= 1;
2279         }
2280
2281         /* do keypos? NOTE: watch it : orcos */
2282
2283         /* effect on text? */
2284
2285         /* boundboxclip still todo */
2286
2287         /* side faces of poly:  work with bevellist */
2288         widfac= (cu->width-1.0);
2289
2290         bl= cu->bev.first;
2291         nu= cu->nurb.first;
2292         while(bl) {
2293
2294                 if(dlbev.first) {    /* otherwise just a poly */
2295
2296                         dlb= dlbev.first;   /* bevel loop */
2297                         while(dlb) {
2298                                 data= MEM_mallocN(3*sizeof(float)*dlb->nr*bl->nr, "init_render_curve3");
2299                                 fp= data;
2300
2301                                 /* for each point at bevelcurve do the entire poly */
2302                                 fp1= dlb->verts;
2303                                 b= dlb->nr;
2304                                 while(b--) {
2305
2306                                         bevp= (BevPoint *)(bl+1);
2307                                         for(a=0; a<bl->nr; a++) {
2308                                                 float fac;
2309                                                 
2310                                                 /* returns 1.0 if no taper, of course */
2311                                                 fac= calc_taper(cu->taperobj, a, bl->nr);
2312
2313                                                 if(cu->flag & CU_3D) {
2314                                                         vec[0]= fp1[1]+widfac;
2315                                                         vec[1]= fp1[2];
2316                                                         vec[2]= 0.0;
2317
2318                                                         MTC_Mat3MulVecfl(bevp->mat, vec);
2319
2320                                                         fp[0]= bevp->x+ fac*vec[0];
2321                                                         fp[1]= bevp->y+ fac*vec[1];
2322                                                         fp[2]= bevp->z+ fac*vec[2];
2323                                                 }
2324                                                 else {
2325
2326                                                         fp[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina;
2327                                                         fp[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa;
2328                                                         fp[2]= bevp->z+ fac*fp1[2];
2329                                                         /* do not MatMul here: polyfill should work uniform, independent which frame */
2330                                                 }
2331                                                 fp+= 3;
2332                                                 bevp++;
2333                                         }
2334                                         fp1+=3;
2335                                 }
2336
2337                                 /* make render vertices */
2338                                 fp= data;
2339                                 startvert= R.totvert;
2340                                 nr= dlb->nr*bl->nr;
2341
2342                                 while(nr--) {
2343                                         ver= RE_findOrAddVert(R.totvert++);
2344                                         
2345                                         if(lt) calc_latt_deform(fp);
2346                                         else if(ika) calc_skel_deform(ika, fp);
2347                                         
2348                                         VECCOPY(ver->co, fp);
2349                                         MTC_Mat4MulVecfl(mat, ver->co);
2350                                         fp+= 3;
2351                                 }
2352
2353                                 startvlak= R.totvlak;
2354
2355                                 for(a=0; a<dlb->nr; a++) {
2356
2357                                         frontside= (a >= dlb->nr/2);
2358
2359                                         DL_SURFINDEX(bl->poly>0, dlb->type==DL_POLY, bl->nr, dlb->nr);
2360                                         p1+= startvert;
2361                                         p2+= startvert;
2362                                         p3+= startvert;
2363                                         p4+= startvert;
2364
2365                                         for(; b<bl->nr; b++) {
2366
2367                                                 vlr= RE_findOrAddVlak(R.totvlak++);
2368                                                 vlr->ob= ob;
2369                                                 vlr->v1= RE_findOrAddVert(p2);
2370                                                 vlr->v2= RE_findOrAddVert(p1);
2371                                                 vlr->v3= RE_findOrAddVert(p3);
2372                                                 vlr->v4= RE_findOrAddVert(p4);
2373                                                 vlr->ec= ME_V2V3+ME_V3V4;
2374                                                 if(a==0) vlr->ec+= ME_V1V2;
2375
2376                                                 vlr->flag= nu->flag;
2377                                                 vlr->lay= ob->lay;
2378
2379                                                 /* this is not really scientific: the vertices
2380                                                  * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
2381                                                  * front and backside treated different!!
2382                                                  */
2383
2384                                                 if(frontside)
2385                                                         CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
2386                                                 else 
2387                                                         CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
2388
2389                                                 vlr->mat= matar[ nu->mat_nr ];
2390
2391                                                 p4= p3;
2392                                                 p3++;
2393                                                 p2= p1;
2394                                                 p1++;
2395
2396                                         }
2397
2398                                 }
2399
2400                                 /* here was split_u before, for split off standard bevels, not needed anymore */
2401                                 /* but it could check on the bevel-curve BevPoints for u-split though... */
2402                                 
2403                                 /* make double points: SPLIT BEVELS */
2404                                 bevp= (BevPoint *)(bl+1);
2405                                 for(a=0; a<bl->nr; a++) {
2406                                         if(bevp->f1)
2407                                                 split_v_renderfaces(startvlak, startvert, bl->nr, dlb->nr, a, bl->poly>0,
2408                                                     dlb->type==DL_POLY);
2409                                         bevp++;
2410                                 }
2411
2412                                 /* vertex normals */
2413                                 for(a= startvlak; a<R.totvlak; a++) {
2414                                         vlr= RE_findOrAddVlak(a);
2415
2416                                         VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
2417                                         VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
2418                                         VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
2419                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
2420                                 }
2421                                 for(a=startvert; a<R.totvert; a++) {
2422                                         ver= RE_findOrAddVert(a);
2423                                         len= Normalise(ver->n);
2424                                         if(len==0.0) ver->sticky= (float *)1;
2425                                         else ver->sticky= 0;
2426                                 }
2427                                 for(a= startvlak; a<R.totvlak; a++) {
2428                                         vlr= RE_findOrAddVlak(a);
2429                                         if(vlr->v1->sticky) VECCOPY(vlr->v1->n, vlr->n);
2430                                         if(vlr->v2->sticky) VECCOPY(vlr->v2->n, vlr->n);
2431                                         if(vlr->v3->sticky) VECCOPY(vlr->v3->n, vlr->n);
2432                                         if(vlr->v4->sticky) VECCOPY(vlr->v4->n, vlr->n);
2433                                 }
2434
2435                                 dlb= dlb->next;
2436
2437                                 MEM_freeN(data);
2438                         }
2439
2440                 }
2441                 bl= bl->next;
2442                 nu= nu->next;
2443         }
2444
2445         if(dlbev.first) {
2446                 freedisplist(&dlbev);
2447         }
2448
2449         if(cu->flag & CU_PATH) return;
2450
2451         /* from displist the filled faces can be extracted */
2452         dl= cu->disp.first;
2453
2454         while(dl) {
2455                 if(dl->type==DL_INDEX3) {
2456                         startvert= R.totvert;
2457                         data= dl->verts;
2458
2459                         n[0]= ob->imat[0][2];
2460                         n[1]= ob->imat[1][2];
2461                         n[2]= ob->imat[2][2];
2462                         Normalise(n);
2463
2464                         /* copy first, rotate later for comparision trick */
2465                         for(a=0; a<dl->nr; a++, data+=3) {
2466                                 ver= RE_findOrAddVert(R.totvert++);
2467                                 VECCOPY(ver->co, data);
2468
2469                                 if(ver->co[2] < 0.0) {
2470                                         VECCOPY(ver->n, n);
2471                                 }
2472                                 else {
2473                                         ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
2474                                 }
2475                         }
2476
2477                         startvlak= R.totvlak;
2478                         index= dl->index;
2479                         for(a=0; a<dl->parts; a++, index+=3) {
2480
2481                                 vlr= RE_findOrAddVlak(R.totvlak++);
2482                                 vlr->ob = ob;   /* yafray: correction for curve rendering, obptr was not set */
2483                                 vlr->v1= RE_findOrAddVert(startvert+index[0]);
2484                                 vlr->v2= RE_findOrAddVert(startvert+index[1]);
2485                                 vlr->v3= RE_findOrAddVert(startvert+index[2]);
2486                                 vlr->v4= NULL;
2487                                 
2488                                 if(vlr->v1->co[2] < 0.0) {
2489                                         VECCOPY(vlr->n, n);
2490                                 }
2491                                 else {
2492                                         vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
2493                                 }
2494                                 
2495                                 vlr->mat= matar[ dl->col ];
2496                                 vlr->flag= 0;
2497                                 if( (cu->flag & CU_NOPUNOFLIP) || (vlr->mat->mode & MA_RAYTRANSP)) {
2498                                         vlr->flag |= R_NOPUNOFLIP;
2499                                 }
2500                                 vlr->ec= 0;
2501                                 vlr->lay= ob->lay;
2502                         }
2503                         /* rotate verts */
2504                         for(a=0; a<dl->nr; a++) {
2505                                 ver= RE_findOrAddVert(startvert+a);
2506                                 MTC_Mat4MulVecfl(mat, ver->co);
2507                         }
2508                         
2509                 }
2510                 dl= dl->next;
2511         }
2512
2513         if(lt) {
2514                 end_latt_deform();
2515         }
2516
2517         if(need_orco) { /* the stupid way: should be replaced; taking account for keys! */
2518
2519                 VECCOPY(size, cu->size);
2520
2521                 nr= R.totvert-firststartvert;
2522                 if(nr) {
2523                         if(cu->orco) {
2524                                 fp= cu->orco;
2525                                 while(nr--) {
2526                                         ver= RE_findOrAddVert(firststartvert++);
2527                                         ver->orco= fp;
2528                                         fp+= 3;
2529                                 }
2530                         }
2531                         else {
2532                                 fp= cu->orco= MEM_mallocN(sizeof(float)*3*nr, "cu orco");
2533                                 while(nr--) {
2534                                         ver= RE_findOrAddVert(firststartvert++);
2535                                         ver->orco= fp;
2536
2537                                         VECCOPY(fp, ver->co);
2538                                         MTC_Mat4MulVecfl(ob->imat, fp);
2539
2540                                         fp[0]= (fp[0]-cu->loc[0])/size[0];
2541                                         fp[1]= (fp[1]-cu->loc[1])/size[1];
2542                                         fp[2]= (fp[2]-cu->loc[2])/size[2];
2543                                         fp+= 3;
2544                                 }
2545                         }
2546                 }
2547         }
2548 }
2549
2550 /* prevent phong interpolation for giving ray shadow errors (terminator problem) */
2551 static void set_phong_threshold(Object *ob, int startface, int numface, int startvert, int numvert )
2552 {
2553         VertRen *ver;
2554         VlakRen *vlr;
2555         float thresh= 0.0, dot;
2556         int tot=0, i;
2557         
2558         /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger 
2559            are taken into account. This threshold is meant to work on smooth geometry, not
2560            for extreme cases (ton) */
2561         
2562         for(i=startface; i<startface+numface; i++) {
2563                 vlr= RE_findOrAddVlak(i);
2564                 if(vlr->flag & R_SMOOTH) {
2565                         dot= INPR(vlr->n, vlr->v1->n);
2566                         dot= ABS(dot);
2567                         if(dot>0.9) {
2568                                 thresh+= dot; tot++;
2569                         }
2570                         dot= INPR(vlr->n, vlr->v2->n);
2571                         dot= ABS(dot);
2572                         if(dot>0.9) {
2573                                 thresh+= dot; tot++;
2574                         }
2575
2576                         dot= INPR(vlr->n, vlr->v3->n);
2577                         dot= ABS(dot);
2578                         if(dot>0.9) {
2579                                 thresh+= dot; tot++;
2580                         }
2581
2582                         if(vlr->v4) {
2583                                 dot= INPR(vlr->n, vlr->v4->n);
2584                                 dot= ABS(dot);
2585                                 if(dot>0.9) {
2586                                         thresh+= dot; tot++;
2587                                 }
2588                         }
2589                 }
2590         }
2591         
2592         if(tot) {
2593                 thresh/= (float)tot;
2594                 ob->smoothresh= cos(0.5*M_PI-acos(thresh));
2595         }
2596 }
2597
2598 static void init_render_object(Object *ob)
2599 {
2600         float mat[4][4];
2601         int startface, startvert;
2602         
2603         startface=R.totvlak;
2604         startvert=R.totvert;
2605
2606         ob->flag |= OB_DONE;
2607
2608         if(ob->type==OB_LAMP)
2609                 RE_add_render_lamp(ob, 1);
2610         else if ELEM(ob->type, OB_FONT, OB_CURVE)
2611                 init_render_curve(ob);
2612         else if(ob->type==OB_SURF)
2613                 init_render_surf(ob);
2614         else if(ob->type==OB_MESH)
2615                 init_render_mesh(ob);
2616         else if(ob->type==OB_MBALL)
2617                 init_render_mball(ob);
2618         else {
2619                 MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
2620                 MTC_Mat4Invert(ob->imat, mat);
2621         }
2622         
2623         /* generic post process here */
2624         if(startvert!=R.totvert) {
2625         
2626                 /* the exception below is because displace code now is in init_render_mesh call, 
2627                 I will look at means to have autosmooth enabled for all object types 
2628                 and have it as general postprocess, like displace */
2629                 if (ob->type!=OB_MESH && test_for_displace( ob ) ) 
2630                         do_displacement(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
2631         
2632                 /* phong normal interpolation can cause error in tracing (terminator prob) */
2633                 ob->smoothresh= 0.0;
2634                 if( (R.r.mode & R_RAYTRACE) && (R.r.mode & R_SHADOW) ) 
2635                         set_phong_threshold(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
2636         }
2637 }
2638
2639 void RE_freeRotateBlenderScene(void)
2640 {
2641         ShadBuf *shb;
2642         Object *ob = NULL;
2643         Mesh *me;
2644         Curve *cu;
2645         DispList *dl;
2646         unsigned long *ztile;
2647         int a, b, v;
2648         char *ctile;
2649
2650         /* FREE */
2651
2652         for(a=0; a<R.totlamp; a++) {
2653                 if(R.la[a]->shb) {
2654                         shb= R.la[a]->shb;
2655                         v= (shb->size*shb->size)/256;
2656                         ztile= shb->zbuf;
2657                         ctile= shb->cbuf;
2658                         for(b=0; b<v; b++, ztile++, ctile++) {
2659                                 if(*ctile) MEM_freeN((void *) *ztile);
2660                         }
2661                         
2662                         MEM_freeN(shb->zbuf);
2663                         MEM_freeN(shb->cbuf);
2664                         MEM_freeN(R.la[a]->shb);
2665                 }
2666                 if(R.la[a]->org) MEM_freeN(R.la[a]->org);
2667                 if(R.la[a]->jitter) MEM_freeN(R.la[a]->jitter);
2668                 MEM_freeN(R.la[a]);
2669         }
2670         a=0;
2671         while(R.blove[a]) {
2672                 MEM_freeN(R.blove[a]);
2673                 R.blove[a]=0;
2674                 a++;
2675         }
2676         a=0;
2677         while(R.blovl[a]) {
2678                 MEM_freeN(R.blovl[a]);
2679                 R.blovl[a]=0;
2680                 a++;
2681         }
2682         a=0;
2683         while(R.bloha[a]) {
2684                 MEM_freeN(R.bloha[a]);
2685                 R.bloha[a]=0;
2686                 a++;
2687         }
2688
2689         /* free orco. check all objects because of duplis and sets */
2690         ob= G.main->object.first;
2691         while(ob) {
2692
2693                 if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
2694                         cu= ob->data;
2695                         if(cu->orco) {
2696                                 MEM_freeN(cu->orco);
2697                                 cu->orco= 0;
2698                         }
2699                 }
2700                 else if(ob->type==OB_MESH) {
2701                         me= ob->data;
2702                         if(me->orco) {
2703                                 MEM_freeN(me->orco);
2704                                 me->orco= 0;
2705                         }
2706                         if (mesh_uses_displist(me) && ((me->subdiv!=me->subdivr) || (ob->effect.first != NULL) || ob==G.obedit) ) { 
2707                             /* Need to recalc for effects since they are time dependant */
2708                                 makeDispList(ob);  /* XXX this should be replaced with proper caching */
2709                                 me->subdivdone= 0;      /* needed to prevent multiple used meshes being recalculated */
2710                         }
2711                 }
2712                 else if(ob->type==OB_MBALL) {
2713                         if(ob->disp.first && ob->disp.first!=ob->disp.last) {
2714                                 dl= ob->disp.first;
2715                                 BLI_remlink(&ob->disp, dl);
2716                                 freedisplist(&ob->disp);
2717                                 BLI_addtail(&ob->disp, dl);
2718                         }
2719                 }
2720                 ob= ob->id.next;
2721         }
2722
2723         end_render_textures();
2724         end_render_materials();
2725         end_radio_render();
2726         
2727         R.totvlak=R.totvert=R.totlamp=R.tothalo= 0;
2728 }
2729
2730 /* per face check if all samples should be taken.
2731    if raytrace, do always for raytraced material, or when material full_osa set */
2732 static void set_fullsample_flag(void)
2733 {
2734         VlakRen *vlr;
2735         int a, trace;
2736
2737         trace= R.r.mode & R_RAYTRACE;
2738         
2739         for(a=R.totvlak-1; a>=0; a--) {
2740                 vlr= RE_findOrAddVlak(a);
2741                 
2742                 if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA;
2743                 else if(trace) {
2744                         if(vlr->mat->mode & MA_SHLESS);
2745                         else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR|MA_SHADOW))
2746                                 vlr->flag |= R_FULL_OSA;
2747                 }
2748         }
2749 }
2750
2751 /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp */
2752 #ifdef FLT_EPSILON
2753 #undef FLT_EPSILON
2754 #endif
2755 #define FLT_EPSILON 1.19209290e-06F
2756
2757
2758 static void check_non_flat_quads(void)
2759 {
2760         VlakRen *vlr, *vlr1;
2761         VertRen *v1, *v2, *v3, *v4;
2762         float nor[3], xn, flen;
2763         int a;
2764
2765         for(a=R.totvlak-1; a>=0; a--) {
2766                 vlr= RE_findOrAddVlak(a);
2767                 
2768                 /* test if rendering as a quad or triangle, skip wire */
2769                 if(vlr->v4 && (vlr->mat->mode & MA_WIRE)==0) {
2770                         
2771                         /* check if quad is actually triangle */
2772                         v1= vlr->v1;
2773                         v2= vlr->v2;
2774                         v3= vlr->v3;
2775                         v4= vlr->v4;
2776                         VECSUB(nor, v1->co, v2->co);
2777                         if( ABS(nor[0])<FLT_EPSILON &&  ABS(nor[1])<FLT_EPSILON && ABS(nor[2])<FLT_EPSILON ) {
2778                                 vlr->v1= v2;
2779                                 vlr->v2= v3;
2780                                 vlr->v3= v4;
2781                                 vlr->v4= NULL;
2782                         }
2783                         else {
2784                                 VECSUB(nor, v2->co, v3->co);
2785                                 if( ABS(nor[0])<FLT_EPSILON &&  ABS(nor[1])<FLT_EPSILON && ABS(nor[2])<FLT_EPSILON ) {
2786                                         vlr->v2= v3;
2787                                         vlr->v3= v4;
2788                                         vlr->v4= NULL;
2789                                 }
2790                                 else {
2791                                         VECSUB(nor, v3->co, v4->co);
2792                                         if( ABS(nor[0])<FLT_EPSILON &&  ABS(nor[1])<FLT_EPSILON && ABS(nor[2])<FLT_EPSILON ) {
2793                                                 vlr->v4= NULL;
2794                                         }
2795                                         else {
2796