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