- added Mesh->derived and Mesh->decimated DerivedMesh pointers
[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                 int needsFree;
1358                 DerivedMesh *dm = mesh_get_derived_render(ob, &needsFree);
1359                 dlm = dm->convertToDispListMesh(dm);
1360                 if (needsFree) {
1361                         dm->release(dm);
1362                 }
1363
1364                 mvert= dlm->mvert;
1365                 totvert= dlm->totvert;
1366
1367                 ms= NULL; // no stick in displistmesh
1368         } else {
1369                 DispList *dl;
1370
1371                 dlm= NULL;
1372                 mvert= me->mvert;
1373                 totvert= me->totvert;
1374
1375                 dl= find_displist(&ob->disp, DL_VERTS);
1376                 if(dl) extverts= dl->verts;
1377         
1378                 ms= me->msticky;
1379         }
1380         
1381         orco= me->orco;
1382
1383         ma= give_render_material(ob, 1);
1384
1385         if(ma->mode & MA_HALO) {
1386                 make_render_halos(ob, me, totvert, mvert, ma, extverts);
1387         }
1388         else {
1389
1390                 for(a=0; a<totvert; a++, mvert++) {
1391
1392                         ver= RE_findOrAddVert(R.totvert++);
1393                         if(extverts) {
1394                                 VECCOPY(ver->co, extverts);
1395                                 extverts+= 3;
1396                         }
1397                         else {
1398                                 VECCOPY(ver->co, mvert->co);
1399                         }
1400                         MTC_Mat4MulVecfl(mat, ver->co);
1401
1402                         xn= mvert->no[0];
1403                         yn= mvert->no[1];
1404                         zn= mvert->no[2];
1405                         if(do_puno==0) {
1406                                 /* transpose ! */
1407                                 ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1408                                 ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1409                                 ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1410                                 Normalise(ver->n);
1411                         }
1412                         if(orco) {
1413                                 ver->orco= orco;
1414                                 orco+=3;
1415                         }
1416                         if(ms) {
1417                                 ver->sticky= (float *)ms;
1418                                 ms++;
1419                         }
1420                 }
1421                 /* still to do for keys: the correct local texture coordinate */
1422
1423                 /* faces in order of color blocks */
1424                 vertofs= R.totvert - totvert;
1425                 for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
1426
1427                         ma= give_render_material(ob, a1+1);
1428                         
1429                         /* test for 100% transparant */
1430                         ok= 1;
1431                         if(ma->alpha==0.0 && ma->spectra==0.0) {
1432                                 ok= 0;
1433                                 /* texture on transparency? */
1434                                 for(a=0; a<MAX_MTEX; a++) {
1435                                         if(ma->mtex[a] && ma->mtex[a]->tex) {
1436                                                 if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1;
1437                                         }
1438                                 }
1439                         }
1440
1441                         if(ok) {
1442                                 TFace *tface= NULL;
1443
1444                                 /* radio faces need autosmooth, to separate shared vertices in corners */
1445                                 if(R.r.mode & R_RADIO)
1446                                         if(ma->mode & MA_RADIO) 
1447                                                 do_autosmooth= 1;
1448                                 
1449                                 start= 0;
1450                                 end= dlm?dlm->totface:me->totface;
1451                                 set_buildvars(ob, &start, &end);
1452                                 if (dlm) {
1453                                         mface= dlm->mface + start;
1454                                         if (dlm->tface) {
1455                                                 tface= dlm->tface + start;
1456                                                 vertcol= NULL;
1457                                         } else if (dlm->mcol) {
1458                                                 vertcol= (unsigned int *)dlm->mcol;
1459                                         } else {
1460                                                 vertcol= NULL;
1461                                         }
1462                                 } else {
1463                                         mface= ((MFace*) me->mface) + start;
1464                                         if (me->tface) {
1465                                                 tface= ((TFace*) me->tface) + start;
1466                                                 vertcol= NULL;
1467                                         } else if (me->mcol) {
1468                                                 vertcol= (unsigned int *)me->mcol;
1469                                         } else {
1470                                                 vertcol= NULL;
1471                                         }
1472                                 }
1473
1474                                 for(a=start; a<end; a++) {
1475                                         int v1, v2, v3, v4, edcode, flag;
1476                                         
1477                                         if( mface->mat_nr==a1 ) {
1478                                                 v1= mface->v1;
1479                                                 v2= mface->v2;
1480                                                 v3= mface->v3;
1481                                                 v4= mface->v4;
1482                                                 flag= mface->flag;
1483                                                 edcode= mface->edcode;
1484                                                 
1485                                                 /* cannot use edges data for render, this has no vcol or tface... */
1486                                                 if(dlm && (dlm->flag & ME_OPT_EDGES)==0) edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1;
1487                                                 
1488                                                 if(v3) {
1489                                                         float len;
1490                                                         
1491                                                         vlr= RE_findOrAddVlak(R.totvlak++);
1492                                                         vlr->ob= vlr_set_ob(ob);
1493                                                         vlr->v1= RE_findOrAddVert(vertofs+v1);
1494                                                         vlr->v2= RE_findOrAddVert(vertofs+v2);
1495                                                         vlr->v3= RE_findOrAddVert(vertofs+v3);
1496                                                         if(v4) vlr->v4= RE_findOrAddVert(vertofs+v4);
1497                                                         else vlr->v4= 0;
1498
1499                                                         /* render normals are inverted in render */
1500                                                         if(vlr->v4) len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co,
1501                                                             vlr->v1->co, vlr->n);
1502                                                         else len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co,
1503                                                             vlr->n);
1504
1505                                                         vlr->mat= ma;
1506                                                         vlr->flag= flag;
1507                                                         if((me->flag & ME_NOPUNOFLIP) ) {
1508                                                                 vlr->flag |= R_NOPUNOFLIP;
1509                                                         }
1510                                                         vlr->ec= edcode;
1511                                                         vlr->lay= ob->lay;
1512
1513                                                         if(len==0) R.totvlak--;
1514                                                         else {
1515                                                                 if(dlm) {
1516                                                                         if(tface) {
1517                                                                                 vlr->tface= BLI_memarena_alloc(R.memArena, sizeof(*vlr->tface));
1518                                                                                 vlr->vcol= vlr->tface->col;
1519                                                                                 memcpy(vlr->tface, tface, sizeof(*tface));
1520                                                                         } 
1521                                                                         else if (vertcol) {
1522                                                                                 vlr->vcol= BLI_memarena_alloc(R.memArena, sizeof(int)*16);
1523                                                                                 memcpy(vlr->vcol, vertcol+4*a, sizeof(int)*16);
1524                                                                         }
1525                                                                 } else {
1526                                                                         if(tface) {
1527                                                                                 vlr->vcol= tface->col;
1528                                                                                 vlr->tface= tface;
1529                                                                         } 
1530                                                                         else if (vertcol) {
1531                                                                                 vlr->vcol= vertcol+4*a;
1532                                                                         }
1533                                                                 }
1534                                                         }
1535                                                 }
1536                                                 else if(v2 && (ma->mode & MA_WIRE)) {
1537                                                         vlr= RE_findOrAddVlak(R.totvlak++);
1538                                                         vlr->ob= vlr_set_ob(ob);
1539                                                         vlr->v1= RE_findOrAddVert(vertofs+v1);
1540                                                         vlr->v2= RE_findOrAddVert(vertofs+v2);
1541                                                         vlr->v3= vlr->v2;
1542                                                         vlr->v4= 0;
1543
1544                                                         vlr->n[0]=vlr->n[1]=vlr->n[2]= 0.0;
1545
1546                                                         vlr->mat= ma;
1547                                                         vlr->flag= flag;
1548                                                         vlr->ec= ME_V1V2;
1549                                                         vlr->lay= ob->lay;
1550                                                 }
1551                                         }
1552
1553                                         mface++;
1554                                         if(tface) tface++;
1555                                 }
1556                         }
1557                 }
1558                 
1559                 /* exception... we do edges for wire mode. potential conflict when faces exist... */
1560                 end= dlm?dlm->totedge:me->totedge;
1561                 ma= give_render_material(ob, 1);
1562                 if(end && (ma->mode & MA_WIRE)) {
1563                         MEdge *medge;
1564                         medge= dlm?dlm->medge:me->medge;
1565                         for(a1=0; a1<end; a1++, medge++) {
1566                                 vlr= RE_findOrAddVlak(R.totvlak++);
1567                                 vlr->ob= vlr_set_ob(ob);
1568                                 vlr->v1= RE_findOrAddVert(vertofs+medge->v1);
1569                                 vlr->v2= RE_findOrAddVert(vertofs+medge->v2);
1570                                 vlr->v3= vlr->v2;
1571                                 vlr->v4= NULL;
1572                                 
1573                                 vlr->n[0]=vlr->n[1]=vlr->n[2]= 0.0;
1574                                 
1575                                 vlr->mat= ma;
1576                                 vlr->flag= 0;
1577                                 vlr->ec= ME_V1V2;
1578                                 vlr->lay= ob->lay;
1579                         }
1580                 }
1581         }
1582         
1583         if(do_puno) {
1584                 calc_vertexnormals(totverto, totvlako);
1585                 do_puno= 0;
1586         }
1587         
1588         if (test_for_displace( ob ) ) 
1589                 do_displacement(ob, totvlako, R.totvlak-totvlako, totverto, R.totvert-totverto);
1590
1591         if(do_autosmooth || (me->flag & ME_AUTOSMOOTH)) {
1592                 autosmooth(totverto, totvlako, me->smoothresh);
1593                 do_puno= 1;
1594         }
1595         
1596         if(do_puno) calc_vertexnormals(totverto, totvlako);
1597         
1598         mesh_modifier(ob, 'e');  // end
1599
1600         if(dlm) displistmesh_free(dlm);
1601 }
1602
1603 /* ------------------------------------------------------------------------- */
1604
1605 static void area_lamp_vectors(LampRen *lar)
1606 {
1607         float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey;
1608
1609         /* corner vectors */
1610         lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
1611         lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
1612         lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
1613
1614         /* corner vectors */
1615         lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
1616         lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
1617         lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
1618
1619         /* corner vectors */
1620         lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
1621         lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
1622         lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
1623
1624         /* corner vectors */
1625         lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
1626         lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
1627         lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
1628         /* only for correction button size, matrix size works on energy */
1629         lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
1630 }
1631
1632 /* If lar takes more lamp data, the decoupling will be better. */
1633 void RE_add_render_lamp(Object *ob, int doshadbuf)
1634 {
1635         Lamp *la;
1636         LampRen *lar, **temp;
1637         float mat[4][4], hoek, xn, yn;
1638         int c;
1639         static int rlalen=LAMPINITSIZE; /*number of currently allocated lampren pointers*/
1640         
1641         if(R.totlamp>=rlalen) { /* Need more Lamp pointers....*/
1642                 printf("Alocating %i more lamp groups, %i total.\n", 
1643                         LAMPINITSIZE, rlalen+LAMPINITSIZE);
1644                 temp=R.la;
1645                 R.la=(LampRen**)MEM_callocN(sizeof(void*)*(rlalen+LAMPINITSIZE) , "renderlamparray");
1646                 memcpy(R.la, temp, rlalen*sizeof(void*));
1647                 memset(&(R.la[R.totlamp]), 0, LAMPINITSIZE*sizeof(void*));
1648                 rlalen+=LAMPINITSIZE;  
1649                 MEM_freeN(temp);        
1650         }
1651         
1652         la= ob->data;
1653         lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
1654         R.la[R.totlamp++]= lar;
1655
1656         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
1657         MTC_Mat4Invert(ob->imat, mat);
1658
1659         MTC_Mat3CpyMat4(lar->mat, mat);
1660         MTC_Mat3CpyMat4(lar->imat, ob->imat);
1661
1662         lar->bufsize = la->bufsize;
1663         lar->samp = la->samp;
1664         lar->soft = la->soft;
1665         lar->shadhalostep = la->shadhalostep;
1666         lar->clipsta = la->clipsta;
1667         lar->clipend = la->clipend;
1668         lar->bias = la->bias;
1669
1670         lar->type= la->type;
1671         lar->mode= la->mode;
1672
1673         lar->energy= la->energy;
1674         lar->energy= la->energy;
1675         if(la->mode & LA_NEG) lar->energy= -lar->energy;
1676
1677         lar->vec[0]= -mat[2][0];
1678         lar->vec[1]= -mat[2][1];
1679         lar->vec[2]= -mat[2][2];
1680         Normalise(lar->vec);
1681         lar->co[0]= mat[3][0];
1682         lar->co[1]= mat[3][1];
1683         lar->co[2]= mat[3][2];
1684         lar->dist= la->dist;
1685         lar->haint= la->haint;
1686         lar->distkw= lar->dist*lar->dist;
1687         lar->r= lar->energy*la->r;
1688         lar->g= lar->energy*la->g;
1689         lar->b= lar->energy*la->b;
1690         lar->k= la->k;
1691
1692         // area
1693         lar->ray_samp= la->ray_samp;
1694         lar->ray_sampy= la->ray_sampy;
1695         lar->ray_sampz= la->ray_sampz;
1696
1697         lar->area_size= la->area_size;
1698         lar->area_sizey= la->area_sizey;
1699         lar->area_sizez= la->area_sizez;
1700
1701         lar->area_shape= la->area_shape;
1702         lar->ray_samp_type= la->ray_samp_type;
1703
1704         if(lar->type==LA_AREA) {
1705                 switch(lar->area_shape) {
1706                 case LA_AREA_SQUARE:
1707                         lar->ray_totsamp= lar->ray_samp*lar->ray_samp;
1708                         lar->ray_sampy= lar->ray_samp;
1709                         lar->area_sizey= lar->area_size;
1710                         break;
1711                 case LA_AREA_RECT:
1712                         lar->ray_totsamp= lar->ray_samp*lar->ray_sampy;
1713                         break;
1714                 case LA_AREA_CUBE:
1715                         lar->ray_totsamp= lar->ray_samp*lar->ray_samp*lar->ray_samp;
1716                         lar->ray_sampy= lar->ray_samp;
1717                         lar->ray_sampz= lar->ray_samp;
1718                         lar->area_sizey= lar->area_size;
1719                         lar->area_sizez= lar->area_size;
1720                         break;
1721                 case LA_AREA_BOX:
1722                         lar->ray_totsamp= lar->ray_samp*lar->ray_sampy*lar->ray_sampz;
1723                         break;
1724                 }
1725
1726                 area_lamp_vectors(lar);
1727         }
1728         else lar->ray_totsamp= 0;
1729         
1730         /* yafray: photonlight and other params */
1731         if (R.r.renderer==R_YAFRAY) {
1732                 lar->YF_numphotons = la->YF_numphotons;
1733                 lar->YF_numsearch = la->YF_numsearch;
1734                 lar->YF_phdepth = la->YF_phdepth;
1735                 lar->YF_useqmc = la->YF_useqmc;
1736                 lar->YF_causticblur = la->YF_causticblur;
1737                 lar->YF_ltradius = la->YF_ltradius;
1738                 lar->YF_bufsize = la->YF_bufsize;
1739         }
1740
1741         lar->spotsi= la->spotsize;
1742         if(lar->mode & LA_HALO) {
1743                 if(lar->spotsi>170.0) lar->spotsi= 170.0;
1744         }
1745         lar->spotsi= cos( M_PI*lar->spotsi/360.0 );
1746         lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
1747
1748         memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *));
1749
1750         lar->lay= ob->lay & 0xFFFFFF;   // higher 8 bits are localview layers
1751
1752         lar->ld1= la->att1;
1753         lar->ld2= la->att2;
1754
1755         if(lar->type==LA_SPOT) {
1756
1757                 Normalise(lar->imat[0]);
1758                 Normalise(lar->imat[1]);
1759                 Normalise(lar->imat[2]);
1760
1761                 xn= saacos(lar->spotsi);
1762                 xn= sin(xn)/cos(xn);
1763                 lar->spottexfac= 1.0/(xn);
1764
1765                 if(lar->mode & LA_ONLYSHADOW) {
1766                         if((lar->mode & (LA_SHAD|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW;
1767                 }
1768
1769         }
1770
1771         /* set flag for spothalo en initvars */
1772         if(la->type==LA_SPOT && (la->mode & LA_HALO)) {
1773                 if(la->haint>0.0) {
1774                         R.flag |= R_LAMPHALO;
1775
1776                         /* camera position (0,0,0) rotate around lamp */
1777                         lar->sh_invcampos[0]= -lar->co[0];
1778                         lar->sh_invcampos[1]= -lar->co[1];
1779                         lar->sh_invcampos[2]= -lar->co[2];
1780                         MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
1781
1782                         /* z factor, for a normalized volume */
1783                         hoek= saacos(lar->spotsi);
1784                         xn= lar->spotsi;
1785                         yn= sin(hoek);
1786                         lar->sh_zfac= yn/xn;
1787                         /* pre-scale */
1788                         lar->sh_invcampos[2]*= lar->sh_zfac;
1789
1790                 }
1791         }
1792
1793         for(c=0; c<MAX_MTEX; c++) {
1794                 if(la->mtex[c] && la->mtex[c]->tex) {
1795                         lar->mode |= LA_TEXTURE;
1796
1797                         if(R.flag & R_RENDERING) {
1798                                 if(R.osa) {
1799                                         if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX;
1800                                 }
1801                         }
1802                 }
1803         }
1804
1805         /* yafray: shadowbuffers only needed for internal render */
1806         if (R.r.renderer==R_INTERN)
1807         {
1808                 if( (R.r.mode & R_SHADOW) && (lar->mode & LA_SHAD) && (la->type==LA_SPOT) && doshadbuf ) {
1809                 /* Per lamp, one shadow buffer is made. */
1810                         RE_initshadowbuf(lar, ob->obmat);
1811                 }
1812         }
1813         
1814         /* yafray: shadow flag should not be cleared, only used with internal renderer */
1815         if (R.r.renderer==R_INTERN) {
1816                 /* to make sure we can check ray shadow easily in the render code */
1817                 if(lar->mode & LA_SHAD_RAY) {
1818                         if( (R.r.mode & R_RAYTRACE)==0)
1819                                 lar->mode &= ~LA_SHAD_RAY;
1820                 }
1821         }
1822 }
1823
1824 /* ------------------------------------------------------------------------- */
1825 static void init_render_surf(Object *ob)
1826 {
1827         extern Material defmaterial;    // initrender.c
1828         Nurb *nu=0;
1829         Curve *cu;
1830         ListBase displist;
1831         DispList *dl;
1832         VertRen *ver, *v1, *v2, *v3, *v4;
1833         VlakRen *vlr;
1834         Material *matar[32];
1835         float *data, *fp, *orco, n1[3], flen, mat[4][4];
1836         int len, a, need_orco=0, startvlak, startvert, p1, p2, p3, p4;
1837 #ifdef STRUBI
1838         int u, v;
1839         int sizeu, sizev;
1840         VlakRen *vlr1, *vlr2, *vlr3;
1841         float  vn[3]; // n2[3],
1842 #endif
1843
1844         cu= ob->data;
1845         nu= cu->nurb.first;
1846         if(nu==0) return;
1847
1848         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
1849         MTC_Mat4Invert(ob->imat, mat);
1850
1851         /* material array */
1852         memset(matar, 0, 4*32);
1853         matar[0]= &defmaterial;
1854         for(a=0; a<ob->totcol; a++) {
1855                 matar[a]= give_render_material(ob, a+1);
1856                 if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
1857                         need_orco= 1;
1858                 }
1859         }
1860
1861         if(ob->parent && (ob->parent->type==OB_IKA || ob->parent->type==OB_LATTICE)) need_orco= 1;
1862
1863         if(cu->orco==0 && need_orco) make_orco_surf(cu);
1864         orco= cu->orco;
1865
1866         curve_modifier(ob, 's');
1867
1868         /* make a complete new displist, the base-displist can be different */
1869         displist.first= displist.last= 0;
1870         nu= cu->nurb.first;
1871         while(nu) {
1872                 if(nu->pntsv>1) {
1873         //              if (dl->flag & DL_CYCLIC_V) {
1874                         len= nu->resolu*nu->resolv;
1875                         /* makeNurbfaces wants zeros */
1876
1877                         dl= MEM_callocN(sizeof(DispList)+len*3*sizeof(float), "makeDispList1");
1878                         dl->verts= MEM_callocN(len*3*sizeof(float), "makeDispList01");
1879                         BLI_addtail(&displist, dl);
1880
1881                         dl->parts= nu->resolu;  /* switched order, makeNurbfaces works that way... */
1882                         dl->nr= nu->resolv;
1883                         dl->col= nu->mat_nr;
1884                         dl->rt= nu->flag;
1885
1886                         data= dl->verts;
1887                         dl->type= DL_SURF;
1888                         /* if nurbs cyclic (u/v) set flags in displist accordingly */
1889                         if(nu->flagv & 1) dl->flag |= DL_CYCLIC_V;      
1890                         if(nu->flagu & 1) dl->flag |= DL_CYCLIC_U;
1891
1892                         makeNurbfaces(nu, data);
1893                 }
1894                 nu= nu->next;
1895         }
1896
1897         if(ob->parent && ob->parent->type==OB_LATTICE) {
1898                 init_latt_deform(ob->parent, ob);
1899                 dl= displist.first;
1900                 while(dl) {
1901
1902                         fp= dl->verts;
1903                         len= dl->nr*dl->parts;
1904                         for(a=0; a<len; a++, fp+=3)  calc_latt_deform(fp);
1905
1906                         dl= dl->next;
1907                 }
1908                 end_latt_deform();
1909         }
1910         
1911         /* note; deform will be included in modifier() later */
1912         curve_modifier(ob, 'e');
1913
1914         if(ob->partype==PARSKEL && ob->parent && ob->parent->type==OB_ARMATURE) {
1915 /*              bArmature *arm= ob->parent->data; */
1916                 init_armature_deform(ob->parent, ob);
1917                 dl= displist.first;
1918                 while(dl) {
1919
1920                         fp= dl->verts;
1921                         len= dl->nr*dl->parts;
1922                         for(a=0; a<len; a++, fp+=3)
1923                                 calc_armature_deform(ob->parent, fp, a);
1924
1925                         dl= dl->next;
1926                 }
1927         }
1928
1929         if(ob->parent && ob->parent->type==OB_IKA) {
1930                 Ika *ika= ob->parent->data;
1931                 
1932                 init_skel_deform(ob->parent, ob);
1933                 dl= displist.first;
1934                 while(dl) {
1935
1936                         fp= dl->verts;
1937                         len= dl->nr*dl->parts;
1938                         for(a=0; a<len; a++, fp+=3)  calc_skel_deform(ika, fp);
1939
1940                         dl= dl->next;
1941                 }
1942         }
1943
1944         dl= displist.first;
1945         /* walk along displaylist and create rendervertices/-faces */
1946         while(dl) {
1947 #ifdef STRUBI
1948 /* watch out: u ^= y, v ^= x !! */
1949                 if(dl->type==DL_SURF) {
1950                         startvert= R.totvert;
1951                         sizeu = dl->parts; sizev = dl->nr; 
1952
1953                         data= dl->verts;
1954                         for (u = 0; u < sizeu; u++) {
1955                                 v1 = RE_findOrAddVert(R.totvert++); /* save this for possible V wrapping */
1956                                 VECCOPY(v1->co, data); data += 3;
1957                                 if(orco) {
1958                                         v1->orco= orco; orco+= 3;
1959                                 }       
1960                                 MTC_Mat4MulVecfl(mat, v1->co);
1961
1962                                 for (v = 1; v < sizev; v++) {
1963                                         ver= RE_findOrAddVert(R.totvert++);
1964                                         VECCOPY(ver->co, data); data += 3;
1965                                         if(orco) {
1966                                                 ver->orco= orco; orco+= 3;
1967                                         }       
1968                                         MTC_Mat4MulVecfl(mat, ver->co);
1969                                 }
1970                                 /* if V-cyclic, add extra vertices at end of the row */
1971                                 if (dl->flag & DL_CYCLIC_V) {
1972                                         ver= RE_findOrAddVert(R.totvert++);
1973                                         VECCOPY(ver->co, v1->co);
1974                                         if(orco) {
1975                                                 ver->orco= orco;
1976                                                 orco+= 3;
1977                                         }
1978                                 }       
1979                         }       
1980
1981                         if (dl->flag & DL_CYCLIC_V)  sizev++; /* adapt U dimension */
1982
1983
1984                         /* if U cyclic, add extra row at end of column */
1985                         if (dl->flag & DL_CYCLIC_U) {
1986                                 for (v = 0; v < sizev; v++) {
1987                                         v1= RE_findOrAddVert(startvert + v);
1988                                         ver= RE_findOrAddVert(R.totvert++);
1989                                         VECCOPY(ver->co, v1->co);
1990                                         if(orco) {
1991                                                 ver->orco= orco;
1992                                                 orco +=3;
1993                                         }
1994                                 }
1995                                 sizeu++;
1996                         }       
1997                                         
1998
1999
2000
2001                         startvlak= R.totvlak;
2002
2003                         /* process generic surface */
2004                         for(u = 0; u < sizeu - 1; u++) {
2005 /*
2006                                 
2007                         ^       ()----p4----p3----()
2008                         |       |     |     |     |
2009                         u       |     |     |     |
2010                                 |     |     |     |
2011                                 ()----p1----p2----()
2012                                        v ->
2013 */
2014
2015                                 p1 = startvert + u * sizev; /* walk through face list */
2016                                 p2 = p1 + 1;
2017                                 p3 = p2 + sizev;
2018                                 p4 = p3 - 1;
2019
2020
2021                                 for(v = 0; v < sizev - 1; v++) {
2022                                         v1= RE_findOrAddVert(p1);
2023                                         v2= RE_findOrAddVert(p2);
2024                                         v3= RE_findOrAddVert(p3);
2025                                         v4= RE_findOrAddVert(p4);
2026
2027 /* normal len can be 0 if there are double nurbs control vertices 
2028         so zero area faces can be generated
2029         ->> there is at the moment no proper way to fix this except
2030         generating empty render faces */
2031
2032
2033                                         vlr= RE_findOrAddVlak(R.totvlak++);
2034                                         vlr->ob= vlr_set_ob(ob);
2035                                         vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
2036                                         
2037                                         flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
2038                                         VECCOPY(vlr->n, n1);
2039                                         
2040                                         vlr->lay= ob->lay;
2041                                         vlr->mat= matar[ dl->col];
2042                                         vlr->ec= ME_V1V2+ME_V2V3;
2043                                         vlr->flag= dl->rt;
2044                                         if( (cu->flag & CU_NOPUNOFLIP) ) {
2045                                                 vlr->flag |= R_NOPUNOFLIP;
2046                                         }
2047
2048                                         VecAddf(v1->n, v1->n, n1);
2049                                         VecAddf(v2->n, v2->n, n1);
2050                                         VecAddf(v3->n, v3->n, n1);
2051                                         VecAddf(v4->n, v4->n, n1);
2052
2053                                         p1++; p2++; p3++; p4++;
2054                                 }
2055                         }       
2056                         /* fix normals for U resp. V cyclic faces */
2057                         sizeu--; sizev--;  /* dec size for face array */
2058                         if (dl->flag & DL_CYCLIC_U) {
2059
2060                                 for (v = 0; v < sizev; v++)
2061                                 {
2062                                         /* optimize! :*/
2063                                         vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, v));
2064                                         vlr1= RE_findOrAddVlak(UVTOINDEX(0, v));
2065                                         VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
2066                                         VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
2067                                         VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
2068                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
2069                                 }
2070                         }
2071                         if (dl->flag & DL_CYCLIC_V) {
2072
2073                                 for (u = 0; u < sizeu; u++)
2074                                 {
2075                                         /* optimize! :*/
2076                                         vlr= RE_findOrAddVlak(UVTOINDEX(u, 0));
2077                                         vlr1= RE_findOrAddVlak(UVTOINDEX(u, sizev-1));
2078                                         VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
2079                                         VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
2080                                         VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
2081                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
2082                                 }
2083                         }
2084                         /* last vertex is an extra case: 
2085
2086                         ^       ()----()----()----()
2087                         |       |     |     ||     |
2088                         u       |     |(0,n)||(0,0)|
2089                                 |     |     ||     |
2090                                 ()====()====[]====()
2091                                 |     |     ||     |
2092                                 |     |(m,n)||(m,0)|
2093                                 |     |     ||     |
2094                                 ()----()----()----()
2095                                        v ->
2096
2097                         vertex [] is no longer shared, therefore distribute
2098                         normals of the surrounding faces to all of the duplicates of []
2099                         */
2100
2101                         if ((dl->flag & DL_CYCLIC_U) && (dl->flag & DL_CYCLIC_V))
2102                         {
2103                                 vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
2104                                 vlr1= RE_findOrAddVlak(UVTOINDEX(0,0));  /* (0,0) */
2105                                 VecAddf(vn, vlr->n, vlr1->n);
2106                                 vlr2= RE_findOrAddVlak(UVTOINDEX(0, sizev-1)); /* (0,n) */
2107                                 VecAddf(vn, vn, vlr2->n);
2108                                 vlr3= RE_findOrAddVlak(UVTOINDEX(sizeu-1, 0)); /* (m,0) */
2109                                 VecAddf(vn, vn, vlr3->n);
2110                                 VECCOPY(vlr->v3->n, vn);
2111                                 VECCOPY(vlr1->v1->n, vn);
2112                                 VECCOPY(vlr2->v2->n, vn);
2113                                 VECCOPY(vlr3->v4->n, vn);
2114                         }
2115                         for(a = startvert; a < R.totvert; a++) {
2116                                 ver= RE_findOrAddVert(a);
2117                                 Normalise(ver->n);
2118                         }
2119
2120
2121                 }
2122 #else
2123
2124                 if(dl->type==DL_SURF) {
2125                         startvert= R.totvert;
2126                         a= dl->nr*dl->parts;
2127                         data= dl->verts;
2128                         while(a--) {
2129                                 ver= RE_findOrAddVert(R.totvert++);
2130                                 VECCOPY(ver->co, data);
2131                                 if(orco) {
2132                                         ver->orco= orco;
2133                                         orco+= 3;
2134                                 }
2135                                 MTC_Mat4MulVecfl(mat, ver->co);
2136                                 data+= 3;
2137                         }
2138
2139                         startvlak= R.totvlak;
2140
2141                         for(a=0; a<dl->parts; a++) {
2142
2143                                 DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts);
2144                                 p1+= startvert;
2145                                 p2+= startvert;
2146                                 p3+= startvert;
2147                                 p4+= startvert;
2148
2149                                 for(; b<dl->nr; b++) {
2150                                         v1= RE_findOrAddVert(p1);
2151                                         v2= RE_findOrAddVert(p2);
2152                                         v3= RE_findOrAddVert(p3);
2153                                         v4= RE_findOrAddVert(p4);
2154
2155                                         flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
2156                                         if(flen!=0.0) {
2157                                                 vlr= RE_findOrAddVlak(R.totvlak++);
2158                                                 vlr->ob= vlr_set_ob(ob);
2159                                                 vlr->v1= v1;
2160                                                 vlr->v2= v3;
2161                                                 vlr->v3= v4;
2162                                                 vlr->v4= v2;
2163                                                 VECCOPY(vlr->n, n1);
2164                                                 vlr->lay= ob->lay;
2165                                                 vlr->mat= matar[ dl->col];
2166                                                 vlr->ec= ME_V1V2+ME_V2V3;
2167                                                 vlr->flag= dl->rt;
2168                                                 if( (cu->flag & CU_NOPUNOFLIP) ) {
2169                                                         vlr->flag |= R_NOPUNOFLIP;
2170                                                 }
2171                                         }
2172
2173                                         VecAddf(v1->n, v1->n, n1);
2174                                         VecAddf(v2->n, v2->n, n1);
2175                                         VecAddf(v3->n, v3->n, n1);
2176                                         VecAddf(v4->n, v4->n, n1);
2177
2178                                         p4= p3;
2179                                         p3++;
2180                                         p2= p1;
2181                                         p1++;
2182                                 }
2183                         }
2184
2185                         for(a=startvert; a<R.totvert; a++) {
2186                                 ver= RE_findOrAddVert(a);
2187                                 Normalise(ver->n);
2188                         }
2189
2190
2191                 }
2192 #endif
2193                 dl= dl->next;
2194         }
2195         freedisplist(&displist);
2196 }
2197
2198 static void init_render_curve(Object *ob)
2199 {
2200         extern Material defmaterial;    // initrender.c
2201         Ika *ika=0;
2202         Lattice *lt=0;
2203         Curve *cu;
2204         VertRen *ver;
2205         VlakRen *vlr;
2206         ListBase dlbev;
2207         Nurb *nu=0;
2208         DispList *dlb, *dl;
2209         BevList *bl;
2210         BevPoint *bevp;
2211         Material *matar[32];
2212         float len, *data, *fp, *fp1, fac;
2213         float n[3], vec[3], widfac, size[3], mat[4][4];
2214         int nr, startvert, startvlak, a, b, p1, p2, p3, p4;
2215         int totvert, frontside, need_orco=0, firststartvert, *index;
2216
2217         cu= ob->data;
2218         if(cu->nurb.first==NULL) return;
2219
2220         /* no modifier call here, is in makedisp */
2221
2222         /* test displist */
2223         if(cu->disp.first==0) makeDispList(ob);
2224         dl= cu->disp.first;
2225         if(cu->disp.first==0) return;
2226         
2227         if(dl->type!=DL_INDEX3) {
2228                 curve_to_filledpoly(cu, &cu->nurb, &cu->disp);
2229         }
2230
2231         if(cu->bev.first==0) makeBevelList(ob);
2232
2233         firststartvert= R.totvert;
2234
2235         MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
2236         MTC_Mat4Invert(ob->imat, mat);
2237
2238         /* material array */
2239         memset(matar, 0, 4*32);
2240         matar[0]= &defmaterial;
2241         for(a=0; a<ob->totcol; a++) {
2242                 matar[a]= give_render_material(ob, a+1);
2243                 if(matar[a]->texco & TEXCO_ORCO) {
2244                         need_orco= 1;
2245                 }
2246         }
2247
2248         /* bevelcurve in displist */
2249         dlbev.first= dlbev.last= 0;
2250
2251         if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj!=NULL) {
2252                 makebevelcurve(ob, &dlbev);
2253         }
2254
2255         /* uv orcos? count amount of points and malloc */
2256         if(need_orco && (cu->flag & CU_UV_ORCO)) {
2257                 if(cu->flag & CU_PATH);
2258                 else {
2259                         totvert= 0;
2260                         bl= cu->bev.first;
2261                         while(bl) {
2262                                 dlb= dlbev.first;
2263                                 while(dlb) {
2264                                         totvert+= dlb->nr*bl->nr;
2265                                         dlb= dlb->next;
2266                                 }
2267                                 bl= bl->next;
2268                         }
2269
2270                         if(totvert) {
2271                                 fp= cu->orco= MEM_mallocN(3*sizeof(float)*totvert, "cu->orco");
2272         
2273                                 bl= cu->bev.first;
2274                                 while(bl) {
2275                                         dlb= dlbev.first;
2276                                         while(dlb) {
2277                                                 for(b=0; b<dlb->nr; b++) {
2278                                                         fac= (2.0*b/(float)(dlb->nr-1)) - 1.0;
2279                                                         for(a=0; a<bl->nr; a++, fp+=3) {
2280                                                                 fp[0]= (2.0*a/(float)(bl->nr-1)) - 1.0;
2281                                                                 fp[1]= fac;
2282                                                                 fp[2]= 0.0;
2283                                                         }
2284                                                 }
2285                                                 dlb= dlb->next;
2286                                         }
2287                                         bl= bl->next;
2288                                 }
2289                         }
2290                 }
2291         }
2292
2293         if(ob->parent && ob->parent->type==OB_LATTICE) {
2294                 lt= ob->parent->data;
2295                 init_latt_deform(ob->parent, ob);
2296                 need_orco= 1;
2297         }
2298         
2299         if(ob->parent && ob->parent->type==OB_IKA) {
2300                 ika= ob->parent->data;
2301                 init_skel_deform(ob->parent, ob);
2302                 need_orco= 1;
2303         }
2304
2305         if(ob->parent && ob->parent->type==OB_ARMATURE) {
2306                 init_armature_deform(ob->parent, ob);
2307                 need_orco= 1;
2308         }
2309
2310         /* do keypos? NOTE: watch it : orcos */
2311
2312         /* effect on text? */
2313
2314         /* boundboxclip still todo */
2315
2316         /* side faces of poly:  work with bevellist */
2317         widfac= (cu->width-1.0);
2318
2319         bl= cu->bev.first;
2320         nu= cu->nurb.first;
2321         while(bl) {
2322
2323                 if(dlbev.first) {    /* otherwise just a poly */
2324
2325                         dlb= dlbev.first;   /* bevel loop */
2326                         while(dlb) {
2327                                 data= MEM_mallocN(3*sizeof(float)*dlb->nr*bl->nr, "init_render_curve3");
2328                                 fp= data;
2329
2330                                 /* for each point at bevelcurve do the entire poly */
2331                                 fp1= dlb->verts;
2332                                 b= dlb->nr;
2333                                 while(b--) {
2334
2335                                         bevp= (BevPoint *)(bl+1);
2336                                         for(a=0; a<bl->nr; a++) {
2337                                                 float fac;
2338                                                 
2339                                                 /* returns 1.0 if no taper, of course */
2340                                                 fac= calc_taper(cu->taperobj, a, bl->nr);
2341
2342                                                 if(cu->flag & CU_3D) {
2343                                                         vec[0]= fp1[1]+widfac;
2344                                                         vec[1]= fp1[2];
2345                                                         vec[2]= 0.0;
2346
2347                                                         MTC_Mat3MulVecfl(bevp->mat, vec);
2348
2349                                                         fp[0]= bevp->x+ fac*vec[0];
2350                                                         fp[1]= bevp->y+ fac*vec[1];
2351                                                         fp[2]= bevp->z+ fac*vec[2];
2352                                                 }
2353                                                 else {
2354
2355                                                         fp[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina;
2356                                                         fp[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa;
2357                                                         fp[2]= bevp->z+ fac*fp1[2];
2358                                                         /* do not MatMul here: polyfill should work uniform, independent which frame */
2359                                                 }
2360                                                 fp+= 3;
2361                                                 bevp++;
2362                                         }
2363                                         fp1+=3;
2364                                 }
2365
2366                                 /* make render vertices */
2367                                 fp= data;
2368                                 startvert= R.totvert;
2369                                 nr= dlb->nr*bl->nr;
2370
2371                                 while(nr--) {
2372                                         ver= RE_findOrAddVert(R.totvert++);
2373                                         
2374                                         if(lt) calc_latt_deform(fp);
2375                                         else if(ika) calc_skel_deform(ika, fp);
2376                                         
2377                                         VECCOPY(ver->co, fp);
2378                                         MTC_Mat4MulVecfl(mat, ver->co);
2379                                         fp+= 3;
2380                                 }
2381
2382                                 startvlak= R.totvlak;
2383
2384                                 for(a=0; a<dlb->nr; a++) {
2385
2386                                         frontside= (a >= dlb->nr/2);
2387
2388                                         DL_SURFINDEX(bl->poly>0, dlb->type==DL_POLY, bl->nr, dlb->nr);
2389                                         p1+= startvert;
2390                                         p2+= startvert;
2391                                         p3+= startvert;
2392                                         p4+= startvert;
2393
2394                                         for(; b<bl->nr; b++) {
2395
2396                                                 vlr= RE_findOrAddVlak(R.totvlak++);
2397                                                 vlr->ob= vlr_set_ob(ob);
2398                                                 vlr->v1= RE_findOrAddVert(p2);
2399                                                 vlr->v2= RE_findOrAddVert(p1);
2400                                                 vlr->v3= RE_findOrAddVert(p3);
2401                                                 vlr->v4= RE_findOrAddVert(p4);
2402                                                 vlr->ec= ME_V2V3+ME_V3V4;
2403                                                 if(a==0) vlr->ec+= ME_V1V2;
2404
2405                                                 vlr->flag= nu->flag;
2406                                                 vlr->lay= ob->lay;
2407
2408                                                 /* this is not really scientific: the vertices
2409                                                  * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
2410                                                  * front and backside treated different!!
2411                                                  */
2412
2413                                                 if(frontside)
2414                                                         CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
2415                                                 else 
2416                                                         CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
2417
2418                                                 vlr->mat= matar[ nu->mat_nr ];
2419
2420                                                 p4= p3;
2421                                                 p3++;
2422                                                 p2= p1;
2423                                                 p1++;
2424
2425                                         }
2426
2427                                 }
2428
2429                                 /* here was split_u before, for split off standard bevels, not needed anymore */
2430                                 /* but it could check on the bevel-curve BevPoints for u-split though... */
2431                                 
2432                                 /* make double points: SPLIT BEVELS */
2433                                 bevp= (BevPoint *)(bl+1);
2434                                 for(a=0; a<bl->nr; a++) {
2435                                         if(bevp->f1)
2436                                                 split_v_renderfaces(startvlak, startvert, bl->nr, dlb->nr, a, bl->poly>0,
2437                                                     dlb->type==DL_POLY);
2438                                         bevp++;
2439                                 }
2440
2441                                 /* vertex normals */
2442                                 for(a= startvlak; a<R.totvlak; a++) {
2443                                         vlr= RE_findOrAddVlak(a);
2444
2445                                         VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
2446                                         VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
2447                                         VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
2448                                         VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
2449                                 }
2450                                 for(a=startvert; a<R.totvert; a++) {
2451                                         ver= RE_findOrAddVert(a);
2452                                         len= Normalise(ver->n);
2453                                         if(len==0.0) ver->sticky= (float *)1;
2454                                         else ver->sticky= 0;
2455                                 }
2456                                 for(a= startvlak; a<R.totvlak; a++) {
2457                                         vlr= RE_findOrAddVlak(a);
2458                                         if(vlr->v1->sticky) VECCOPY(vlr->v1->n, vlr->n);
2459                                         if(vlr->v2->sticky) VECCOPY(vlr->v2->n, vlr->n);
2460                                         if(vlr->v3->sticky) VECCOPY(vlr->v3->n, vlr->n);
2461                                         if(vlr->v4->sticky) VECCOPY(vlr->v4->n, vlr->n);
2462                                 }
2463
2464                                 dlb= dlb->next;
2465
2466                                 MEM_freeN(data);
2467                         }
2468
2469                 }
2470                 bl= bl->next;
2471                 nu= nu->next;
2472         }
2473
2474         if(dlbev.first) {
2475                 freedisplist(&dlbev);
2476         }
2477
2478         if(cu->flag & CU_PATH) return;
2479
2480         /* from displist the filled faces can be extracted */
2481         dl= cu->disp.first;
2482
2483         while(dl) {
2484                 if(dl->type==DL_INDEX3) {
2485                         startvert= R.totvert;
2486                         data= dl->verts;
2487
2488                         n[0]= ob->imat[0][2];
2489                         n[1]= ob->imat[1][2];
2490                         n[2]= ob->imat[2][2];
2491                         Normalise(n);
2492
2493                         /* copy first, rotate later for comparision trick */
2494                         for(a=0; a<dl->nr; a++, data+=3) {
2495                                 ver= RE_findOrAddVert(R.totvert++);
2496                                 VECCOPY(ver->co, data);
2497
2498                                 if(ver->co[2] < 0.0) {
2499                                         VECCOPY(ver->n, n);
2500                                 }
2501                                 else {
2502                                         ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
2503                                 }
2504                         }
2505
2506                         startvlak= R.totvlak;
2507                         index= dl->index;
2508                         for(a=0; a<dl->parts; a++, index+=3) {
2509
2510                                 vlr= RE_findOrAddVlak(R.totvlak++);
2511                                 vlr->ob = vlr_set_ob(ob);       /* yafray: correction for curve rendering, obptr was not set */
2512                                 vlr->v1= RE_findOrAddVert(startvert+index[0]);
2513                                 vlr->v2= RE_findOrAddVert(startvert+index[1]);
2514                                 vlr->v3= RE_findOrAddVert(startvert+index[2]);
2515                                 vlr->v4= NULL;
2516                                 
2517                                 if(vlr->v1->co[2] < 0.0) {
2518                                         VECCOPY(vlr->n, n);
2519                                 }
2520                                 else {
2521                                         vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
2522                                 }
2523                                 
2524                                 vlr->mat= matar[ dl->col ];
2525                                 vlr->flag= 0;
2526                                 if( (cu->flag & CU_NOPUNOFLIP) ) {
2527                                         vlr->flag |= R_NOPUNOFLIP;
2528                                 }
2529                                 vlr->ec= 0;
2530                                 vlr->lay= ob->lay;
2531                         }
2532                         /* rotate verts */
2533                         for(a=0; a<dl->nr; a++) {
2534                                 ver= RE_findOrAddVert(startvert+a);
2535                                 MTC_Mat4MulVecfl(mat, ver->co);
2536                         }
2537                         
2538                 }
2539                 dl= dl->next;
2540         }
2541
2542         if(lt) {
2543                 end_latt_deform();
2544         }
2545
2546         if(need_orco) { /* the stupid way: should be replaced; taking account for keys! */
2547
2548                 VECCOPY(size, cu->size);
2549
2550                 nr= R.totvert-firststartvert;
2551                 if(nr) {
2552                         if(cu->orco) {
2553                                 fp= cu->orco;
2554                                 while(nr--) {
2555                                         ver= RE_findOrAddVert(firststartvert++);
2556                                         ver->orco= fp;
2557                                         fp+= 3;
2558                                 }
2559                         }
2560                         else {
2561                                 fp= cu->orco= MEM_mallocN(sizeof(float)*3*nr, "cu orco");
2562                                 while(nr--) {
2563                                         ver= RE_findOrAddVert(firststartvert++);
2564                                         ver->orco= fp;
2565
2566                                         VECCOPY(fp, ver->co);
2567                                         MTC_Mat4MulVecfl(ob->imat, fp);
2568
2569                                         fp[0]= (fp[0]-cu->loc[0])/size[0];
2570                                         fp[1]= (fp[1]-cu->loc[1])/size[1];
2571                                         fp[2]= (fp[2]-cu->loc[2])/size[2];
2572                                         fp+= 3;
2573                                 }
2574                         }
2575                 }
2576         }
2577 }
2578
2579 /* prevent phong interpolation for giving ray shadow errors (terminator problem) */
2580 static void set_phong_threshold(Object *ob, int startface, int numface, int startvert, int numvert )
2581 {
2582 //      VertRen *ver;
2583         VlakRen *vlr;
2584         float thresh= 0.0, dot;
2585         int tot=0, i;
2586         
2587         /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger 
2588            are taken into account. This threshold is meant to work on smooth geometry, not
2589            for extreme cases (ton) */
2590         
2591         for(i=startface; i<startface+numface; i++) {
2592                 vlr= RE_findOrAddVlak(i);
2593                 if(vlr->flag & R_SMOOTH) {
2594                         dot= INPR(vlr->n, vlr->v1->n);
2595                         dot= ABS(dot);
2596                         if(dot>0.9) {
2597                                 thresh+= dot; tot++;
2598                         }
2599                         dot= INPR(vlr->n, vlr->v2->n);
2600                         dot= ABS(dot);
2601                         if(dot>0.9) {
2602                                 thresh+= dot; tot++;
2603                         }
2604
2605                         dot= INPR(vlr->n, vlr->v3->n);
2606                         dot= ABS(dot);
2607                         if(dot>0.9) {
2608                                 thresh+= dot; tot++;
2609                         }
2610
2611                         if(vlr->v4) {
2612                                 dot= INPR(vlr->n, vlr->v4->n);
2613                                 dot= ABS(dot);
2614                                 if(dot>0.9) {
2615                                         thresh+= dot; tot++;
2616                                 }
2617                         }
2618                 }
2619         }
2620         
2621         if(tot) {
2622                 thresh/= (float)tot;
2623                 ob->smoothresh= cos(0.5*M_PI-acos(thresh));
2624         }
2625 }
2626
2627 static void init_render_object(Object *ob)
2628 {
2629         float mat[4][4];
2630         int startface, startvert;
2631         
2632         startface=R.totvlak;
2633         startvert=R.totvert;
2634
2635         ob->flag |= OB_DONE;
2636
2637         if(ob->type==OB_LAMP)
2638                 RE_add_render_lamp(ob, 1);
2639         else if ELEM(ob->type, OB_FONT, OB_CURVE)
2640                 init_render_curve(ob);
2641         else if(ob->type==OB_SURF)
2642                 init_render_surf(ob);
2643         else if(ob->type==OB_MESH)
2644                 init_render_mesh(ob);
2645         else if(ob->type==OB_MBALL)
2646                 init_render_mball(ob);
2647         else {
2648                 MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
2649                 MTC_Mat4Invert(ob->imat, mat);
2650         }
2651         
2652         /* generic post process here */
2653         if(startvert!=R.totvert) {
2654         
2655                 /* the exception below is because displace code now is in init_render_mesh call, 
2656                 I will look at means to have autosmooth enabled for all object types 
2657                 and have it as general postprocess, like displace */
2658                 if (ob->type!=OB_MESH && test_for_displace( ob ) ) 
2659                         do_displacement(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
2660         
2661                 /* phong normal interpolation can cause error in tracing (terminator prob) */
2662                 ob->smoothresh= 0.0;
2663                 if( (R.r.mode & R_RAYTRACE) && (R.r.mode & R_SHADOW) ) 
2664                         set_phong_threshold(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
2665         }
2666 }
2667
2668 void RE_freeRotateBlenderScene(void)
2669 {
2670         ShadBuf *shb;
2671         Object *ob = NULL;
2672         Mesh *me;
2673         Curve *cu;
2674         DispList *dl;
2675         unsigned long *ztile;
2676         int a, b, v;
2677         char *ctile;
2678
2679         /* FREE */
2680         
2681         BLI_memarena_free(R.memArena);
2682         R.memArena = NULL;
2683
2684         for(a=0; a<R.totlamp; a++) {
2685                 if(R.la[a]->shb) {
2686                         shb= R.la[a]->shb;
2687                         v= (shb->size*shb->size)/256;
2688                         ztile= shb->zbuf;
2689                         ctile= shb->cbuf;
2690                         for(b=0; b<v; b++, ztile++, ctile++) {
2691                                 if(*ctile) MEM_freeN((void *) *ztile);
2692                         }
2693                         
2694                         MEM_freeN(shb->zbuf);
2695                         MEM_freeN(shb->cbuf);
2696                         MEM_freeN(R.la[a]->shb);
2697                 }
2698                 if(R.la[a]->jitter) MEM_freeN(R.la[a]->jitter);
2699                 MEM_freeN(R.la[a]);
2700         }
2701
2702         /* note; these pointer arrays were allocated, with last element NULL to stop loop */
2703         a=0;
2704         while(R.blove[a]) {
2705                 MEM_freeN(R.blove[a]);
2706                 R.blove[a]= NULL;
2707                 a++;
2708         }
2709
2710         a=0;
2711         while(R.blovl[a]) {
2712                 MEM_freeN(R.blovl[a]);
2713                 R.blovl[a]= NULL;
2714                 a++;
2715         }
2716         a=0;
2717         while(R.bloha[a]) {
2718                 MEM_freeN(R.bloha[a]);
2719                 R.bloha[a]= NULL;
2720                 a++;
2721         }
2722
2723         /* free orco. check all objects because of duplis and sets */
2724         ob= G.main->object.first;
2725         while(ob) {
2726
2727                 if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
2728                         cu= ob->data;
2729                         if(cu->orco) {
2730                                 MEM_freeN(cu->orco);
2731                                 cu->orco= 0;
2732                         }
2733                 }
2734                 else if(ob->type==OB_MESH) {
2735                         me= ob->data;
2736                         if(me->orco) {
2737                                 MEM_freeN(me->orco);
2738                                 me->orco= 0;
2739                         }
2740                         if (mesh_uses_displist(me) && ((me->subdiv!=me->subdivr) || (ob->effect.first != NULL) || ob==G.obedit) ) { 
2741                             /* Need to recalc for effects since they are time dependant */
2742                                 makeDispList(ob);  /* XXX this should be replaced with proper caching */
2743                         }
2744                 }
2745                 else if(ob->type==OB_MBALL) {
2746                         if(ob->disp.first && ob->disp.first!=ob->disp.last) {
2747                                 dl= ob->disp.first;
2748                                 BLI_remlink(&ob->disp, dl);
2749                                 freedisplist(&ob->disp);
2750                                 BLI_addtail(&ob->disp, dl);
2751                         }
2752                 }
2753                 ob= ob->id.next;
2754         }
2755
2756         end_render_textures();
2757         end_render_materials();
2758         end_radio_render();
2759         
2760         R.totvlak=R.totvert=R.totlamp=R.tothalo= 0;
2761 }
2762
2763 /* per face check if all samples should be taken.
2764    if raytrace, do always for raytraced material, or when material full_osa set */
2765 static void set_fullsample_flag(void)
2766 {
2767         VlakRen *vlr;
2768         int a, trace;
2769
2770         trace= R.r.mode & R_RAYTRACE;
2771         
2772         for(a=R.totvlak-1; a>=0; a--) {
2773                 vlr= RE_findOrAddVlak(a);
2774                 
2775                 if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA;
2776                 else if(trace) {
2777                         if(vlr->mat->mode & MA_SHLESS);
2778                         else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR|MA_SHADOW))
2779                                 vlr->flag |= R_FULL_OSA;
2780                 }
2781         }
2782 }
2783
2784 /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp */
2785 #ifdef FLT_EPSILON
2786 #undef FLT_EPSILON
2787 #endif
2788 #define FLT_EPSILON 1.19209290e-06F
2789
2790