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