Support multiple tangents for BI render & viewport
[blender.git] / source / blender / render / intern / source / convertblender.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributors: 2004/2005/2006 Blender Foundation, full recode
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/convertblender.c
27  *  \ingroup render
28  */
29
30 #include <math.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_math.h"
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_rand.h"
42 #include "BLI_memarena.h"
43 #ifdef WITH_FREESTYLE
44 #  include "BLI_edgehash.h"
45 #endif
46
47 #include "BLT_translation.h"
48
49 #include "DNA_material_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_group_types.h"
52 #include "DNA_lamp_types.h"
53 #include "DNA_image_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_modifier_types.h"
57 #include "DNA_node_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_object_fluidsim.h"
60 #include "DNA_particle_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_texture_types.h"
63
64 #include "BKE_anim.h"
65 #include "BKE_curve.h"
66 #include "BKE_customdata.h"
67 #include "BKE_colortools.h"
68 #include "BKE_displist.h"
69 #include "BKE_depsgraph.h"
70 #include "BKE_DerivedMesh.h"
71 #include "BKE_global.h"
72 #include "BKE_key.h"
73 #include "BKE_image.h"
74 #include "BKE_lattice.h"
75 #include "BKE_material.h"
76 #include "BKE_main.h"
77 #include "BKE_mball.h"
78 #include "BKE_mesh.h"
79 #include "BKE_modifier.h"
80 #include "BKE_node.h"
81 #include "BKE_object.h"
82 #include "BKE_particle.h"
83 #include "BKE_scene.h"
84
85 #include "PIL_time.h"
86
87 #include "envmap.h"
88 #include "occlusion.h"
89 #include "pointdensity.h"
90 #include "voxeldata.h"
91 #include "render_types.h"
92 #include "rendercore.h"
93 #include "renderdatabase.h"
94 #include "renderpipeline.h"
95 #include "shadbuf.h"
96 #include "shading.h"
97 #include "strand.h"
98 #include "texture.h"
99 #include "volume_precache.h"
100 #include "sss.h"
101 #include "zbuf.h"
102 #include "sunsky.h"
103
104 /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
105 /* or for checking vertex normal flips */
106 #define FLT_EPSILON10 1.19209290e-06F
107
108 /* could enable at some point but for now there are far too many conversions */
109 #ifdef __GNUC__
110 #  pragma GCC diagnostic ignored "-Wdouble-promotion"
111 #endif
112
113 /* ------------------------------------------------------------------------- */
114 /* tool functions/defines for ad hoc simplification and possible future 
115  * cleanup      */
116 /* ------------------------------------------------------------------------- */
117
118 #define UVTOINDEX(u, v) (startvlak + (u) * sizev + (v))
119 /*
120  *
121  * NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !!
122  *
123  * ^   ()----p4----p3----()
124  * |   |     |     |     |
125  * u   |     |  F1 |  F2 |
126  *     |     |     |     |
127  *     ()----p1----p2----()
128  *            v ->
129  */
130
131 /* ------------------------------------------------------------------------- */
132
133 #define CD_MASK_RENDER_INTERNAL \
134     (CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL)
135
136 static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startvert), int UNUSED(usize), int vsize, int uIndex, int UNUSED(cyclu), int cyclv)
137 {
138         int vLen = vsize-1+(!!cyclv);
139         int v;
140
141         for (v=0; v<vLen; v++) {
142                 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v);
143                 VlakRen *vlr_other;
144                 VertRen *vert = RE_vertren_copy(obr, vlr->v2);
145
146                 if (cyclv) {
147                         vlr->v2 = vert;
148
149                         if (v == vLen - 1) {
150                                 vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0);
151                                 vlr_other->v1 = vert;
152                         }
153                         else {
154                                 vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
155                                 vlr_other->v1 = vert;
156                         }
157                 }
158                 else {
159                         vlr->v2 = vert;
160
161                         if (v < vLen - 1) {
162                                 vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
163                                 vlr_other->v1 = vert;
164                         }
165
166                         if (v == 0) {
167                                 vlr->v1 = RE_vertren_copy(obr, vlr->v1);
168                         }
169                 }
170         }
171 }
172
173 /* ------------------------------------------------------------------------- */
174 /* Stress, tangents and normals                                              */
175 /* ------------------------------------------------------------------------- */
176
177 static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2)
178 {
179         float len= len_v3v3(v1->co, v2->co)/len_v3v3(v1->orco, v2->orco);
180         float *acc;
181         
182         acc= accum + 2*v1->index;
183         acc[0]+= len;
184         acc[1]+= 1.0f;
185         
186         acc= accum + 2*v2->index;
187         acc[0]+= len;
188         acc[1]+= 1.0f;
189 }
190
191 static void calc_edge_stress(Render *UNUSED(re), ObjectRen *obr, Mesh *me)
192 {
193         float loc[3], size[3], *accum, *acc, *accumoffs, *stress;
194         int a;
195         
196         if (obr->totvert==0) return;
197         
198         BKE_mesh_texspace_get(me, loc, NULL, size);
199         
200         accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress");
201         
202         /* de-normalize orco */
203         for (a=0; a<obr->totvert; a++) {
204                 VertRen *ver= RE_findOrAddVert(obr, a);
205                 if (ver->orco) {
206                         ver->orco[0]= ver->orco[0]*size[0] +loc[0];
207                         ver->orco[1]= ver->orco[1]*size[1] +loc[1];
208                         ver->orco[2]= ver->orco[2]*size[2] +loc[2];
209                 }
210         }
211         
212         /* add stress values */
213         accumoffs= accum;       /* so we can use vertex index */
214         for (a=0; a<obr->totvlak; a++) {
215                 VlakRen *vlr= RE_findOrAddVlak(obr, a);
216
217                 if (vlr->v1->orco && vlr->v4) {
218                         calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2);
219                         calc_edge_stress_add(accumoffs, vlr->v2, vlr->v3);
220                         calc_edge_stress_add(accumoffs, vlr->v3, vlr->v1);
221                         if (vlr->v4) {
222                                 calc_edge_stress_add(accumoffs, vlr->v3, vlr->v4);
223                                 calc_edge_stress_add(accumoffs, vlr->v4, vlr->v1);
224                                 calc_edge_stress_add(accumoffs, vlr->v2, vlr->v4);
225                         }
226                 }
227         }
228         
229         for (a=0; a<obr->totvert; a++) {
230                 VertRen *ver= RE_findOrAddVert(obr, a);
231                 if (ver->orco) {
232                         /* find stress value */
233                         acc= accumoffs + 2*ver->index;
234                         if (acc[1]!=0.0f)
235                                 acc[0]/= acc[1];
236                         stress= RE_vertren_get_stress(obr, ver, 1);
237                         *stress= *acc;
238                         
239                         /* restore orcos */
240                         ver->orco[0] = (ver->orco[0]-loc[0])/size[0];
241                         ver->orco[1] = (ver->orco[1]-loc[1])/size[1];
242                         ver->orco[2] = (ver->orco[2]-loc[2])/size[2];
243                 }
244         }
245         
246         MEM_freeN(accum);
247 }
248
249 /* gets tangent from tface or orco */
250 static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr, int do_tangent)
251 {
252         MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
253         VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
254         float tang[3], *tav;
255         float *uv1, *uv2, *uv3, *uv4;
256         float uv[4][2];
257         
258         if (tface) {
259                 uv1= tface->uv[0];
260                 uv2= tface->uv[1];
261                 uv3= tface->uv[2];
262                 uv4= tface->uv[3];
263         }
264         else if (v1->orco) {
265                 uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
266                 map_to_sphere(&uv[0][0], &uv[0][1], v1->orco[0], v1->orco[1], v1->orco[2]);
267                 map_to_sphere(&uv[1][0], &uv[1][1], v2->orco[0], v2->orco[1], v2->orco[2]);
268                 map_to_sphere(&uv[2][0], &uv[2][1], v3->orco[0], v3->orco[1], v3->orco[2]);
269                 if (v4)
270                         map_to_sphere(&uv[3][0], &uv[3][1], v4->orco[0], v4->orco[1], v4->orco[2]);
271         }
272         else return;
273
274         tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang);
275         
276         if (do_tangent) {
277                 tav= RE_vertren_get_tangent(obr, v1, 1);
278                 add_v3_v3(tav, tang);
279                 tav= RE_vertren_get_tangent(obr, v2, 1);
280                 add_v3_v3(tav, tang);
281                 tav= RE_vertren_get_tangent(obr, v3, 1);
282                 add_v3_v3(tav, tang);
283         }
284         
285         if (v4) {
286                 tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang);
287                 
288                 if (do_tangent) {
289                         tav= RE_vertren_get_tangent(obr, v1, 1);
290                         add_v3_v3(tav, tang);
291                         tav= RE_vertren_get_tangent(obr, v3, 1);
292                         add_v3_v3(tav, tang);
293                         tav= RE_vertren_get_tangent(obr, v4, 1);
294                         add_v3_v3(tav, tang);
295                 }
296         }
297 }
298
299
300
301 /****************************************************************
302  ************ tangent space generation interface ****************
303  ****************************************************************/
304
305 typedef struct {
306         ObjectRen *obr;
307         int mtface_index;
308 } SRenderMeshToTangent;
309
310 /* interface */
311 #include "mikktspace.h"
312
313 static int GetNumFaces(const SMikkTSpaceContext *pContext)
314 {
315         SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
316         return pMesh->obr->totvlak;
317 }
318
319 static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
320 {
321         SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
322         VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
323         return vlr->v4!=NULL ? 4 : 3;
324 }
325
326 static void GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index)
327 {
328         //assert(vert_index>=0 && vert_index<4);
329         SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
330         VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
331         const float *co = (&vlr->v1)[vert_index]->co;
332         copy_v3_v3(r_co, co);
333 }
334
335 static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_num, const int vert_index)
336 {
337         //assert(vert_index>=0 && vert_index<4);
338         SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
339         VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
340         MTFace *tface= RE_vlakren_get_tface(pMesh->obr, vlr, pMesh->mtface_index, NULL, 0);
341         const float *coord;
342         
343         if (tface  != NULL) {
344                 coord= tface->uv[vert_index];
345                 copy_v2_v2(r_uv, coord);
346         }
347         else if ((coord = (&vlr->v1)[vert_index]->orco)) {
348                 map_to_sphere(&r_uv[0], &r_uv[1], coord[0], coord[1], coord[2]);
349         }
350         else { /* else we get un-initialized value, 0.0 ok default? */
351                 zero_v2(r_uv);
352         }
353 }
354
355 static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_num, const int vert_index)
356 {
357         //assert(vert_index>=0 && vert_index<4);
358         SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
359         VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
360
361         if (vlr->flag & ME_SMOOTH) {
362                 const float *n = (&vlr->v1)[vert_index]->n;
363                 copy_v3_v3(r_no, n);
364         }
365         else {
366                 negate_v3_v3(r_no, vlr->n);
367         }
368 }
369 static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int iVert)
370 {
371         //assert(vert_index>=0 && vert_index<4);
372         SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
373         VlakRen *vlr = RE_findOrAddVlak(pMesh->obr, face_num);
374         float *ftang = RE_vlakren_get_nmap_tangent(pMesh->obr, vlr, pMesh->mtface_index, true);
375         if (ftang!=NULL) {
376                 copy_v3_v3(&ftang[iVert*4+0], fvTangent);
377                 ftang[iVert*4+3]=fSign;
378         }
379 }
380
381 static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_vertex_normal, bool do_tangent, bool do_nmap_tangent)
382 {
383         int a;
384
385         /* clear all vertex normals */
386         if (do_vertex_normal) {
387                 for (a=0; a<obr->totvert; a++) {
388                         VertRen *ver= RE_findOrAddVert(obr, a);
389                         ver->n[0]=ver->n[1]=ver->n[2]= 0.0f;
390                 }
391         }
392
393         /* calculate cos of angles and point-masses, use as weight factor to
394          * add face normal to vertex */
395         for (a=0; a<obr->totvlak; a++) {
396                 VlakRen *vlr= RE_findOrAddVlak(obr, a);
397                 if (do_vertex_normal && vlr->flag & ME_SMOOTH) {
398                         float *n4= (vlr->v4)? vlr->v4->n: NULL;
399                         const float *c4= (vlr->v4)? vlr->v4->co: NULL;
400
401                         accumulate_vertex_normals(vlr->v1->n, vlr->v2->n, vlr->v3->n, n4,
402                                 vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co, c4);
403                 }
404                 if (do_tangent) {
405                         /* tangents still need to be calculated for flat faces too */
406                         /* weighting removed, they are not vertexnormals */
407                         calc_tangent_vector(obr, vlr, do_tangent);
408                 }
409         }
410
411         /* do solid faces */
412         for (a=0; a<obr->totvlak; a++) {
413                 VlakRen *vlr= RE_findOrAddVlak(obr, a);
414
415                 if (do_vertex_normal && (vlr->flag & ME_SMOOTH)==0) {
416                         if (is_zero_v3(vlr->v1->n)) copy_v3_v3(vlr->v1->n, vlr->n);
417                         if (is_zero_v3(vlr->v2->n)) copy_v3_v3(vlr->v2->n, vlr->n);
418                         if (is_zero_v3(vlr->v3->n)) copy_v3_v3(vlr->v3->n, vlr->n);
419                         if (vlr->v4 && is_zero_v3(vlr->v4->n)) copy_v3_v3(vlr->v4->n, vlr->n);
420                 }
421         }
422         
423         /* normalize vertex normals */
424         for (a=0; a<obr->totvert; a++) {
425                 VertRen *ver= RE_findOrAddVert(obr, a);
426                 normalize_v3(ver->n);
427                 if (do_tangent) {
428                         float *tav= RE_vertren_get_tangent(obr, ver, 0);
429                         if (tav) {
430                                 /* orthonorm. */
431                                 const float tdn = dot_v3v3(tav, ver->n);
432                                 tav[0] -= ver->n[0]*tdn;
433                                 tav[1] -= ver->n[1]*tdn;
434                                 tav[2] -= ver->n[2]*tdn;
435                                 normalize_v3(tav);
436                         }
437                 }
438         }
439
440         /* normal mapping tangent with mikktspace */
441         if (do_nmap_tangent != false) {
442                 SRenderMeshToTangent mesh2tangent;
443                 SMikkTSpaceContext sContext;
444                 SMikkTSpaceInterface sInterface;
445                 memset(&mesh2tangent, 0, sizeof(SRenderMeshToTangent));
446                 memset(&sContext, 0, sizeof(SMikkTSpaceContext));
447                 memset(&sInterface, 0, sizeof(SMikkTSpaceInterface));
448
449                 mesh2tangent.obr = obr;
450
451                 sContext.m_pUserData = &mesh2tangent;
452                 sContext.m_pInterface = &sInterface;
453                 sInterface.m_getNumFaces = GetNumFaces;
454                 sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace;
455                 sInterface.m_getPosition = GetPosition;
456                 sInterface.m_getTexCoord = GetTextureCoordinate;
457                 sInterface.m_getNormal = GetNormal;
458                 sInterface.m_setTSpaceBasic = SetTSpace;
459
460                 for (a = 0; a < MAX_MTFACE; a++) {
461                         if (obr->tangent_mask & 1 << a) {
462                                 mesh2tangent.mtface_index = a;
463                                 genTangSpaceDefault(&sContext);
464                         }
465                 }
466         }
467 }
468
469 /* ------------------------------------------------------------------------- */
470 /* Autosmoothing:                                                            */
471 /* ------------------------------------------------------------------------- */
472
473 typedef struct ASvert {
474         int totface;
475         ListBase faces;
476 } ASvert;
477
478 typedef struct ASface {
479         struct ASface *next, *prev;
480         VlakRen *vlr[4];
481         VertRen *nver[4];
482 } ASface;
483
484 static int as_addvert(ASvert *asv, VertRen *v1, VlakRen *vlr)
485 {
486         ASface *asf;
487         int a = -1;
488
489         if (v1 == NULL)
490                 return a;
491
492         asf = asv->faces.last;
493         if (asf) {
494                 for (a = 0; a < 4 && asf->vlr[a]; a++) {
495                 }
496         }
497         else {
498                 a = 4;
499         }
500
501         /* new face struct */
502         if (a == 4) {
503                 a = 0;
504                 asf = MEM_callocN(sizeof(ASface), "asface");
505                 BLI_addtail(&asv->faces, asf);
506         }
507
508         asf->vlr[a] = vlr;
509         asv->totface++;
510
511         return a;
512 }
513
514 static VertRen *as_findvertex_lnor(VlakRen *vlr, VertRen *ver, ASvert *asv, const float lnor[3])
515 {
516         /* return when new vertex already was made, or existing one is OK */
517         ASface *asf;
518         int a;
519
520         /* First face, we can use existing vert and assign it current lnor! */
521         if (asv->totface == 1) {
522                 copy_v3_v3(ver->n, lnor);
523                 return ver;
524         }
525
526         /* In case existing ver has same normal as current lnor, we can simply use it! */
527         if (equals_v3v3(lnor, ver->n)) {
528                 return ver;
529         }
530
531         asf = asv->faces.first;
532         while (asf) {
533                 for (a = 0; a < 4; a++) {
534                         if (asf->vlr[a] && asf->vlr[a] != vlr) {
535                                 /* this face already made a copy for this vertex! */
536                                 if (asf->nver[a]) {
537                                         if (equals_v3v3(lnor, asf->nver[a]->n)) {
538                                                 return asf->nver[a];
539                                         }
540                                 }
541                         }
542                 }
543                 asf = asf->next;
544         }
545
546         return NULL;
547 }
548
549 static void as_addvert_lnor(ObjectRen *obr, ASvert *asv, VertRen *ver, VlakRen *vlr, const short _lnor[3])
550 {
551         VertRen *v1;
552         ASface *asf;
553         int asf_idx;
554         float lnor[3];
555
556         normal_short_to_float_v3(lnor, _lnor);
557
558         asf_idx = as_addvert(asv, ver, vlr);
559         if (asf_idx < 0) {
560                 return;
561         }
562         asf = asv->faces.last;
563
564         /* already made a new vertex within threshold? */
565         v1 = as_findvertex_lnor(vlr, ver, asv, lnor);
566         if (v1 == NULL) {
567                 /* make a new vertex */
568                 v1 = RE_vertren_copy(obr, ver);
569                 copy_v3_v3(v1->n, lnor);
570         }
571         if (v1 != ver) {
572                 asf->nver[asf_idx] = v1;
573                 if (vlr->v1 == ver) vlr->v1 = v1;
574                 if (vlr->v2 == ver) vlr->v2 = v1;
575                 if (vlr->v3 == ver) vlr->v3 = v1;
576                 if (vlr->v4 == ver) vlr->v4 = v1;
577         }
578 }
579
580 /* note; autosmooth happens in object space still, after applying autosmooth we rotate */
581 /* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */
582 static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], short (*lnors)[4][3])
583 {
584         ASvert *asverts;
585         VertRen *ver;
586         VlakRen *vlr;
587         int a, totvert;
588
589         float rot[3][3];
590
591         /* Note: For normals, we only want rotation, not scaling component.
592          *       Negative scales (aka mirroring) give wrong results, see T44102. */
593         if (lnors) {
594                 float mat3[3][3], size[3];
595
596                 copy_m3_m4(mat3, mat);
597                 mat3_to_rot_size(rot, size, mat3);
598         }
599
600         if (obr->totvert == 0)
601                 return;
602
603         totvert = obr->totvert;
604         asverts = MEM_callocN(sizeof(ASvert) * totvert, "all smooth verts");
605
606         if (lnors) {
607                 /* We construct listbase of all vertices and pointers to faces, and add new verts when needed
608                  * (i.e. when existing ones do not share the same (loop)normal).
609                  */
610                 for (a = 0; a < obr->totvlak; a++, lnors++) {
611                         vlr = RE_findOrAddVlak(obr, a);
612                         /* skip wire faces */
613                         if (vlr->v2 != vlr->v3) {
614                                 as_addvert_lnor(obr, asverts+vlr->v1->index, vlr->v1, vlr, (const short*)lnors[0][0]);
615                                 as_addvert_lnor(obr, asverts+vlr->v2->index, vlr->v2, vlr, (const short*)lnors[0][1]);
616                                 as_addvert_lnor(obr, asverts+vlr->v3->index, vlr->v3, vlr, (const short*)lnors[0][2]);
617                                 if (vlr->v4)
618                                         as_addvert_lnor(obr, asverts+vlr->v4->index, vlr->v4, vlr, (const short*)lnors[0][3]);
619                         }
620                 }
621         }
622
623         /* free */
624         for (a = 0; a < totvert; a++) {
625                 BLI_freelistN(&asverts[a].faces);
626         }
627         MEM_freeN(asverts);
628
629         /* rotate vertices and calculate normal of faces */
630         for (a = 0; a < obr->totvert; a++) {
631                 ver = RE_findOrAddVert(obr, a);
632                 mul_m4_v3(mat, ver->co);
633                 if (lnors) {
634                         mul_m3_v3(rot, ver->n);
635                         negate_v3(ver->n);
636                 }
637         }
638         for (a = 0; a < obr->totvlak; a++) {
639                 vlr = RE_findOrAddVlak(obr, a);
640
641                 /* skip wire faces */
642                 if (vlr->v2 != vlr->v3) {
643                         if (vlr->v4)
644                                 normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
645                         else 
646                                 normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co);
647                 }
648         }
649 }
650
651 /* ------------------------------------------------------------------------- */
652 /* Orco hash and Materials                                                   */
653 /* ------------------------------------------------------------------------- */
654
655 static float *get_object_orco(Render *re, void *ob)
656 {
657         if (!re->orco_hash) {
658                 return NULL;
659         }
660
661         return BLI_ghash_lookup(re->orco_hash, ob);
662 }
663
664 static void set_object_orco(Render *re, void *ob, float *orco)
665 {
666         if (!re->orco_hash)
667                 re->orco_hash = BLI_ghash_ptr_new("set_object_orco gh");
668         
669         BLI_ghash_insert(re->orco_hash, ob, orco);
670 }
671
672 static void free_mesh_orco_hash(Render *re) 
673 {
674         if (re->orco_hash) {
675                 BLI_ghash_free(re->orco_hash, NULL, MEM_freeN);
676                 re->orco_hash = NULL;
677         }
678 }
679
680 static void check_material_mapto(Material *ma)
681 {
682         int a;
683         ma->mapto_textured = 0;
684         
685         /* cache which inputs are actually textured.
686          * this can avoid a bit of time spent iterating through all the texture slots, map inputs and map tos
687          * every time a property which may or may not be textured is accessed */
688         
689         for (a=0; a<MAX_MTEX; a++) {
690                 if (ma->mtex[a] && ma->mtex[a]->tex) {
691                         /* currently used only in volume render, so we'll check for those flags */
692                         if (ma->mtex[a]->mapto & MAP_DENSITY) ma->mapto_textured |= MAP_DENSITY;
693                         if (ma->mtex[a]->mapto & MAP_EMISSION) ma->mapto_textured |= MAP_EMISSION;
694                         if (ma->mtex[a]->mapto & MAP_EMISSION_COL) ma->mapto_textured |= MAP_EMISSION_COL;
695                         if (ma->mtex[a]->mapto & MAP_SCATTERING) ma->mapto_textured |= MAP_SCATTERING;
696                         if (ma->mtex[a]->mapto & MAP_TRANSMISSION_COL) ma->mapto_textured |= MAP_TRANSMISSION_COL;
697                         if (ma->mtex[a]->mapto & MAP_REFLECTION) ma->mapto_textured |= MAP_REFLECTION;
698                         if (ma->mtex[a]->mapto & MAP_REFLECTION_COL) ma->mapto_textured |= MAP_REFLECTION_COL;
699                 }
700         }
701 }
702 static void flag_render_node_material(Render *re, bNodeTree *ntree)
703 {
704         bNode *node;
705
706         for (node = ntree->nodes.first; node; node = node->next) {
707                 if (node->id) {
708                         if (GS(node->id->name)==ID_MA) {
709                                 Material *ma= (Material *)node->id;
710
711                                 if ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))
712                                         re->flag |= R_ZTRA;
713
714                                 ma->flag |= MA_IS_USED;
715                         }
716                         else if (node->type==NODE_GROUP)
717                                 flag_render_node_material(re, (bNodeTree *)node->id);
718                 }
719         }
720 }
721
722 static Material *give_render_material(Render *re, Object *ob, short nr)
723 {
724         extern Material defmaterial;    /* material.c */
725         Material *ma;
726         
727         ma= give_current_material(ob, nr);
728         if (ma==NULL)
729                 ma= &defmaterial;
730         
731         if (re->r.mode & R_SPEED) ma->texco |= NEED_UV;
732         
733         if (ma->material_type == MA_TYPE_VOLUME) {
734                 ma->mode |= MA_TRANSP;
735                 ma->mode &= ~MA_SHADBUF;
736         }
737         if ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP))
738                 re->flag |= R_ZTRA;
739         
740         /* for light groups and SSS */
741         ma->flag |= MA_IS_USED;
742
743         if (ma->nodetree && ma->use_nodes)
744                 flag_render_node_material(re, ma->nodetree);
745         
746         check_material_mapto(ma);
747         
748         return ma;
749 }
750
751 /* ------------------------------------------------------------------------- */
752 /* Particles                                                                 */
753 /* ------------------------------------------------------------------------- */
754 typedef struct ParticleStrandData {
755         struct MCol *mcol;
756         float *orco, *uvco, *surfnor;
757         float time, adapt_angle, adapt_pix, size;
758         int totuv, totcol;
759         int first, line, adapt, override_uv;
760 }
761 ParticleStrandData;
762 /* future thread problem... */
763 static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, const float vec[3], const float vec1[3])
764 {
765         static VertRen *v1= NULL, *v2= NULL;
766         VlakRen *vlr= NULL;
767         float nor[3], cross[3], crosslen, w, dx, dy, width;
768         static float anor[3], avec[3];
769         int flag, i;
770         static int second=0;
771         
772         sub_v3_v3v3(nor, vec, vec1);
773         normalize_v3(nor);  /* nor needed as tangent */
774         cross_v3_v3v3(cross, vec, nor);
775
776         /* turn cross in pixelsize */
777         w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
778         dx= re->winx*cross[0]*re->winmat[0][0];
779         dy= re->winy*cross[1]*re->winmat[1][1];
780         w = sqrtf(dx * dx + dy * dy) / w;
781         
782         if (w!=0.0f) {
783                 float fac;
784                 if (ma->strand_ease!=0.0f) {
785                         if (ma->strand_ease<0.0f)
786                                 fac= pow(sd->time, 1.0f+ma->strand_ease);
787                         else
788                                 fac= pow(sd->time, 1.0f/(1.0f-ma->strand_ease));
789                 }
790                 else fac= sd->time;
791
792                 width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end);
793
794                 /* use actual Blender units for strand width and fall back to minimum width */
795                 if (ma->mode & MA_STR_B_UNITS) {
796                         crosslen= len_v3(cross);
797                         w= 2.0f*crosslen*ma->strand_min/w;
798
799                         if (width < w)
800                                 width= w;
801
802                         /*cross is the radius of the strand so we want it to be half of full width */
803                         mul_v3_fl(cross, 0.5f/crosslen);
804                 }
805                 else
806                         width/=w;
807
808                 mul_v3_fl(cross, width);
809         }
810         
811         if (ma->mode & MA_TANGENT_STR)
812                 flag= R_SMOOTH|R_TANGENT;
813         else
814                 flag= R_SMOOTH;
815         
816         /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */
817         if (ma->strand_sta==1.0f)
818                 flag |= R_STRAND;
819         
820         /* single face line */
821         if (sd->line) {
822                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
823                 vlr->flag= flag;
824                 vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
825                 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
826                 vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
827                 vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
828                 
829                 copy_v3_v3(vlr->v1->co, vec);
830                 add_v3_v3(vlr->v1->co, cross);
831                 copy_v3_v3(vlr->v1->n, nor);
832                 vlr->v1->orco= sd->orco;
833                 vlr->v1->accum = -1.0f;  /* accum abuse for strand texco */
834                 
835                 copy_v3_v3(vlr->v2->co, vec);
836                 sub_v3_v3v3(vlr->v2->co, vlr->v2->co, cross);
837                 copy_v3_v3(vlr->v2->n, nor);
838                 vlr->v2->orco= sd->orco;
839                 vlr->v2->accum= vlr->v1->accum;
840
841                 copy_v3_v3(vlr->v4->co, vec1);
842                 add_v3_v3(vlr->v4->co, cross);
843                 copy_v3_v3(vlr->v4->n, nor);
844                 vlr->v4->orco= sd->orco;
845                 vlr->v4->accum = 1.0f;  /* accum abuse for strand texco */
846
847                 copy_v3_v3(vlr->v3->co, vec1);
848                 sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross);
849                 copy_v3_v3(vlr->v3->n, nor);
850                 vlr->v3->orco= sd->orco;
851                 vlr->v3->accum= vlr->v4->accum;
852
853                 normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
854                 
855                 vlr->mat= ma;
856                 vlr->ec= ME_V2V3;
857
858                 if (sd->surfnor) {
859                         float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
860                         copy_v3_v3(snor, sd->surfnor);
861                 }
862
863                 if (sd->uvco) {
864                         for (i=0; i<sd->totuv; i++) {
865                                 MTFace *mtf;
866                                 mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1);
867                                 mtf->uv[0][0]=mtf->uv[1][0]=
868                                 mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
869                                 mtf->uv[0][1]=mtf->uv[1][1]=
870                                 mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
871                         }
872                         if (sd->override_uv>=0) {
873                                 MTFace *mtf;
874                                 mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0);
875                                 
876                                 mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
877                                 mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
878
879                                 mtf->uv[0][1]=mtf->uv[1][1]=0.0f;
880                                 mtf->uv[2][1]=mtf->uv[3][1]=1.0f;
881                         }
882                 }
883                 if (sd->mcol) {
884                         for (i=0; i<sd->totcol; i++) {
885                                 MCol *mc;
886                                 mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1);
887                                 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
888                                 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
889                         }
890                 }
891         }
892         /* first two vertices of a strand */
893         else if (sd->first) {
894                 if (sd->adapt) {
895                         copy_v3_v3(anor, nor);
896                         copy_v3_v3(avec, vec);
897                         second=1;
898                 }
899
900                 v1= RE_findOrAddVert(obr, obr->totvert++);
901                 v2= RE_findOrAddVert(obr, obr->totvert++);
902                 
903                 copy_v3_v3(v1->co, vec);
904                 add_v3_v3(v1->co, cross);
905                 copy_v3_v3(v1->n, nor);
906                 v1->orco= sd->orco;
907                 v1->accum = -1.0f;  /* accum abuse for strand texco */
908                 
909                 copy_v3_v3(v2->co, vec);
910                 sub_v3_v3v3(v2->co, v2->co, cross);
911                 copy_v3_v3(v2->n, nor);
912                 v2->orco= sd->orco;
913                 v2->accum= v1->accum;
914         }
915         /* more vertices & faces to strand */
916         else {
917                 if (sd->adapt==0 || second) {
918                         vlr= RE_findOrAddVlak(obr, obr->totvlak++);
919                         vlr->flag= flag;
920                         vlr->v1= v1;
921                         vlr->v2= v2;
922                         vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
923                         vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
924
925                         v1= vlr->v4; /* cycle */
926                         v2= vlr->v3; /* cycle */
927
928
929                         if (sd->adapt) {
930                                 second=0;
931                                 copy_v3_v3(anor, nor);
932                                 copy_v3_v3(avec, vec);
933                         }
934
935                 }
936                 else if (sd->adapt) {
937                         float dvec[3], pvec[3];
938                         sub_v3_v3v3(dvec, avec, vec);
939                         project_v3_v3v3(pvec, dvec, vec);
940                         sub_v3_v3v3(dvec, dvec, pvec);
941
942                         w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
943                         dx= re->winx*dvec[0]*re->winmat[0][0]/w;
944                         dy= re->winy*dvec[1]*re->winmat[1][1]/w;
945                         w = sqrtf(dx * dx + dy * dy);
946                         if (dot_v3v3(anor, nor)<sd->adapt_angle && w>sd->adapt_pix) {
947                                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
948                                 vlr->flag= flag;
949                                 vlr->v1= v1;
950                                 vlr->v2= v2;
951                                 vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
952                                 vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
953
954                                 v1= vlr->v4; /* cycle */
955                                 v2= vlr->v3; /* cycle */
956
957                                 copy_v3_v3(anor, nor);
958                                 copy_v3_v3(avec, vec);
959                         }
960                         else {
961                                 vlr= RE_findOrAddVlak(obr, obr->totvlak-1);
962                         }
963                 }
964         
965                 copy_v3_v3(vlr->v4->co, vec);
966                 add_v3_v3(vlr->v4->co, cross);
967                 copy_v3_v3(vlr->v4->n, nor);
968                 vlr->v4->orco= sd->orco;
969                 vlr->v4->accum= -1.0f + 2.0f * sd->time;  /* accum abuse for strand texco */
970
971                 copy_v3_v3(vlr->v3->co, vec);
972                 sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross);
973                 copy_v3_v3(vlr->v3->n, nor);
974                 vlr->v3->orco= sd->orco;
975                 vlr->v3->accum= vlr->v4->accum;
976                 
977                 normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
978                 
979                 vlr->mat= ma;
980                 vlr->ec= ME_V2V3;
981
982                 if (sd->surfnor) {
983                         float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
984                         copy_v3_v3(snor, sd->surfnor);
985                 }
986
987                 if (sd->uvco) {
988                         for (i=0; i<sd->totuv; i++) {
989                                 MTFace *mtf;
990                                 mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1);
991                                 mtf->uv[0][0]=mtf->uv[1][0]=
992                                 mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
993                                 mtf->uv[0][1]=mtf->uv[1][1]=
994                                 mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
995                         }
996                         if (sd->override_uv>=0) {
997                                 MTFace *mtf;
998                                 mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0);
999                                 
1000                                 mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
1001                                 mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
1002
1003                                 mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f;
1004                                 mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f;
1005                         }
1006                 }
1007                 if (sd->mcol) {
1008                         for (i=0; i<sd->totcol; i++) {
1009                                 MCol *mc;
1010                                 mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1);
1011                                 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
1012                                 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
1013                         }
1014                 }
1015         }
1016 }
1017
1018 static void static_particle_wire(ObjectRen *obr, Material *ma, const float vec[3], const float vec1[3], int first, int line)
1019 {
1020         VlakRen *vlr;
1021         static VertRen *v1;
1022
1023         if (line) {
1024                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1025                 vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
1026                 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1027                 vlr->v3= vlr->v2;
1028                 vlr->v4= NULL;
1029                 
1030                 copy_v3_v3(vlr->v1->co, vec);
1031                 copy_v3_v3(vlr->v2->co, vec1);
1032                 
1033                 sub_v3_v3v3(vlr->n, vec, vec1);
1034                 normalize_v3(vlr->n);
1035                 copy_v3_v3(vlr->v1->n, vlr->n);
1036                 copy_v3_v3(vlr->v2->n, vlr->n);
1037                 
1038                 vlr->mat= ma;
1039                 vlr->ec= ME_V1V2;
1040
1041         }
1042         else if (first) {
1043                 v1= RE_findOrAddVert(obr, obr->totvert++);
1044                 copy_v3_v3(v1->co, vec);
1045         }
1046         else {
1047                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1048                 vlr->v1= v1;
1049                 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1050                 vlr->v3= vlr->v2;
1051                 vlr->v4= NULL;
1052                 
1053                 v1= vlr->v2; /* cycle */
1054                 copy_v3_v3(v1->co, vec);
1055                 
1056                 sub_v3_v3v3(vlr->n, vec, vec1);
1057                 normalize_v3(vlr->n);
1058                 copy_v3_v3(v1->n, vlr->n);
1059                 
1060                 vlr->mat= ma;
1061                 vlr->ec= ME_V1V2;
1062         }
1063
1064 }
1065
1066 static void particle_curve(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd,
1067                            const float loc[3], const float loc1[3], int seed, float *pa_co)
1068 {
1069         HaloRen *har = NULL;
1070
1071         if (ma->material_type == MA_TYPE_WIRE)
1072                 static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
1073         else if (ma->material_type == MA_TYPE_HALO) {
1074                 har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed, pa_co);
1075                 if (har) har->lay= obr->ob->lay;
1076         }
1077         else
1078                 static_particle_strand(re, obr, ma, sd, loc, loc1);
1079 }
1080 static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb)
1081 {
1082         VlakRen *vlr;
1083         MTFace *mtf;
1084         float xvec[3], yvec[3], zvec[3], bb_center[3];
1085         /* Number of tiles */
1086         int totsplit = bb->uv_split * bb->uv_split;
1087         int tile, x, y;
1088         /* Tile offsets */
1089         float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f;
1090
1091         vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1092         vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
1093         vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1094         vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
1095         vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
1096
1097         psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
1098
1099         add_v3_v3v3(vlr->v1->co, bb_center, xvec);
1100         add_v3_v3(vlr->v1->co, yvec);
1101         mul_m4_v3(re->viewmat, vlr->v1->co);
1102
1103         sub_v3_v3v3(vlr->v2->co, bb_center, xvec);
1104         add_v3_v3(vlr->v2->co, yvec);
1105         mul_m4_v3(re->viewmat, vlr->v2->co);
1106
1107         sub_v3_v3v3(vlr->v3->co, bb_center, xvec);
1108         sub_v3_v3v3(vlr->v3->co, vlr->v3->co, yvec);
1109         mul_m4_v3(re->viewmat, vlr->v3->co);
1110
1111         add_v3_v3v3(vlr->v4->co, bb_center, xvec);
1112         sub_v3_v3(vlr->v4->co, yvec);
1113         mul_m4_v3(re->viewmat, vlr->v4->co);
1114
1115         normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
1116         copy_v3_v3(vlr->v1->n, vlr->n);
1117         copy_v3_v3(vlr->v2->n, vlr->n);
1118         copy_v3_v3(vlr->v3->n, vlr->n);
1119         copy_v3_v3(vlr->v4->n, vlr->n);
1120         
1121         vlr->mat= ma;
1122         vlr->ec= ME_V2V3;
1123
1124         if (bb->uv_split > 1) {
1125                 uvdx = uvdy = 1.0f / (float)bb->uv_split;
1126
1127                 if (ELEM(bb->anim, PART_BB_ANIM_AGE, PART_BB_ANIM_FRAME)) {
1128                         if (bb->anim == PART_BB_ANIM_FRAME)
1129                                 time = ((int)(bb->time * bb->lifetime) % totsplit)/(float)totsplit;
1130                         else
1131                                 time = bb->time;
1132                 }
1133                 else if (bb->anim == PART_BB_ANIM_ANGLE) {
1134                         if (bb->align == PART_BB_VIEW) {
1135                                 time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0);
1136                         }
1137                         else {
1138                                 float axis1[3] = {0.0f, 0.0f, 0.0f};
1139                                 float axis2[3] = {0.0f, 0.0f, 0.0f};
1140
1141                                 axis1[(bb->align + 1) % 3] = 1.0f;
1142                                 axis2[(bb->align + 2) % 3] = 1.0f;
1143
1144                                 if (bb->lock == 0) {
1145                                         zvec[bb->align] = 0.0f;
1146                                         normalize_v3(zvec);
1147                                 }
1148                                 
1149                                 time = saacos(dot_v3v3(zvec, axis1)) / (float)M_PI;
1150                                 
1151                                 if (dot_v3v3(zvec, axis2) < 0.0f)
1152                                         time = 1.0f - time / 2.0f;
1153                                 else
1154                                         time /= 2.0f;
1155                         }
1156                 }
1157
1158                 if (bb->split_offset == PART_BB_OFF_LINEAR)
1159                         time = (float)fmod(time + (float)bb->num / (float)totsplit, 1.0f);
1160                 else if (bb->split_offset==PART_BB_OFF_RANDOM)
1161                         time = (float)fmod(time + bb->random, 1.0f);
1162
1163                 /* Find the coordinates in tile space (integer), then convert to UV
1164                  * space (float). Note that Y is flipped. */
1165                 tile = (int)((time + FLT_EPSILON10) * totsplit);
1166                 x = tile % bb->uv_split;
1167                 y = tile / bb->uv_split;
1168                 y = (bb->uv_split - 1) - y;
1169                 uvx = uvdx * x;
1170                 uvy = uvdy * y;
1171         }
1172
1173         /* normal UVs */
1174         if (bb->uv[0] >= 0) {
1175                 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1);
1176                 mtf->uv[0][0] = 1.0f;
1177                 mtf->uv[0][1] = 1.0f;
1178                 mtf->uv[1][0] = 0.0f;
1179                 mtf->uv[1][1] = 1.0f;
1180                 mtf->uv[2][0] = 0.0f;
1181                 mtf->uv[2][1] = 0.0f;
1182                 mtf->uv[3][0] = 1.0f;
1183                 mtf->uv[3][1] = 0.0f;
1184         }
1185
1186         /* time-index UVs */
1187         if (bb->uv[1] >= 0) {
1188                 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1);
1189                 mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time;
1190                 mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum;
1191         }
1192
1193         /* split UVs */
1194         if (bb->uv_split > 1 && bb->uv[2] >= 0) {
1195                 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1);
1196                 mtf->uv[0][0] = uvx + uvdx;
1197                 mtf->uv[0][1] = uvy + uvdy;
1198                 mtf->uv[1][0] = uvx;
1199                 mtf->uv[1][1] = uvy + uvdy;
1200                 mtf->uv[2][0] = uvx;
1201                 mtf->uv[2][1] = uvy;
1202                 mtf->uv[3][0] = uvx + uvdx;
1203                 mtf->uv[3][1] = uvy;
1204         }
1205 }
1206 static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, ParticleBillboardData *bb, ParticleKey *state, int seed, float hasize, float *pa_co)
1207 {
1208         float loc[3], loc0[3], loc1[3], vel[3];
1209         
1210         copy_v3_v3(loc, state->co);
1211
1212         if (ren_as != PART_DRAW_BB)
1213                 mul_m4_v3(re->viewmat, loc);
1214
1215         switch (ren_as) {
1216                 case PART_DRAW_LINE:
1217                         sd->line = 1;
1218                         sd->time = 0.0f;
1219                         sd->size = hasize;
1220
1221                         mul_v3_mat3_m4v3(vel, re->viewmat, state->vel);
1222                         normalize_v3(vel);
1223
1224                         if (part->draw & PART_DRAW_VEL_LENGTH)
1225                                 mul_v3_fl(vel, len_v3(state->vel));
1226
1227                         madd_v3_v3v3fl(loc0, loc, vel, -part->draw_line[0]);
1228                         madd_v3_v3v3fl(loc1, loc, vel, part->draw_line[1]);
1229
1230                         particle_curve(re, obr, dm, ma, sd, loc0, loc1, seed, pa_co);
1231
1232                         break;
1233
1234                 case PART_DRAW_BB:
1235
1236                         copy_v3_v3(bb->vec, loc);
1237                         copy_v3_v3(bb->vel, state->vel);
1238
1239                         particle_billboard(re, obr, ma, bb);
1240
1241                         break;
1242
1243                 default:
1244                 {
1245                         HaloRen *har = NULL;
1246
1247                         har = RE_inithalo_particle(re, obr, dm, ma, loc, NULL, sd->orco, sd->uvco, hasize, 0.0, seed, pa_co);
1248                         
1249                         if (har) har->lay= obr->ob->lay;
1250
1251                         break;
1252                 }
1253         }
1254 }
1255 static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd)
1256 {
1257         int i;
1258
1259         /* get uvco */
1260         if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
1261                 for (i=0; i<sd->totuv; i++) {
1262                         if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
1263                                 MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
1264                                 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
1265                                 mtface += num;
1266                                 
1267                                 psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i);
1268                         }
1269                         else {
1270                                 sd->uvco[2*i] = 0.0f;
1271                                 sd->uvco[2*i + 1] = 0.0f;
1272                         }
1273                 }
1274         }
1275
1276         /* get mcol */
1277         if (sd->mcol && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
1278                 for (i=0; i<sd->totcol; i++) {
1279                         if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
1280                                 MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
1281                                 MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
1282                                 mc += num * 4;
1283
1284                                 psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i);
1285                         }
1286                         else
1287                                 memset(&sd->mcol[i], 0, sizeof(MCol));
1288                 }
1289         }
1290 }
1291 static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
1292 {
1293         Object *ob= obr->ob;
1294 //      Object *tob=0;
1295         Material *ma = NULL;
1296         ParticleSystemModifierData *psmd;
1297         ParticleSystem *tpsys = NULL;
1298         ParticleSettings *part, *tpart = NULL;
1299         ParticleData *pars, *pa = NULL, *tpa = NULL;
1300         ParticleKey *states = NULL;
1301         ParticleKey state;
1302         ParticleCacheKey *cache = NULL;
1303         ParticleBillboardData bb;
1304         ParticleSimulationData sim = {NULL};
1305         ParticleStrandData sd;
1306         StrandBuffer *strandbuf = NULL;
1307         StrandVert *svert = NULL;
1308         StrandBound *sbound = NULL;
1309         StrandRen *strand = NULL;
1310         RNG *rng = NULL;
1311         float loc[3], loc1[3], loc0[3], mat[4][4], nmat[3][3], co[3], nor[3], duplimat[4][4];
1312         float strandlen=0.0f, curlen=0.0f;
1313         float hasize, pa_size, r_tilt, r_length;
1314         float pa_time, pa_birthtime, pa_dietime;
1315         float random, simplify[2], pa_co[3];
1316         const float cfra= BKE_scene_frame_get(re->scene);
1317         int i, a, k, max_k=0, totpart;
1318         bool do_simplify = false, do_surfacecache = false, use_duplimat = false;
1319         int totchild=0, step_nbr;
1320         int seed, path_nbr=0, orco1=0, num;
1321         int totface;
1322
1323         const int *index_mf_to_mpoly = NULL;
1324         const int *index_mp_to_orig = NULL;
1325
1326 /* 1. check that everything is ok & updated */
1327         if (psys==NULL)
1328                 return 0;
1329
1330         part=psys->part;
1331         pars=psys->particles;
1332
1333         if (part==NULL || pars==NULL || !psys_check_enabled(ob, psys))
1334                 return 0;
1335         
1336         if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT)
1337                 return 1;
1338
1339         if ((re->r.scemode & R_VIEWPORT_PREVIEW) && (ob->mode & OB_MODE_PARTICLE_EDIT))
1340                 return 0;
1341
1342         if (part->ren_as == PART_DRAW_BB && part->bb_ob == NULL && RE_GetCamera(re) == NULL)
1343                 return 0;
1344
1345 /* 2. start initializing things */
1346
1347         /* last possibility to bail out! */
1348         psmd = psys_get_modifier(ob, psys);
1349         if (!(psmd->modifier.mode & eModifierMode_Render))
1350                 return 0;
1351
1352         sim.scene= re->scene;
1353         sim.ob= ob;
1354         sim.psys= psys;
1355         sim.psmd= psmd;
1356
1357         if (part->phystype==PART_PHYS_KEYED)
1358                 psys_count_keyed_targets(&sim);
1359
1360         totchild=psys->totchild;
1361
1362         /* can happen for disconnected/global hair */
1363         if (part->type==PART_HAIR && !psys->childcache)
1364                 totchild= 0;
1365
1366         if (re->r.scemode & R_VIEWPORT_PREVIEW) { /* preview render */
1367                 totchild = (int)((float)totchild * (float)part->disp / 100.0f);
1368                 step_nbr = 1 << part->draw_step;
1369         }
1370         else {
1371                 step_nbr = 1 << part->ren_step;
1372         }
1373         if (ELEM(part->kink, PART_KINK_SPIRAL))
1374                 step_nbr += part->kink_extra_steps;
1375
1376         psys->flag |= PSYS_DRAWING;
1377
1378         rng= BLI_rng_new(psys->seed);
1379
1380         totpart=psys->totpart;
1381
1382         memset(&sd, 0, sizeof(ParticleStrandData));
1383         sd.override_uv = -1;
1384
1385 /* 2.1 setup material stff */
1386         ma= give_render_material(re, ob, part->omat);
1387         
1388 #if 0  /* XXX old animation system */
1389         if (ma->ipo) {
1390                 calc_ipo(ma->ipo, cfra);
1391                 execute_ipo((ID *)ma, ma->ipo);
1392         }
1393 #endif  /* XXX old animation system */
1394
1395         hasize = ma->hasize;
1396         seed = ma->seed1;
1397
1398         re->flag |= R_HALO;
1399
1400         RE_set_customdata_names(obr, &psmd->dm_final->faceData);
1401         sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE);
1402         sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL);
1403
1404         if (ma->texco & TEXCO_UV && sd.totuv) {
1405                 sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
1406
1407                 if (ma->strand_uvname[0]) {
1408                         sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname);
1409                         sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
1410                 }
1411         }
1412         else
1413                 sd.uvco = NULL;
1414
1415         if (sd.totcol)
1416                 sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols");
1417
1418 /* 2.2 setup billboards */
1419         if (part->ren_as == PART_DRAW_BB) {
1420                 int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
1421
1422                 bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]);
1423                 if (bb.uv[0] < 0)
1424                         bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
1425
1426                 bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]);
1427
1428                 bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]);
1429
1430                 if (first_uv >= 0) {
1431                         bb.uv[0] -= first_uv;
1432                         bb.uv[1] -= first_uv;
1433                         bb.uv[2] -= first_uv;
1434                 }
1435
1436                 bb.align = part->bb_align;
1437                 bb.anim = part->bb_anim;
1438                 bb.lock = part->draw & PART_DRAW_BB_LOCK;
1439                 bb.ob = (part->bb_ob ? part->bb_ob : RE_GetCamera(re));
1440                 bb.split_offset = part->bb_split_offset;
1441                 bb.totnum = totpart+totchild;
1442                 bb.uv_split = part->bb_uv_split;
1443         }
1444         
1445 /* 2.5 setup matrices */
1446         mul_m4_m4m4(mat, re->viewmat, ob->obmat);
1447         invert_m4_m4(ob->imat, mat);    /* need to be that way, for imat texture */
1448         transpose_m3_m4(nmat, ob->imat);
1449
1450         if (psys->flag & PSYS_USE_IMAT) {
1451                 /* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */
1452                 mul_m4_m4m4(duplimat, ob->obmat, psys->imat);
1453                 use_duplimat = true;
1454         }
1455
1456 /* 2.6 setup strand rendering */
1457         if (part->ren_as == PART_DRAW_PATH && psys->pathcache) {
1458                 path_nbr = step_nbr;
1459
1460                 if (path_nbr) {
1461                         if (!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) {
1462                                 sd.orco = get_object_orco(re, psys);
1463                                 if (!sd.orco) {
1464                                         sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
1465                                         set_object_orco(re, psys, sd.orco);
1466                                 }
1467                         }
1468                 }
1469
1470                 if (part->draw & PART_DRAW_REN_ADAPT) {
1471                         sd.adapt = 1;
1472                         sd.adapt_pix = (float)part->adapt_pix;
1473                         sd.adapt_angle = cosf(DEG2RADF((float)part->adapt_angle));
1474                 }
1475
1476                 if (part->draw & PART_DRAW_REN_STRAND) {
1477                         strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
1478                         strandbuf->ma= ma;
1479                         strandbuf->lay= ob->lay;
1480                         copy_m4_m4(strandbuf->winmat, re->winmat);
1481                         strandbuf->winx= re->winx;
1482                         strandbuf->winy= re->winy;
1483                         strandbuf->maxdepth= 2;
1484                         strandbuf->adaptcos= cosf(DEG2RADF((float)part->adapt_angle));
1485                         strandbuf->overrideuv= sd.override_uv;
1486                         strandbuf->minwidth= ma->strand_min;
1487
1488                         if (ma->strand_widthfade == 0.0f)
1489                                 strandbuf->widthfade= -1.0f;
1490                         else if (ma->strand_widthfade >= 1.0f)
1491                                 strandbuf->widthfade= 2.0f - ma->strand_widthfade;
1492                         else
1493                                 strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
1494
1495                         if (part->flag & PART_HAIR_BSPLINE)
1496                                 strandbuf->flag |= R_STRAND_BSPLINE;
1497                         if (ma->mode & MA_STR_B_UNITS)
1498                                 strandbuf->flag |= R_STRAND_B_UNITS;
1499
1500                         svert= strandbuf->vert;
1501
1502                         if (re->r.mode & R_SPEED)
1503                                 do_surfacecache = true;
1504                         else if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
1505                                 if (ma->amb != 0.0f)
1506                                         do_surfacecache = true;
1507
1508                         totface= psmd->dm_final->getNumTessFaces(psmd->dm_final);
1509                         index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX);
1510                         index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX);
1511                         if (index_mf_to_mpoly == NULL) {
1512                                 index_mp_to_orig = NULL;
1513                         }
1514                         for (a=0; a<totface; a++)
1515                                 strandbuf->totbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a);
1516
1517                         strandbuf->totbound++;
1518                         strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
1519                         sbound= strandbuf->bound;
1520                         sbound->start= sbound->end= 0;
1521                 }
1522         }
1523
1524         if (sd.orco == NULL) {
1525                 sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco");
1526                 orco1 = 1;
1527         }
1528
1529         if (path_nbr == 0)
1530                 psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
1531
1532 /* 3. start creating renderable things */
1533         for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) {
1534                 random = BLI_rng_get_float(rng);
1535                 /* setup per particle individual stuff */
1536                 if (a<totpart) {
1537                         if (pa->flag & PARS_UNEXIST) continue;
1538
1539                         pa_time=(cfra-pa->time)/pa->lifetime;
1540                         pa_birthtime = pa->time;
1541                         pa_dietime = pa->dietime;
1542
1543                         hasize = ma->hasize;
1544
1545                         /* XXX 'tpsys' is alwyas NULL, this code won't run! */
1546                         /* get orco */
1547                         if (tpsys && part->phystype == PART_PHYS_NO) {
1548                                 tpa = tpsys->particles + pa->num;
1549                                 psys_particle_on_emitter(
1550                                         psmd,
1551                                         tpart->from, tpa->num, pa->num_dmcache, tpa->fuv,
1552                                         tpa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
1553                         }
1554                         else {
1555                                 psys_particle_on_emitter(
1556                                         psmd,
1557                                         part->from, pa->num, pa->num_dmcache,
1558                                         pa->fuv, pa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
1559                         }
1560
1561                         /* get uvco & mcol */
1562                         num= pa->num_dmcache;
1563
1564                         if (num == DMCACHE_NOTFOUND)
1565                                 if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
1566                                         num= pa->num;
1567
1568                         get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd);
1569
1570                         pa_size = pa->size;
1571
1572                         r_tilt = 2.0f*(psys_frand(psys, a) - 0.5f);
1573                         r_length = psys_frand(psys, a+1);
1574
1575                         if (path_nbr) {
1576                                 cache = psys->pathcache[a];
1577                                 max_k = (int)cache->segments;
1578                         }
1579
1580                         if (totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
1581                 }
1582                 else {
1583                         ChildParticle *cpa= psys->child+a-totpart;
1584
1585                         if (path_nbr) {
1586                                 cache = psys->childcache[a-totpart];
1587
1588                                 if (cache->segments < 0)
1589                                         continue;
1590
1591                                 max_k = (int)cache->segments;
1592                         }
1593                         
1594                         pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
1595                         pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);
1596
1597                         r_tilt = 2.0f*(psys_frand(psys, a + 21) - 0.5f);
1598                         r_length = psys_frand(psys, a + 22);
1599
1600                         num = cpa->num;
1601
1602                         /* get orco */
1603                         if (part->childtype == PART_CHILD_FACES) {
1604                                 psys_particle_on_emitter(
1605                                         psmd,
1606                                         PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD,
1607                                         cpa->fuv, cpa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
1608                         }
1609                         else {
1610                                 ParticleData *par = psys->particles + cpa->parent;
1611                                 psys_particle_on_emitter(
1612                                         psmd,
1613                                         part->from, par->num, DMCACHE_ISCHILD, par->fuv,
1614                                         par->foffset, co, nor, NULL, NULL, sd.orco, NULL);
1615                         }
1616
1617                         /* get uvco & mcol */
1618                         if (part->childtype==PART_CHILD_FACES) {
1619                                 get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd);
1620                         }
1621                         else {
1622                                 ParticleData *parent = psys->particles + cpa->parent;
1623                                 num = parent->num_dmcache;
1624
1625                                 if (num == DMCACHE_NOTFOUND)
1626                                         if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
1627                                                 num = parent->num;
1628
1629                                 get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
1630                         }
1631
1632                         do_simplify = psys_render_simplify_params(psys, cpa, simplify);
1633
1634                         if (strandbuf) {
1635                                 int orignum = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, cpa->num) : cpa->num;
1636
1637                                 if ((orignum > sbound - strandbuf->bound) &&
1638                                     (orignum < strandbuf->totbound))
1639                                 {
1640                                         sbound = &strandbuf->bound[orignum];
1641                                         sbound->start = sbound->end = obr->totstrand;
1642                                 }
1643                         }
1644                 }
1645
1646                 /* TEXCO_PARTICLE */
1647                 pa_co[0] = pa_time;
1648                 pa_co[1] = 0.f;
1649                 pa_co[2] = 0.f;
1650
1651                 /* surface normal shading setup */
1652                 if (ma->mode_l & MA_STR_SURFDIFF) {
1653                         mul_m3_v3(nmat, nor);
1654                         sd.surfnor= nor;
1655                 }
1656                 else
1657                         sd.surfnor= NULL;
1658
1659                 /* strand render setup */
1660                 if (strandbuf) {
1661                         strand= RE_findOrAddStrand(obr, obr->totstrand++);
1662                         strand->buffer= strandbuf;
1663                         strand->vert= svert;
1664                         copy_v3_v3(strand->orco, sd.orco);
1665
1666                         if (do_simplify) {
1667                                 float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
1668                                 ssimplify[0]= simplify[0];
1669                                 ssimplify[1]= simplify[1];
1670                         }
1671
1672                         if (sd.surfnor) {
1673                                 float *snor= RE_strandren_get_surfnor(obr, strand, 1);
1674                                 copy_v3_v3(snor, sd.surfnor);
1675                         }
1676
1677                         if (do_surfacecache && num >= 0) {
1678                                 int *facenum= RE_strandren_get_face(obr, strand, 1);
1679                                 *facenum= num;
1680                         }
1681
1682                         if (sd.uvco) {
1683                                 for (i=0; i<sd.totuv; i++) {
1684                                         if (i != sd.override_uv) {
1685                                                 float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
1686
1687                                                 uv[0]= sd.uvco[2*i];
1688                                                 uv[1]= sd.uvco[2*i+1];
1689                                         }
1690                                 }
1691                         }
1692                         if (sd.mcol) {
1693                                 for (i=0; i<sd.totcol; i++) {
1694                                         MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1);
1695                                         *mc = sd.mcol[i];
1696                                 }
1697                         }
1698
1699                         sbound->end++;
1700                 }
1701
1702                 /* strandco computation setup */
1703                 if (path_nbr) {
1704                         strandlen= 0.0f;
1705                         curlen= 0.0f;
1706                         for (k=1; k<=path_nbr; k++)
1707                                 if (k<=max_k)
1708                                         strandlen += len_v3v3((cache+k-1)->co, (cache+k)->co);
1709                 }
1710
1711                 if (path_nbr) {
1712                         /* render strands */
1713                         for (k=0; k<=path_nbr; k++) {
1714                                 float time;
1715
1716                                 if (k<=max_k) {
1717                                         copy_v3_v3(state.co, (cache+k)->co);
1718                                         copy_v3_v3(state.vel, (cache+k)->vel);
1719                                 }
1720                                 else
1721                                         continue;
1722
1723                                 if (k > 0)
1724                                         curlen += len_v3v3((cache+k-1)->co, (cache+k)->co);
1725                                 time= curlen/strandlen;
1726
1727                                 copy_v3_v3(loc, state.co);
1728                                 mul_m4_v3(re->viewmat, loc);
1729
1730                                 if (strandbuf) {
1731                                         copy_v3_v3(svert->co, loc);
1732                                         svert->strandco= -1.0f + 2.0f*time;
1733                                         svert++;
1734                                         strand->totvert++;
1735                                 }
1736                                 else {
1737                                         sd.size = hasize;
1738
1739                                         if (k==1) {
1740                                                 sd.first = 1;
1741                                                 sd.time = 0.0f;
1742                                                 sub_v3_v3v3(loc0, loc1, loc);
1743                                                 add_v3_v3v3(loc0, loc1, loc0);
1744
1745                                                 particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co);
1746                                         }
1747
1748                                         sd.first = 0;
1749                                         sd.time = time;
1750
1751                                         if (k)
1752                                                 particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co);
1753
1754                                         copy_v3_v3(loc1, loc);
1755                                 }
1756                         }
1757
1758                 }
1759                 else {
1760                         /* render normal particles */
1761                         if (part->trail_count > 1) {
1762                                 float length = part->path_end * (1.0f - part->randlength * r_length);
1763                                 int trail_count = part->trail_count * (1.0f - part->randlength * r_length);
1764                                 float ct = (part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time;
1765                                 float dt = length / (trail_count ? (float)trail_count : 1.0f);
1766
1767                                 /* make sure we have pointcache in memory before getting particle on path */
1768                                 psys_make_temp_pointcache(ob, psys);
1769
1770                                 for (i=0; i < trail_count; i++, ct -= dt) {
1771                                         if (part->draw & PART_ABS_PATH_TIME) {
1772                                                 if (ct < pa_birthtime || ct > pa_dietime)
1773                                                         continue;
1774                                         }
1775                                         else if (ct < 0.0f || ct > 1.0f)
1776                                                 continue;
1777
1778                                         state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
1779                                         psys_get_particle_on_path(&sim, a, &state, 1);
1780
1781                                         if (psys->parent)
1782                                                 mul_m4_v3(psys->parent->obmat, state.co);
1783
1784                                         if (use_duplimat)
1785                                                 mul_m4_v4(duplimat, state.co);
1786
1787                                         if (part->ren_as == PART_DRAW_BB) {
1788                                                 bb.random = random;
1789                                                 bb.offset[0] = part->bb_offset[0];
1790                                                 bb.offset[1] = part->bb_offset[1];
1791                                                 bb.size[0] = part->bb_size[0] * pa_size;
1792                                                 if (part->bb_align==PART_BB_VEL) {
1793                                                         float pa_vel = len_v3(state.vel);
1794                                                         float head = part->bb_vel_head*pa_vel;
1795                                                         float tail = part->bb_vel_tail*pa_vel;
1796                                                         bb.size[1] = part->bb_size[1]*pa_size + head + tail;
1797                                                         /* use offset to adjust the particle center. this is relative to size, so need to divide! */
1798                                                         if (bb.size[1] > 0.0f)
1799                                                                 bb.offset[1] += (head-tail) / bb.size[1];
1800                                                 }
1801                                                 else
1802                                                         bb.size[1] = part->bb_size[1] * pa_size;
1803                                                 bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
1804                                                 bb.time = ct;
1805                                                 bb.num = a;
1806                                         }
1807
1808                                         pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct;
1809                                         pa_co[1] = (float)i/(float)(trail_count-1);
1810
1811                                         particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
1812                                 }
1813                         }
1814                         else {
1815                                 state.time=cfra;
1816                                 if (psys_get_particle_state(&sim, a, &state, 0)==0)
1817                                         continue;
1818
1819                                 if (psys->parent)
1820                                         mul_m4_v3(psys->parent->obmat, state.co);
1821
1822                                 if (use_duplimat)
1823                                         mul_m4_v3(duplimat, state.co);
1824
1825                                 if (part->ren_as == PART_DRAW_BB) {
1826                                         bb.random = random;
1827                                         bb.offset[0] = part->bb_offset[0];
1828                                         bb.offset[1] = part->bb_offset[1];
1829                                         bb.size[0] = part->bb_size[0] * pa_size;
1830                                         if (part->bb_align==PART_BB_VEL) {
1831                                                 float pa_vel = len_v3(state.vel);
1832                                                 float head = part->bb_vel_head*pa_vel;
1833                                                 float tail = part->bb_vel_tail*pa_vel;
1834                                                 bb.size[1] = part->bb_size[1]*pa_size + head + tail;
1835                                                 /* use offset to adjust the particle center. this is relative to size, so need to divide! */
1836                                                 if (bb.size[1] > 0.0f)
1837                                                         bb.offset[1] += (head-tail) / bb.size[1];
1838                                         }
1839                                         else
1840                                                 bb.size[1] = part->bb_size[1] * pa_size;
1841                                         bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
1842                                         bb.time = pa_time;
1843                                         bb.num = a;
1844                                         bb.lifetime = pa_dietime-pa_birthtime;
1845                                 }
1846
1847                                 particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
1848                         }
1849                 }
1850
1851                 if (orco1==0)
1852                         sd.orco+=3;
1853
1854                 if (re->test_break(re->tbh))
1855                         break;
1856         }
1857
1858         if (do_surfacecache)
1859                 strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset);
1860
1861 /* 4. clean up */
1862 #if 0  /* XXX old animation system */
1863         if (ma) do_mat_ipo(re->scene, ma);
1864 #endif  /* XXX old animation system */
1865
1866         if (orco1)
1867                 MEM_freeN(sd.orco);
1868
1869         if (sd.uvco)
1870                 MEM_freeN(sd.uvco);
1871         
1872         if (sd.mcol)
1873                 MEM_freeN(sd.mcol);
1874
1875         if (states)
1876                 MEM_freeN(states);
1877         
1878         BLI_rng_free(rng);
1879
1880         psys->flag &= ~PSYS_DRAWING;
1881
1882         if (psys->lattice_deform_data) {
1883                 end_latt_deform(psys->lattice_deform_data);
1884                 psys->lattice_deform_data = NULL;
1885         }
1886
1887         if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
1888                 calc_vertexnormals(re, obr, 1, 0, 0);
1889
1890         return 1;
1891 }
1892
1893 /* ------------------------------------------------------------------------- */
1894 /* Halo's                                                                                                                                */
1895 /* ------------------------------------------------------------------------- */
1896
1897 static void make_render_halos(Render *re, ObjectRen *obr, Mesh *UNUSED(me), int totvert, MVert *mvert, Material *ma, float *orco)
1898 {
1899         Object *ob= obr->ob;
1900         HaloRen *har;
1901         float xn, yn, zn, nor[3], view[3];
1902         float vec[3], hasize, mat[4][4], imat[3][3];
1903         int a, ok, seed= ma->seed1;
1904
1905         mul_m4_m4m4(mat, re->viewmat, ob->obmat);
1906         copy_m3_m4(imat, ob->imat);
1907
1908         re->flag |= R_HALO;
1909
1910         for (a=0; a<totvert; a++, mvert++) {
1911                 ok= 1;
1912
1913                 if (ok) {
1914                         hasize= ma->hasize;
1915
1916                         copy_v3_v3(vec, mvert->co);
1917                         mul_m4_v3(mat, vec);
1918
1919                         if (ma->mode & MA_HALOPUNO) {
1920                                 xn= mvert->no[0];
1921                                 yn= mvert->no[1];
1922                                 zn= mvert->no[2];
1923
1924                                 /* transpose ! */
1925                                 nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
1926                                 nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
1927                                 nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
1928                                 normalize_v3(nor);
1929
1930                                 copy_v3_v3(view, vec);
1931                                 normalize_v3(view);
1932
1933                                 zn = dot_v3v3(nor, view);
1934                                 if (zn>=0.0f) hasize= 0.0f;
1935                                 else hasize*= zn*zn*zn*zn;
1936                         }
1937
1938                         if (orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed);
1939                         else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed);
1940                         if (har) har->lay= ob->lay;
1941                 }
1942                 if (orco) orco+= 3;
1943                 seed++;
1944         }
1945 }
1946
1947 static int verghalo(const void *a1, const void *a2)
1948 {
1949         const HaloRen *har1= *(const HaloRen**)a1;
1950         const HaloRen *har2= *(const HaloRen**)a2;
1951         
1952         if (har1->zs < har2->zs) return 1;
1953         else if (har1->zs > har2->zs) return -1;
1954         return 0;
1955 }
1956
1957 static void sort_halos(Render *re, int totsort)
1958 {
1959         ObjectRen *obr;
1960         HaloRen *har= NULL, **haso;
1961         int a;
1962
1963         if (re->tothalo==0) return;
1964
1965         re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos");
1966         haso= re->sortedhalos;
1967
1968         for (obr=re->objecttable.first; obr; obr=obr->next) {
1969                 for (a=0; a<obr->tothalo; a++) {
1970                         if ((a & 255)==0) har= obr->bloha[a>>8];
1971                         else har++;
1972
1973                         *(haso++)= har;
1974                 }
1975         }
1976
1977         qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo);
1978 }
1979
1980 /* ------------------------------------------------------------------------- */
1981 /* Displacement Mapping                                                                                                          */
1982 /* ------------------------------------------------------------------------- */
1983
1984 static short test_for_displace(Render *re, Object *ob)
1985 {
1986         /* return 1 when this object uses displacement textures. */
1987         Material *ma;
1988         int i;
1989         
1990         for (i=1; i<=ob->totcol; i++) {
1991                 ma=give_render_material(re, ob, i);
1992                 /* ma->mapto is ORed total of all mapto channels */
1993                 if (ma && (ma->mapto & MAP_DISPLACE)) return 1;
1994         }
1995         return 0;
1996 }
1997
1998 static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale)
1999 {
2000         MTFace *tface;
2001         short texco= shi->mat->texco;
2002         float sample=0, displace[3];
2003         char *name;
2004         int i;
2005
2006         /* shi->co is current render coord, just make sure at least some vector is here */
2007         copy_v3_v3(shi->co, vr->co);
2008         /* vertex normal is used for textures type 'col' and 'var' */
2009         copy_v3_v3(shi->vn, vr->n);
2010
2011         if (texco & TEXCO_UV) {
2012                 shi->totuv= 0;
2013                 shi->actuv= obr->actmtface;
2014
2015                 for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) {
2016                         ShadeInputUV *suv= &shi->uv[i];
2017
2018                         /* shi.uv needs scale correction from tface uv */
2019                         suv->uv[0]= 2*tface->uv[vindex][0]-1.0f;
2020                         suv->uv[1]= 2*tface->uv[vindex][1]-1.0f;
2021                         suv->uv[2]= 0.0f;
2022                         suv->name= name;
2023                         shi->totuv++;
2024                 }
2025         }
2026
2027         /* set all rendercoords, 'texco' is an ORed value for all textures needed */
2028         if ((texco & TEXCO_ORCO) && (vr->orco)) {
2029                 copy_v3_v3(shi->lo, vr->orco);
2030         }
2031         if (texco & TEXCO_GLOB) {
2032                 copy_v3_v3(shi->gl, shi->co);
2033                 mul_m4_v3(re->viewinv, shi->gl);
2034         }
2035         if (texco & TEXCO_NORM) {
2036                 copy_v3_v3(shi->orn, shi->vn);
2037         }
2038         if (texco & TEXCO_REFL) {
2039                 /* not (yet?) */
2040         }
2041         if (texco & TEXCO_STRESS) {
2042                 const float *s= RE_vertren_get_stress(obr, vr, 0);
2043
2044                 if (s) {
2045                         shi->stress= *s;
2046                         if (shi->stress<1.0f) shi->stress-= 1.0f;
2047                         else shi->stress= (shi->stress-1.0f)/shi->stress;
2048                 }
2049                 else
2050                         shi->stress= 0.0f;
2051         }
2052
2053         shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
2054         
2055         do_material_tex(shi, re);
2056         
2057         //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2], 
2058         //vr->co[0], vr->co[1], vr->co[2]);
2059
2060         displace[0]= shi->displace[0] * scale[0];
2061         displace[1]= shi->displace[1] * scale[1];
2062         displace[2]= shi->displace[2] * scale[2];
2063
2064         /* 0.5 could become button once?  */
2065         vr->co[0] += displace[0]; 
2066         vr->co[1] += displace[1];
2067         vr->co[2] += displace[2];
2068         
2069         //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]); 
2070         
2071         /* we just don't do this vertex again, bad luck for other face using same vertex with
2072          * different material... */
2073         vr->flag |= 1;
2074         
2075         /* Pass sample back so displace_face can decide which way to split the quad */
2076         sample  = shi->displace[0]*shi->displace[0];
2077         sample += shi->displace[1]*shi->displace[1];
2078         sample += shi->displace[2]*shi->displace[2];
2079         
2080         vr->accum=sample; 
2081         /* Should be sqrt(sample), but I'm only looking for "bigger".  Save the cycles. */
2082         return;
2083 }
2084
2085 static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float *scale)
2086 {
2087         ShadeInput shi;
2088
2089         /* Warning, This is not that nice, and possibly a bit slow,
2090          * however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
2091         memset(&shi, 0, sizeof(ShadeInput)); 
2092         /* end warning! - Campbell */
2093         
2094         /* set up shadeinput struct for multitex() */
2095         
2096         /* memset above means we don't need this */
2097         /*shi.osatex= 0;*/              /* signal not to use dx[] and dy[] texture AA vectors */
2098
2099         shi.obr= obr;
2100         shi.vlr= vlr;           /* current render face */
2101         shi.mat= vlr->mat;              /* current input material */
2102         shi.thread= 0;
2103         
2104         /* TODO, assign these, displacement with new bumpmap is skipped without - campbell */
2105 #if 0
2106         /* order is not known ? */
2107         shi.v1= vlr->v1;
2108         shi.v2= vlr->v2;
2109         shi.v3= vlr->v3;
2110 #endif
2111
2112         /* Displace the verts, flag is set when done */
2113         if (!vlr->v1->flag)
2114                 displace_render_vert(re, obr, &shi, vlr->v1, 0,  scale);
2115         
2116         if (!vlr->v2->flag)
2117                 displace_render_vert(re, obr, &shi, vlr->v2, 1, scale);
2118
2119         if (!vlr->v3->flag)
2120                 displace_render_vert(re, obr, &shi, vlr->v3, 2, scale);
2121
2122         if (vlr->v4) {
2123                 if (!vlr->v4->flag)
2124                         displace_render_vert(re, obr, &shi, vlr->v4, 3, scale);
2125
2126                 /*      closest in displace value.  This will help smooth edges.   */ 
2127                 if (fabsf(vlr->v1->accum - vlr->v3->accum) > fabsf(vlr->v2->accum - vlr->v4->accum)) vlr->flag |=  R_DIVIDE_24;
2128                 else                                                                                 vlr->flag &= ~R_DIVIDE_24;
2129         }
2130         
2131         /* Recalculate the face normal  - if flipped before, flip now */
2132         if (vlr->v4) {
2133                 normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2134         }
2135         else {
2136                 normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2137         }
2138 }
2139
2140 static void displace(Render *re, ObjectRen *obr)
2141 {
2142         VertRen *vr;
2143         VlakRen *vlr;
2144 //      float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30};
2145         float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn
2146         int i; //, texflag=0;
2147         Object *obt;
2148                 
2149         /* Object Size with parenting */
2150         obt=obr->ob;
2151         while (obt) {
2152                 mul_v3_v3v3(temp, obt->size, obt->dscale);
2153                 scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2];
2154                 obt=obt->parent;
2155         }
2156         
2157         /* Clear all flags */
2158         for (i=0; i<obr->totvert; i++) {
2159                 vr= RE_findOrAddVert(obr, i);
2160                 vr->flag= 0;
2161         }
2162
2163         for (i=0; i<obr->totvlak; i++) {
2164                 vlr=RE_findOrAddVlak(obr, i);
2165                 displace_render_face(re, obr, vlr, scale);
2166         }
2167         
2168         /* Recalc vertex normals */
2169         calc_vertexnormals(re, obr, 1, 0, 0);
2170 }
2171
2172 /* ------------------------------------------------------------------------- */
2173 /* Metaball                                                                                                                              */
2174 /* ------------------------------------------------------------------------- */
2175
2176 static void init_render_mball(Render *re, ObjectRen *obr)
2177 {
2178         Object *ob= obr->ob;
2179         DispList *dl;
2180         VertRen *ver;
2181         VlakRen *vlr, *vlr1;
2182         Material *ma;
2183         float *data, *nors, *orco=NULL, mat[4][4], imat[3][3], xn, yn, zn;
2184         int a, need_orco, vlakindex, *index, negative_scale;
2185         ListBase dispbase= {NULL, NULL};
2186
2187         if (ob!=BKE_mball_basis_find(re->scene, ob))
2188                 return;
2189
2190         mul_m4_m4m4(mat, re->viewmat, ob->obmat);
2191         invert_m4_m4(ob->imat, mat);
2192         copy_m3_m4(imat, ob->imat);
2193         negative_scale = is_negative_m4(mat);
2194
2195         ma= give_render_material(re, ob, 1);
2196
2197         need_orco= 0;
2198         if (ma->texco & TEXCO_ORCO) {
2199                 need_orco= 1;
2200         }
2201
2202         BKE_displist_make_mball_forRender(re->eval_ctx, re->scene, ob, &dispbase);
2203         dl= dispbase.first;
2204         if (dl == NULL) return;
2205
2206         data= dl->verts;
2207         nors= dl->nors;
2208         if (need_orco) {
2209                 orco= get_object_orco(re, ob);
2210
2211                 if (!orco) {
2212                         /* orco hasn't been found in cache - create new one and add to cache */
2213                         orco= BKE_mball_make_orco(ob, &dispbase);
2214                         set_object_orco(re, ob, orco);
2215                 }
2216         }
2217
2218         for (a=0; a<dl->nr; a++, data+=3, nors+=3) {
2219
2220                 ver= RE_findOrAddVert(obr, obr->totvert++);
2221                 copy_v3_v3(ver->co, data);
2222                 mul_m4_v3(mat, ver->co);
2223
2224                 /* render normals are inverted */
2225                 xn= -nors[0];
2226                 yn= -nors[1];
2227                 zn= -nors[2];
2228
2229                 /* transpose ! */
2230                 ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
2231                 ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
2232                 ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
2233                 normalize_v3(ver->n);
2234                 //if (ob->transflag & OB_NEG_SCALE) negate_v3(ver->n);
2235                 
2236                 if (need_orco) {
2237                         ver->orco= orco;
2238                         orco+=3;
2239                 }
2240         }
2241
2242         index= dl->index;
2243         for (a=0; a<dl->parts; a++, index+=4) {
2244
2245                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2246                 vlr->v1= RE_findOrAddVert(obr, index[0]);
2247                 vlr->v2= RE_findOrAddVert(obr, index[1]);
2248                 vlr->v3= RE_findOrAddVert(obr, index[2]);
2249                 vlr->v4 = NULL;
2250
2251                 if (negative_scale)
2252                         normal_tri_v3(vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co);
2253                 else
2254                         normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2255
2256                 vlr->mat= ma;
2257                 vlr->flag= ME_SMOOTH;
2258                 vlr->ec= 0;
2259
2260                 /* mball -too bad- always has triangles, because quads can be non-planar */
2261                 if (index[3] && index[3]!=index[2]) {
2262                         vlr1= RE_findOrAddVlak(obr, obr->totvlak++);
2263                         vlakindex= vlr1->index;
2264                         *vlr1= *vlr;
2265                         vlr1->index= vlakindex;
2266                         vlr1->v2= vlr1->v3;
2267                         vlr1->v3= RE_findOrAddVert(obr, index[3]);
2268                         if (negative_scale)
2269                                 normal_tri_v3(vlr1->n, vlr1->v1->co, vlr1->v2->co, vlr1->v3->co);
2270                         else
2271                                 normal_tri_v3(vlr1->n, vlr1->v3->co, vlr1->v2->co, vlr1->v1->co);
2272                 }
2273         }
2274
2275         /* enforce display lists remade */
2276         BKE_displist_free(&dispbase);
2277 }
2278
2279 /* ------------------------------------------------------------------------- */
2280 /* Surfaces and Curves                                                                                                           */
2281 /* ------------------------------------------------------------------------- */
2282
2283 /* returns amount of vertices added for orco */
2284 static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4])
2285 {
2286         VertRen *v1, *v2, *v3, *v4, *ver;
2287         VlakRen *vlr, *vlr1, *vlr2, *vlr3;
2288         float *data, n1[3];
2289         int u, v, orcoret= 0;
2290         int p1, p2, p3, p4, a;
2291         int sizeu, nsizeu, sizev, nsizev;
2292         int startvert, startvlak;
2293         
2294         startvert= obr->totvert;
2295         nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; 
2296         
2297         data= dl->verts;
2298         for (u = 0; u < sizeu; u++) {
2299                 v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */
2300                 copy_v3_v3(v1->co, data); data += 3;
2301                 if (orco) {
2302                         v1->orco= orco; orco+= 3; orcoret++;
2303                 }
2304                 mul_m4_v3(mat, v1->co);
2305                 
2306                 for (v = 1; v < sizev; v++) {
2307                         ver= RE_findOrAddVert(obr, obr->totvert++);
2308                         copy_v3_v3(ver->co, data); data += 3;
2309                         if (orco) {
2310                                 ver->orco= orco; orco+= 3; orcoret++;
2311                         }
2312                         mul_m4_v3(mat, ver->co);
2313                 }
2314                 /* if V-cyclic, add extra vertices at end of the row */
2315                 if (dl->flag & DL_CYCL_U) {
2316                         ver= RE_findOrAddVert(obr, obr->totvert++);
2317                         copy_v3_v3(ver->co, v1->co);
2318                         if (orco) {
2319                                 ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0);
2320                         }
2321                 }
2322         }
2323         
2324         /* Done before next loop to get corner vert */
2325         if (dl->flag & DL_CYCL_U) nsizev++;
2326         if (dl->flag & DL_CYCL_V) nsizeu++;
2327         
2328         /* if U cyclic, add extra row at end of column */
2329         if (dl->flag & DL_CYCL_V) {
2330                 for (v = 0; v < nsizev; v++) {
2331                         v1= RE_findOrAddVert(obr, startvert + v);
2332                         ver= RE_findOrAddVert(obr, obr->totvert++);
2333                         copy_v3_v3(ver->co, v1->co);
2334                         if (orco) {
2335                                 ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v);
2336                         }
2337                 }
2338         }
2339         
2340         sizeu = nsizeu;
2341         sizev = nsizev;
2342         
2343         startvlak= obr->totvlak;
2344         
2345         for (u = 0; u < sizeu - 1; u++) {
2346                 p1 = startvert + u * sizev; /* walk through face list */
2347                 p2 = p1 + 1;
2348                 p3 = p2 + sizev;
2349                 p4 = p3 - 1;
2350                 
2351                 for (v = 0; v < sizev - 1; v++) {
2352                         v1= RE_findOrAddVert(obr, p1);
2353                         v2= RE_findOrAddVert(obr, p2);
2354                         v3= RE_findOrAddVert(obr, p3);
2355                         v4= RE_findOrAddVert(obr, p4);
2356                         
2357                         vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2358                         vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
2359                         
2360                         normal_quad_v3(n1, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2361                         
2362                         copy_v3_v3(vlr->n, n1);
2363                         
2364                         vlr->mat= matar[ dl->col];
2365                         vlr->ec= ME_V1V2+ME_V2V3;
2366                         vlr->flag= dl->rt;
2367                         
2368                         add_v3_v3(v1->n, n1);
2369                         add_v3_v3(v2->n, n1);
2370                         add_v3_v3(v3->n, n1);
2371                         add_v3_v3(v4->n, n1);
2372                         
2373                         p1++; p2++; p3++; p4++;
2374                 }
2375         }
2376         /* fix normals for U resp. V cyclic faces */
2377         sizeu--; sizev--;  /* dec size for face array */
2378         if (dl->flag & DL_CYCL_V) {
2379                 
2380                 for (v = 0; v < sizev; v++) {
2381                         /* optimize! :*/
2382                         vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v));
2383                         vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v));
2384                         add_v3_v3(vlr1->v1->n, vlr->n);
2385                         add_v3_v3(vlr1->v2->n, vlr->n);
2386                         add_v3_v3(vlr->v3->n, vlr1->n);
2387                         add_v3_v3(vlr->v4->n, vlr1->n);
2388                 }
2389         }
2390         if (dl->flag & DL_CYCL_U) {
2391                 
2392                 for (u = 0; u < sizeu; u++) {
2393                         /* optimize! :*/
2394                         vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0));
2395                         vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1));
2396                         add_v3_v3(vlr1->v2->n, vlr->n);
2397                         add_v3_v3(vlr1->v3->n, vlr->n);
2398                         add_v3_v3(vlr->v1->n, vlr1->n);
2399                         add_v3_v3(vlr->v4->n, vlr1->n);
2400                 }
2401         }
2402
2403         /* last vertex is an extra case: 
2404          *
2405          *     ^     ()----()----()----()
2406          *     |     |     |     ||     |
2407          *     u     |     |(0,n)||(0,0)|
2408          *     |     |     ||     |
2409          *     ()====()====[]====()
2410          *     |     |     ||     |
2411          *     |     |(m,n)||(m,0)|
2412          *     |     |     ||     |
2413          *     ()----()----()----()
2414          *     v ->
2415          *  
2416          *  vertex [] is no longer shared, therefore distribute
2417          *  normals of the surrounding faces to all of the duplicates of []
2418          */
2419
2420         if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)) {
2421                 vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m, n) */
2422                 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, 0));  /* (0, 0) */
2423                 add_v3_v3v3(n1, vlr->n, vlr1->n);
2424                 vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0, n) */
2425                 add_v3_v3(n1, vlr2->n);
2426                 vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m, 0) */
2427                 add_v3_v3(n1, vlr3->n);
2428                 copy_v3_v3(vlr->v3->n, n1);
2429                 copy_v3_v3(vlr1->v1->n, n1);
2430                 copy_v3_v3(vlr2->v2->n, n1);
2431                 copy_v3_v3(vlr3->v4->n, n1);
2432         }
2433         for (a = startvert; a < obr->totvert; a++) {
2434                 ver= RE_findOrAddVert(obr, a);
2435                 normalize_v3(ver->n);
2436         }
2437         
2438         
2439         return orcoret;
2440 }
2441
2442 static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
2443         int timeoffset, float *orco, float mat[4][4])
2444 {
2445         Object *ob= obr->ob;
2446         int a, end, totvert, vertofs;
2447         short mat_iter;
2448         VertRen *ver;
2449         VlakRen *vlr;
2450         MVert *mvert = NULL;
2451         MFace *mface;
2452         Material *ma;
2453 #ifdef WITH_FREESTYLE
2454         const int *index_mf_to_mpoly = NULL;
2455         const int *index_mp_to_orig = NULL;
2456         FreestyleFace *ffa = NULL;
2457 #endif
2458         /* Curve *cu= ELEM(ob->type, OB_FONT, OB_CURVE) ? ob->data : NULL; */
2459
2460         mvert= dm->getVertArray(dm);
2461         totvert= dm->getNumVerts(dm);
2462
2463         for (a=0; a<totvert; a++, mvert++) {
2464                 ver= RE_findOrAddVert(obr, obr->totvert++);
2465                 copy_v3_v3(ver->co, mvert->co);
2466                 mul_m4_v3(mat, ver->co);
2467
2468                 if (orco) {
2469                         ver->orco= orco;
2470                         orco+=3;
2471                 }
2472         }
2473
2474         if (!timeoffset) {
2475                 /* store customdata names, because DerivedMesh is freed */
2476                 RE_set_customdata_names(obr, &dm->faceData);
2477
2478                 /* still to do for keys: the correct local texture coordinate */
2479
2480                 /* faces in order of color blocks */
2481                 vertofs= obr->totvert - totvert;
2482                 for (mat_iter= 0; (mat_iter < ob->totcol || (mat_iter==0 && ob->totcol==0)); mat_iter++) {
2483
2484                         ma= give_render_material(re, ob, mat_iter+1);
2485                         end= dm->getNumTessFaces(dm);
2486                         mface= dm->getTessFaceArray(dm);
2487
2488 #ifdef WITH_FREESTYLE
2489                         if (ob->type == OB_MESH) {
2490                                 Mesh *me= ob->data;
2491                                 index_mf_to_mpoly= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
2492                                 index_mp_to_orig= dm->getPolyDataArray(dm, CD_ORIGINDEX);
2493                                 ffa= CustomData_get_layer(&me->pdata, CD_FREESTYLE_FACE);
2494                         }
2495 #endif
2496
2497                         for (a=0; a<end; a++, mface++) {
2498                                 int v1, v2, v3, v4, flag;
2499
2500                                 if (mface->mat_nr == mat_iter) {
2501                                         float len;
2502
2503                                         v1= mface->v1;
2504                                         v2= mface->v2;
2505                                         v3= mface->v3;
2506                                         v4= mface->v4;
2507                                         flag= mface->flag & ME_SMOOTH;
2508
2509                                         vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2510                                         vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
2511                                         vlr->v2= RE_findOrAddVert(obr, vertofs+v2);
2512                                         vlr->v3= RE_findOrAddVert(obr, vertofs+v3);
2513                                         if (v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4);
2514                                         else vlr->v4 = NULL;
2515
2516                                         /* render normals are inverted in render */
2517                                         if (vlr->v4)
2518                                                 len= normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2519                                         else
2520                                                 len= normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2521
2522                                         vlr->mat= ma;
2523                                         vlr->flag= flag;
2524                                         vlr->ec= 0; /* mesh edges rendered separately */
2525 #ifdef WITH_FREESTYLE
2526                                         if (ffa) {
2527                                                 int index = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
2528                                                 vlr->freestyle_face_mark= (ffa[index].flag & FREESTYLE_FACE_MARK) ? 1 : 0;
2529                                         }
2530                                         else {
2531                                                 vlr->freestyle_face_mark= 0;
2532                                         }
2533 #endif
2534
2535                                         if (len==0) obr->totvlak--;
2536                                         else {
2537                                                 CustomDataLayer *layer;
2538                                                 MTFace *mtface, *mtf;
2539                                                 MCol *mcol, *mc;
2540                                                 int index, mtfn= 0, mcn= 0;
2541                                                 char *name;
2542
2543                                                 for (index=0; index<dm->faceData.totlayer; index++) {
2544                                                         layer= &dm->faceData.layers[index];
2545                                                         name= layer->name;
2546
2547                                                         if (layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
2548                                                                 mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1);
2549                                                                 mtface= (MTFace*)layer->data;
2550                                                                 *mtf= mtface[a];
2551                                                         }
2552                                                         else if (layer->type == CD_MCOL && mcn < MAX_MCOL) {
2553                                                                 mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1);
2554                                                                 mcol= (MCol*)layer->data;
2555                                                                 memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
2556                                                         }
2557                                                 }
2558                                         }
2559                                 }
2560                         }
2561                 }
2562
2563                 /* Normals */
2564                 calc_vertexnormals(re, obr, 1, 0, 0);
2565         }
2566
2567 }
2568
2569 static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset)
2570 {
2571         Object *ob= obr->ob;
2572         Nurb *nu = NULL;
2573         Curve *cu;
2574         ListBase displist= {NULL, NULL};
2575         DispList *dl;
2576         Material **matar;
2577         float *orco=NULL, mat[4][4];
2578         int a, totmat;
2579         bool need_orco = false;
2580         DerivedMesh *dm= NULL;
2581
2582         cu= ob->data;
2583         nu= cu->nurb.first;
2584         if (nu == NULL) return;
2585
2586         mul_m4_m4m4(mat, re->viewmat, ob->obmat);
2587         invert_m4_m4(ob->imat, mat);
2588
2589         /* material array */
2590         totmat= ob->totcol+1;
2591         matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar");
2592
2593         for (a=0; a<totmat; a++) {
2594                 matar[a]= give_render_material(re, ob, a+1);
2595
2596                 if (matar[a] && matar[a]->texco & TEXCO_ORCO)
2597                         need_orco= 1;
2598         }
2599
2600         if (ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
2601
2602         BKE_displist_make_surf(re->scene, ob, &displist, &dm, 1, 0, 1);
2603
2604         if (dm) {
2605                 if (need_orco) {
2606                         orco = get_object_orco(re, ob);
2607                         if (!orco) {
2608                                 orco= BKE_displist_make_orco(re->scene, ob, dm, true, true);
2609                                 if (orco) {
2610                                         set_object_orco(re, ob, orco);
2611                                 }
2612                         }
2613                 }
2614
2615                 init_render_dm(dm, re, obr, timeoffset, orco, mat);
2616                 dm->release(dm);
2617         }
2618         else {
2619                 if (need_orco) {
2620                         orco = get_object_orco(re, ob);
2621                         if (!orco) {
2622                                 orco = BKE_curve_surf_make_orco(ob);
2623                                 set_object_orco(re, ob, orco);
2624                         }
2625                 }
2626
2627                 /* walk along displaylist and create rendervertices/-faces */
2628                 for (dl=displist.first; dl; dl=dl->next) {
2629                         /* watch out: u ^= y, v ^= x !! */
2630                         if (dl->type==DL_SURF)
2631                                 orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
2632                 }
2633         }
2634
2635         BKE_displist_free(&displist);
2636
2637         MEM_freeN(matar);
2638 }
2639
2640 static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
2641 {
2642         Object *ob= obr->ob;
2643         Curve *cu;
2644         VertRen *ver;
2645         VlakRen *vlr;
2646         DispList *dl;
2647         DerivedMesh *dm = NULL;
2648         ListBase disp={NULL, NULL};
2649         Material **matar;
2650         float *data, *fp, *orco=NULL;
2651         float n[3], mat[4][4], nmat[4][4];
2652         int nr, startvert, a, b, negative_scale;
2653         bool need_orco = false;
2654         int totmat;
2655
2656         cu= ob->data;
2657         if (ob->type==OB_FONT && cu->str==NULL) return;
2658         else if (ob->type==OB_CURVE && cu->nurb.first==NULL) return;
2659
2660         BKE_displist_make_curveTypes_forRender(re->scene, ob, &disp, &dm, false, true);
2661         dl= disp.first;
2662         if (dl==NULL) return;
2663         
2664         mul_m4_m4m4(mat, re->viewmat, ob->obmat);
2665         invert_m4_m4(ob->imat, mat);
2666         negative_scale = is_negative_m4(mat);
2667
2668         /* local object -> world space transform for normals */
2669         transpose_m4_m4(nmat, mat);
2670         invert_m4(nmat);
2671
2672         /* material array */
2673         totmat= ob->totcol+1;
2674         matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar");
2675
2676         for (a=0; a<totmat; a++) {
2677                 matar[a]= give_render_material(re, ob, a+1);
2678
2679                 if (matar[a] && matar[a]->texco & TEXCO_ORCO)
2680                         need_orco= 1;
2681         }
2682
2683         if (dm) {
2684                 if (need_orco) {
2685                         orco = get_object_orco(re, ob);
2686                         if (!orco) {
2687                                 orco = BKE_displist_make_orco(re->scene, ob, dm, true, true);
2688                                 if (orco) {
2689                                         set_object_orco(re, ob, orco);
2690                                 }
2691                         }
2692                 }
2693
2694                 init_render_dm(dm, re, obr, timeoffset, orco, mat);
2695                 dm->release(dm);
2696         }
2697         else {
2698                 if (need_orco) {
2699                         orco = get_object_orco(re, ob);
2700                         if (!orco) {
2701                                 orco = BKE_curve_make_orco(re->scene, ob, NULL);
2702                                 set_object_orco(re, ob, orco);
2703                         }
2704                 }
2705
2706                 while (dl) {
2707                         if (dl->col > ob->totcol) {
2708                                 /* pass */
2709                         }
2710                         else if (dl->type==DL_INDEX3) {
2711                                 const int *index;
2712
2713                                 startvert= obr->totvert;
2714                                 data= dl->verts;
2715
2716                                 for (a=0; a<dl->nr; a++, data+=3) {
2717                                         ver= RE_findOrAddVert(obr, obr->totvert++);
2718                                         copy_v3_v3(ver->co, data);
2719
2720                                         mul_m4_v3(mat, ver->co);
2721
2722                                         if (orco) {
2723                                                 ver->orco = orco;
2724                                                 orco += 3;
2725                                         }
2726                                 }
2727
2728                                 if (timeoffset==0) {
2729                                         float tmp[3];
2730                                         const int startvlak= obr->totvlak;
2731
2732                                         zero_v3(n);
2733                                         index= dl->index;
2734                                         for (a=0; a<dl->parts; a++, index+=3) {
2735                                                 int v1 = index[0], v2 = index[2], v3 = index[1];
2736                                                 float *co1 = &dl->verts[v1 * 3],
2737                                                       *co2 = &dl->verts[v2 * 3],
2738                                                       *co3 = &dl->verts[v3 * 3];
2739
2740                                                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2741                                                 vlr->v1= RE_findOrAddVert(obr, startvert + v1);
2742                                                 vlr->v2= RE_findOrAddVert(obr, startvert + v2);
2743                                                 vlr->v3= RE_findOrAddVert(obr, startvert + v3);
2744                                                 vlr->v4= NULL;
2745
2746                                                 /* to prevent float accuracy issues, we calculate normal in local object space (not world) */
2747                                                 if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) {
2748                                                         if (negative_scale == false) {
2749                                                                 add_v3_v3(n, tmp);
2750                                                         }
2751                                                         else {
2752                                                                 sub_v3_v3(n, tmp);
2753                                                         }
2754                                                 }
2755
2756                                                 vlr->mat= matar[ dl->col ];
2757                                                 vlr->flag= 0;
2758                                                 vlr->ec= 0;
2759                                         }
2760
2761                                         /* transform normal to world space */
2762                                         mul_m4_v3(nmat, n);
2763                                         normalize_v3(n);
2764
2765                                         /* vertex normals */
2766                                         for (a= startvlak; a<obr->totvlak; a++) {
2767                                                 vlr= RE_findOrAddVlak(obr, a);
2768
2769                                                 copy_v3_v3(vlr->n, n);
2770                                                 add_v3_v3(vlr->v1->n, vlr->n);
2771                                                 add_v3_v3(vlr->v3->n, vlr->n);
2772                                                 add_v3_v3(vlr->v2->n, vlr->n);
2773                                         }
2774                                         for (a=startvert; a<obr->totvert; a++) {
2775                                                 ver= RE_findOrAddVert(obr, a);
2776                                                 normalize_v3(ver->n);
2777                                         }
2778                                 }
2779                         }
2780                         else if (dl->type==DL_SURF) {
2781
2782                                 /* cyclic U means an extruded full circular curve, we skip bevel splitting then */
2783                                 if (dl->flag & DL_CYCL_U) {
2784                                         orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
2785                                 }
2786                                 else {
2787                                         int p1, p2, p3, p4;
2788
2789                                         fp= dl->verts;
2790                                         startvert= obr->totvert;
2791                                         nr= dl->nr*dl->parts;
2792
2793                                         while (nr--) {
2794                                                 ver= RE_findOrAddVert(obr, obr->totvert++);
2795
2796                                                 copy_v3_v3(ver->co, fp);
2797                                                 mul_m4_v3(mat, ver->co);
2798                                                 fp+= 3;
2799
2800                                                 if (orco) {
2801                                                         ver->orco = orco;
2802                                                         orco += 3;
2803                                                 }
2804                                         }
2805
2806                                         if (dl->flag & DL_CYCL_V && orco) {
2807                                                 fp = dl->verts;
2808                                                 nr = dl->nr;
2809                                                 while (nr--) {
2810                                                         ver = RE_findOrAddVert(obr, obr->totvert++);
2811                                                         copy_v3_v3(ver->co, fp);
2812                                                         mul_m4_v3(mat, ver->co);
2813                                                         ver->orco = orco;
2814                                                         fp += 3;
2815                                                         orco += 3;
2816                                                 }
2817                                         }
2818
2819                                         if (dl->bevelSplitFlag || timeoffset==0) {
2820                                                 const int startvlak= obr->totvlak;
2821
2822                                                 for (a=0; a<dl->parts; a++) {
2823
2824                                                         if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4)==0)
2825                                                                 break;
2826
2827                                                         p1+= startvert;
2828                                                         p2+= startvert;
2829                                                         p3+= startvert;
2830                                                         p4+= startvert;
2831
2832                                                         if (dl->flag & DL_CYCL_V && orco && a == dl->parts - 1) {
2833                                                                 p3 = p1 + dl->nr;
2834                                                                 p4 = p2 + dl->nr;
2835                                                         }
2836
2837                                                         for (; b<dl->nr; b++) {
2838                                                                 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2839                                                                 /* important 1 offset in order is kept [#24913] */
2840                                                                 vlr->v1= RE_findOrAddVert(obr, p2);
2841                                                                 vlr->v2= RE_findOrAddVert(obr, p1);
2842                                                                 vlr->v3= RE_findOrAddVert(obr, p3);
2843                                                                 vlr->v4= RE_findOrAddVert(obr, p4);
2844                                                                 vlr->ec= ME_V2V3+ME_V3V4;
2845                                                                 if (a==0) vlr->ec+= ME_V1V2;
2846
2847                                                                 vlr->flag= dl->rt;
2848
2849                                                                 normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
2850                                                                 vlr->mat= matar[ dl->col ];
2851
2852                                                                 p4= p3;
2853                                                                 p3++;
2854                                                                 p2= p1;
2855                                                                 p1++;
2856                                                         }
2857                                                 }
2858
2859                                                 if (dl->bevelSplitFlag) {
2860                                                         for (a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
2861                                                                 if (dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
2862                                                                         split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
2863                                                 }
2864
2865                                                 /* vertex normals */
2866                                                 for (a= startvlak; a<obr->totvlak; a++) {
2867                                                         vlr= RE_findOrAddVlak(obr, a);
2868
2869                                                         add_v3_v3(vlr->v1->n, vlr->n);
2870                                                         add_v3_v3(vlr->v3->n, vlr->n);
2871                                                         add_v3_v3(vlr->v2->n, vlr->n);
2872                                                         add_v3_v3(vlr->v4->n, vlr->n);
2873                                                 }
2874                                                 for (a=startvert; a<obr->totvert; a++) {
2875                                                         ver= RE_findOrAddVert(obr, a);
2876                                                         normalize_v3(ver->n);
2877                                                 }
2878                                         }
2879                                 }
2880                         }
2881
2882                         dl= dl->next;
2883                 }
2884         }
2885
2886         BKE_displist_free(&disp);