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