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