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