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