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