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