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