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