4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributors: 2004/2005/2006 Blender Foundation, full recode
25 * ***** END GPL LICENSE BLOCK *****
34 #include "MTC_matrixops.h"
36 #include "MEM_guardedalloc.h"
38 #include "BLI_arithb.h"
39 #include "BLI_blenlib.h"
41 #include "BLI_memarena.h"
42 #include "BLI_ghash.h"
44 #include "DNA_armature_types.h"
45 #include "DNA_camera_types.h"
46 #include "DNA_material_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_effect_types.h"
49 #include "DNA_group_types.h"
50 #include "DNA_lamp_types.h"
51 #include "DNA_image_types.h"
52 #include "DNA_lattice_types.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_meta_types.h"
56 #include "DNA_modifier_types.h"
57 #include "DNA_node_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_object_force.h"
60 #include "DNA_object_fluidsim.h"
61 #include "DNA_particle_types.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_texture_types.h"
64 #include "DNA_view3d_types.h"
67 #include "BKE_armature.h"
68 #include "BKE_action.h"
69 #include "BKE_curve.h"
70 #include "BKE_customdata.h"
71 #include "BKE_colortools.h"
72 #include "BKE_constraint.h"
73 #include "BKE_displist.h"
74 #include "BKE_deform.h"
75 #include "BKE_DerivedMesh.h"
76 #include "BKE_effect.h"
77 #include "BKE_global.h"
78 #include "BKE_group.h"
81 #include "BKE_image.h"
82 #include "BKE_lattice.h"
83 #include "BKE_library.h"
84 #include "BKE_material.h"
86 #include "BKE_mball.h"
88 #include "BKE_modifier.h"
90 #include "BKE_object.h"
91 #include "BKE_particle.h"
92 #include "BKE_scene.h"
93 #include "BKE_subsurf.h"
94 #include "BKE_texture.h"
95 #include "BKE_utildefines.h"
96 #include "BKE_world.h"
99 #include "IMB_imbuf_types.h"
102 #include "occlusion.h"
103 #include "render_types.h"
104 #include "rendercore.h"
105 #include "renderdatabase.h"
106 #include "renderpipeline.h"
118 /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
119 /* or for checking vertex normal flips */
120 #define FLT_EPSILON10 1.19209290e-06F
122 /* ------------------------------------------------------------------------- */
124 /* Stuff for stars. This sits here because it uses gl-things. Part of
125 this code may move down to the converter. */
126 /* ------------------------------------------------------------------------- */
127 /* this is a bad beast, since it is misused by the 3d view drawing as well. */
129 static HaloRen *initstar(Render *re, ObjectRen *obr, float *vec, float hasize)
134 projectverto(vec, re->winmat, hoco);
136 har= RE_findOrAddHalo(obr, obr->tothalo++);
138 /* projectvert is done in function zbufvlaggen again, because of parts */
139 VECCOPY(har->co, vec);
147 /* there must be a 'fixed' amount of stars generated between
149 * all stars must by preference lie on the far and solely
150 * differ in clarity/color
153 void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void),
154 void (*vertexfunc)(float*), void (*termfunc)(void))
156 extern unsigned char hash[512];
157 ObjectRen *obr= NULL;
162 double dblrand, hlfrand;
163 float vec[4], fx, fy, fz;
164 float fac, starmindist, clipend;
165 float mat[4][4], stargrid, maxrand, maxjit, force, alpha;
166 int x, y, z, sx, sy, sz, ex, ey, ez, done = 0;
177 stargrid = wrld->stardist; /* distance between stars */
178 maxrand = 2.0; /* amount a star can be shifted (in grid units) */
179 maxjit = (wrld->starcolnoise); /* amount a color is being shifted */
182 force = ( wrld->starsize );
184 /* minimal free space (starting at camera) */
185 starmindist= wrld->starmindist;
187 if (stargrid <= 0.10) return;
189 if (re) re->flag |= R_HALO;
190 else stargrid *= 1.0; /* then it draws fewer */
192 if(re) MTC_Mat4Invert(mat, re->viewmat);
193 else MTC_Mat4One(mat);
195 /* BOUNDING BOX CALCULATION
196 * bbox goes from z = loc_near_var | loc_far_var,
201 if(scene->camera==NULL)
203 camera = scene->camera->data;
204 clipend = camera->clipend;
206 /* convert to grid coordinates */
208 sx = ((mat[3][0] - clipend) / stargrid) - maxrand;
209 sy = ((mat[3][1] - clipend) / stargrid) - maxrand;
210 sz = ((mat[3][2] - clipend) / stargrid) - maxrand;
212 ex = ((mat[3][0] + clipend) / stargrid) + maxrand;
213 ey = ((mat[3][1] + clipend) / stargrid) + maxrand;
214 ez = ((mat[3][2] + clipend) / stargrid) + maxrand;
216 dblrand = maxrand * stargrid;
217 hlfrand = 2.0 * dblrand;
223 if(re) /* add render object for stars */
224 obr= RE_addRenderObject(re, NULL, NULL, 0, 0, 0);
226 for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) {
227 for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) {
228 for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) {
230 BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8));
231 vec[0] = fx + (hlfrand * BLI_drand()) - dblrand;
232 vec[1] = fy + (hlfrand * BLI_drand()) - dblrand;
233 vec[2] = fz + (hlfrand * BLI_drand()) - dblrand;
237 if(done & 1) vertexfunc(vec);
241 MTC_Mat4MulVecfl(re->viewmat, vec);
243 /* in vec are global coordinates
244 * calculate distance to camera
245 * and using that, define the alpha
255 alpha = sqrt(tx * tx + ty * ty + tz * tz);
257 if (alpha >= clipend) alpha = 0.0;
258 else if (alpha <= starmindist) alpha = 0.0;
259 else if (alpha <= 2.0 * starmindist) {
260 alpha = (alpha - starmindist) / starmindist;
262 alpha -= 2.0 * starmindist;
263 alpha /= (clipend - 2.0 * starmindist);
270 fac = force * BLI_drand();
272 har = initstar(re, obr, vec, fac);
275 har->alfa = sqrt(sqrt(alpha));
277 har->r = har->g = har->b = 1.0;
279 har->r += ((maxjit * BLI_drand()) ) - maxjit;
280 har->g += ((maxjit * BLI_drand()) ) - maxjit;
281 har->b += ((maxjit * BLI_drand()) ) - maxjit;
285 har->type |= HA_ONLYSKY;
291 /* do not call blender_test_break() here, since it is used in UI as well, confusing the callback system */
292 /* main cause is G.afbreek of course, a global again... (ton) */
295 if (termfunc) termfunc();
298 re->tothalo += obr->tothalo;
302 /* ------------------------------------------------------------------------- */
303 /* tool functions/defines for ad hoc simplification and possible future
305 /* ------------------------------------------------------------------------- */
307 #define UVTOINDEX(u,v) (startvlak + (u) * sizev + (v))
310 NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !!
312 ^ ()----p4----p3----()
320 /* ------------------------------------------------------------------------- */
322 static void split_v_renderfaces(ObjectRen *obr, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv)
324 int vLen = vsize-1+(!!cyclv);
327 for (v=0; v<vLen; v++) {
328 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v);
329 VertRen *vert = RE_vertren_copy(obr, vlr->v2);
335 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0);
338 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
345 VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
350 vlr->v1 = RE_vertren_copy(obr, vlr->v1);
356 /* ------------------------------------------------------------------------- */
358 static int check_vnormal(float *n, float *veno)
362 inp=n[0]*veno[0]+n[1]*veno[1]+n[2]*veno[2];
363 if(inp < -FLT_EPSILON10) return 1;
367 /* ------------------------------------------------------------------------- */
368 /* Stress, tangents and normals */
369 /* ------------------------------------------------------------------------- */
371 static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2)
373 float len= VecLenf(v1->co, v2->co)/VecLenf(v1->orco, v2->orco);
376 acc= accum + 2*v1->index;
380 acc= accum + 2*v2->index;
385 static void calc_edge_stress(Render *re, ObjectRen *obr, Mesh *me)
387 float loc[3], size[3], *accum, *acc, *accumoffs, *stress;
390 if(obr->totvert==0) return;
392 mesh_get_texspace(me, loc, NULL, size);
394 accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress");
396 /* de-normalize orco */
397 for(a=0; a<obr->totvert; a++) {
398 VertRen *ver= RE_findOrAddVert(obr, a);
400 ver->orco[0]= ver->orco[0]*size[0] +loc[0];
401 ver->orco[1]= ver->orco[1]*size[1] +loc[1];
402 ver->orco[2]= ver->orco[2]*size[2] +loc[2];
406 /* add stress values */
407 accumoffs= accum; /* so we can use vertex index */
408 for(a=0; a<obr->totvlak; a++) {
409 VlakRen *vlr= RE_findOrAddVlak(obr, a);
411 if(vlr->v1->orco && vlr->v4) {
412 calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2);
413 calc_edge_stress_add(accumoffs, vlr->v2, vlr->v3);
414 calc_edge_stress_add(accumoffs, vlr->v3, vlr->v1);
416 calc_edge_stress_add(accumoffs, vlr->v3, vlr->v4);
417 calc_edge_stress_add(accumoffs, vlr->v4, vlr->v1);
418 calc_edge_stress_add(accumoffs, vlr->v2, vlr->v4);
423 for(a=0; a<obr->totvert; a++) {
424 VertRen *ver= RE_findOrAddVert(obr, a);
426 /* find stress value */
427 acc= accumoffs + 2*ver->index;
430 stress= RE_vertren_get_stress(obr, ver, 1);
434 ver->orco[0] = (ver->orco[0]-loc[0])/size[0];
435 ver->orco[1] = (ver->orco[1]-loc[1])/size[1];
436 ver->orco[2] = (ver->orco[2]-loc[2])/size[2];
443 /* gets tangent from tface or orco */
444 static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemArena *arena, VlakRen *vlr, int do_nmap_tangent, int do_tangent)
446 MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
447 VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
449 float *uv1, *uv2, *uv3, *uv4;
459 uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
460 spheremap(v1->orco[0], v1->orco[1], v1->orco[2], &uv[0][0], &uv[0][1]);
461 spheremap(v2->orco[0], v2->orco[1], v2->orco[2], &uv[1][0], &uv[1][1]);
462 spheremap(v3->orco[0], v3->orco[1], v3->orco[2], &uv[2][0], &uv[2][1]);
464 spheremap(v4->orco[0], v4->orco[1], v4->orco[2], &uv[3][0], &uv[3][1]);
468 tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang);
471 tav= RE_vertren_get_tangent(obr, v1, 1);
472 VECADD(tav, tav, tang);
473 tav= RE_vertren_get_tangent(obr, v2, 1);
474 VECADD(tav, tav, tang);
475 tav= RE_vertren_get_tangent(obr, v3, 1);
476 VECADD(tav, tav, tang);
479 if(do_nmap_tangent) {
480 sum_or_add_vertex_tangent(arena, &vtangents[v1->index], tang, uv1);
481 sum_or_add_vertex_tangent(arena, &vtangents[v2->index], tang, uv2);
482 sum_or_add_vertex_tangent(arena, &vtangents[v3->index], tang, uv3);
486 tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang);
489 tav= RE_vertren_get_tangent(obr, v1, 1);
490 VECADD(tav, tav, tang);
491 tav= RE_vertren_get_tangent(obr, v3, 1);
492 VECADD(tav, tav, tang);
493 tav= RE_vertren_get_tangent(obr, v4, 1);
494 VECADD(tav, tav, tang);
497 if(do_nmap_tangent) {
498 sum_or_add_vertex_tangent(arena, &vtangents[v1->index], tang, uv1);
499 sum_or_add_vertex_tangent(arena, &vtangents[v3->index], tang, uv3);
500 sum_or_add_vertex_tangent(arena, &vtangents[v4->index], tang, uv4);
506 static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int do_nmap_tangent)
508 MemArena *arena= NULL;
509 VertexTangent **vtangents= NULL;
512 if(do_nmap_tangent) {
513 arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
514 BLI_memarena_use_calloc(arena);
516 vtangents= MEM_callocN(sizeof(VertexTangent*)*obr->totvert, "VertexTangent");
519 /* clear all vertex normals */
520 for(a=0; a<obr->totvert; a++) {
521 VertRen *ver= RE_findOrAddVert(obr, a);
522 ver->n[0]=ver->n[1]=ver->n[2]= 0.0f;
525 /* calculate cos of angles and point-masses, use as weight factor to
526 add face normal to vertex */
527 for(a=0; a<obr->totvlak; a++) {
528 VlakRen *vlr= RE_findOrAddVlak(obr, a);
529 if(vlr->flag & ME_SMOOTH) {
530 VertRen *v1= vlr->v1;
531 VertRen *v2= vlr->v2;
532 VertRen *v3= vlr->v3;
533 VertRen *v4= vlr->v4;
534 float n1[3], n2[3], n3[3], n4[3];
535 float fac1, fac2, fac3, fac4=0.0f;
537 if(re->flag & R_GLOB_NOPUNOFLIP)
538 vlr->flag |= R_NOPUNOFLIP;
540 VecSubf(n1, v2->co, v1->co);
542 VecSubf(n2, v3->co, v2->co);
545 VecSubf(n3, v1->co, v3->co);
548 fac1= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
549 fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
550 fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
553 VecSubf(n3, v4->co, v3->co);
555 VecSubf(n4, v1->co, v4->co);
558 fac1= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
559 fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
560 fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
561 fac4= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
563 if(!(vlr->flag & R_NOPUNOFLIP)) {
564 if( check_vnormal(vlr->n, v4->n) ) fac4= -fac4;
567 v4->n[0] +=fac4*vlr->n[0];
568 v4->n[1] +=fac4*vlr->n[1];
569 v4->n[2] +=fac4*vlr->n[2];
572 if(!(vlr->flag & R_NOPUNOFLIP)) {
573 if( check_vnormal(vlr->n, v1->n) ) fac1= -fac1;
574 if( check_vnormal(vlr->n, v2->n) ) fac2= -fac2;
575 if( check_vnormal(vlr->n, v3->n) ) fac3= -fac3;
578 v1->n[0] +=fac1*vlr->n[0];
579 v1->n[1] +=fac1*vlr->n[1];
580 v1->n[2] +=fac1*vlr->n[2];
582 v2->n[0] +=fac2*vlr->n[0];
583 v2->n[1] +=fac2*vlr->n[1];
584 v2->n[2] +=fac2*vlr->n[2];
586 v3->n[0] +=fac3*vlr->n[0];
587 v3->n[1] +=fac3*vlr->n[1];
588 v3->n[2] +=fac3*vlr->n[2];
591 if(do_nmap_tangent || do_tangent) {
592 /* tangents still need to be calculated for flat faces too */
593 /* weighting removed, they are not vertexnormals */
594 calc_tangent_vector(obr, vtangents, arena, vlr, do_nmap_tangent, do_tangent);
599 for(a=0; a<obr->totvlak; a++) {
600 VlakRen *vlr= RE_findOrAddVlak(obr, a);
601 if((vlr->flag & ME_SMOOTH)==0) {
602 float *f1= vlr->v1->n;
603 if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
605 if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
607 if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
610 if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
614 if(do_nmap_tangent) {
615 VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
616 MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
619 float *vtang, *ftang= RE_vlakren_get_nmap_tangent(obr, vlr, 1);
621 vtang= find_vertex_tangent(vtangents[v1->index], tface->uv[0]);
622 VECCOPY(ftang, vtang);
624 vtang= find_vertex_tangent(vtangents[v2->index], tface->uv[1]);
625 VECCOPY(ftang+3, vtang);
627 vtang= find_vertex_tangent(vtangents[v3->index], tface->uv[2]);
628 VECCOPY(ftang+6, vtang);
631 vtang= find_vertex_tangent(vtangents[v4->index], tface->uv[3]);
632 VECCOPY(ftang+9, vtang);
639 /* normalize vertex normals */
640 for(a=0; a<obr->totvert; a++) {
641 VertRen *ver= RE_findOrAddVert(obr, a);
644 float *tav= RE_vertren_get_tangent(obr, ver, 0);
647 float tdn = tav[0]*ver->n[0] + tav[1]*ver->n[1] + tav[2]*ver->n[2];
648 tav[0] -= ver->n[0]*tdn;
649 tav[1] -= ver->n[1]*tdn;
650 tav[2] -= ver->n[2]*tdn;
658 BLI_memarena_free(arena);
660 MEM_freeN(vtangents);
663 /* ------------------------------------------------------------------------- */
665 /* ------------------------------------------------------------------------- */
667 typedef struct ASvert {
672 typedef struct ASface {
673 struct ASface *next, *prev;
678 static void as_addvert(ASvert *asv, VertRen *v1, VlakRen *vlr)
683 if(v1 == NULL) return;
685 if(asv->faces.first==NULL) {
686 asf= MEM_callocN(sizeof(ASface), "asface");
687 BLI_addtail(&asv->faces, asf);
690 asf= asv->faces.last;
692 if(asf->vlr[a]==NULL) {
699 /* new face struct */
701 asf= MEM_callocN(sizeof(ASface), "asface");
702 BLI_addtail(&asv->faces, asf);
708 static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh)
710 /* return 1: vertex needs a copy */
717 asf= asv->faces.first;
720 if(asf->vlr[a] && asf->vlr[a]!=vlr) {
721 inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] );
722 if(inp < thresh) return 1;
731 static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh)
733 /* return when new vertex already was made */
738 asf= asv->faces.first;
741 if(asf->vlr[a] && asf->vlr[a]!=vlr) {
742 /* this face already made a copy for this vertex! */
744 inp= fabs( vlr->n[0]*asf->vlr[a]->n[0] + vlr->n[1]*asf->vlr[a]->n[1] + vlr->n[2]*asf->vlr[a]->n[2] );
757 /* note; autosmooth happens in object space still, after applying autosmooth we rotate */
758 /* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */
759 static void autosmooth(Render *re, ObjectRen *obr, float mat[][4], int degr)
761 ASvert *asv, *asverts;
768 if(obr->totvert==0) return;
769 asverts= MEM_callocN(sizeof(ASvert)*obr->totvert, "all smooth verts");
771 thresh= cos( M_PI*(0.5f+(float)degr)/180.0 );
773 /* step zero: give faces normals of original mesh, if this is provided */
776 /* step one: construct listbase of all vertices and pointers to faces */
777 for(a=0; a<obr->totvlak; a++) {
778 vlr= RE_findOrAddVlak(obr, a);
779 /* skip wire faces */
780 if(vlr->v2 != vlr->v3) {
781 as_addvert(asverts+vlr->v1->index, vlr->v1, vlr);
782 as_addvert(asverts+vlr->v2->index, vlr->v2, vlr);
783 as_addvert(asverts+vlr->v3->index, vlr->v3, vlr);
785 as_addvert(asverts+vlr->v4->index, vlr->v4, vlr);
789 totvert= obr->totvert;
790 /* we now test all vertices, when faces have a normal too much different: they get a new vertex */
791 for(a=0, asv=asverts; a<totvert; a++, asv++) {
792 if(asv && asv->totface>1) {
793 ver= RE_findOrAddVert(obr, a);
795 asf= asv->faces.first;
799 /* is there a reason to make a new vertex? */
801 if( as_testvertex(vlr, ver, asv, thresh) ) {
803 /* already made a new vertex within threshold? */
804 v1= as_findvertex(vlr, ver, asv, thresh);
806 /* make a new vertex */
807 v1= RE_vertren_copy(obr, ver);
810 if(vlr->v1==ver) vlr->v1= v1;
811 if(vlr->v2==ver) vlr->v2= v1;
812 if(vlr->v3==ver) vlr->v3= v1;
813 if(vlr->v4==ver) vlr->v4= v1;
822 for(a=0; a<totvert; a++) {
823 BLI_freelistN(&asverts[a].faces);
827 /* rotate vertices and calculate normal of faces */
828 for(a=0; a<obr->totvert; a++) {
829 ver= RE_findOrAddVert(obr, a);
830 MTC_Mat4MulVecfl(mat, ver->co);
832 for(a=0; a<obr->totvlak; a++) {
833 vlr= RE_findOrAddVlak(obr, a);
835 /* skip wire faces */
836 if(vlr->v2 != vlr->v3) {
838 CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
840 CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
845 /* ------------------------------------------------------------------------- */
846 /* Orco hash and Materials */
847 /* ------------------------------------------------------------------------- */
849 static float *get_object_orco(Render *re, Object *ob)
854 re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
856 orco = BLI_ghash_lookup(re->orco_hash, ob);
859 if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
860 orco = make_orco_curve(re->scene, ob);
861 } else if (ob->type==OB_SURF) {
862 orco = make_orco_surf(ob);
863 } else if (ob->type==OB_MBALL) {
864 orco = make_orco_mball(ob);
868 BLI_ghash_insert(re->orco_hash, ob, orco);
874 static void set_object_orco(Render *re, void *ob, float *orco)
877 re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
879 BLI_ghash_insert(re->orco_hash, ob, orco);
882 static void free_mesh_orco_hash(Render *re)
885 BLI_ghash_free(re->orco_hash, NULL, (GHashValFreeFP)MEM_freeN);
886 re->orco_hash = NULL;
890 static void flag_render_node_material(Render *re, bNodeTree *ntree)
894 for(node=ntree->nodes.first; node; node= node->next) {
896 if(GS(node->id->name)==ID_MA) {
897 Material *ma= (Material *)node->id;
899 if(ma->mode & MA_ZTRA)
902 ma->flag |= MA_IS_USED;
904 else if(node->type==NODE_GROUP)
905 flag_render_node_material(re, (bNodeTree *)node->id);
910 static Material *give_render_material(Render *re, Object *ob, int nr)
912 extern Material defmaterial; /* material.c */
915 ma= give_current_material(ob, nr);
919 if(re->r.mode & R_SPEED) ma->texco |= NEED_UV;
921 if(ma->mode & MA_ZTRA)
924 /* for light groups */
925 ma->flag |= MA_IS_USED;
927 if(ma->nodetree && ma->use_nodes)
928 flag_render_node_material(re, ma->nodetree);
933 /* ------------------------------------------------------------------------- */
935 /* ------------------------------------------------------------------------- */
936 typedef struct ParticleStrandData
939 float *orco, *uvco, *surfnor;
940 float time, adapt_angle, adapt_pix, size;
942 int first, line, adapt, override_uv;
945 /* future thread problem... */
946 static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, float *vec, float *vec1)
948 static VertRen *v1= NULL, *v2= NULL;
950 float nor[3], cross[3], crosslen, w, dx, dy, width;
951 static float anor[3], avec[3];
955 VecSubf(nor, vec, vec1);
956 Normalize(nor); // nor needed as tangent
957 Crossf(cross, vec, nor);
959 /* turn cross in pixelsize */
960 w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
961 dx= re->winx*cross[0]*re->winmat[0][0];
962 dy= re->winy*cross[1]*re->winmat[1][1];
963 w= sqrt(dx*dx + dy*dy)/w;
967 if(ma->strand_ease!=0.0f) {
968 if(ma->strand_ease<0.0f)
969 fac= pow(sd->time, 1.0+ma->strand_ease);
971 fac= pow(sd->time, 1.0/(1.0f-ma->strand_ease));
975 width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end);
977 /* use actual Blender units for strand width and fall back to minimum width */
978 if(ma->mode & MA_STR_B_UNITS){
979 crosslen= VecLength(cross);
980 w= 2.0f*crosslen*ma->strand_min/w;
985 /*cross is the radius of the strand so we want it to be half of full width */
986 VecMulf(cross,0.5/crosslen);
991 VecMulf(cross, width);
995 if(ma->mode & MA_TANGENT_STR)
996 flag= R_SMOOTH|R_NOPUNOFLIP|R_TANGENT;
1000 /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */
1001 if(ma->strand_sta==1.0f)
1004 /* single face line */
1006 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1008 vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
1009 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1010 vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
1011 vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
1013 VECCOPY(vlr->v1->co, vec);
1014 VecAddf(vlr->v1->co, vlr->v1->co, cross);
1015 VECCOPY(vlr->v1->n, nor);
1016 vlr->v1->orco= sd->orco;
1017 vlr->v1->accum= -1.0f; // accum abuse for strand texco
1019 VECCOPY(vlr->v2->co, vec);
1020 VecSubf(vlr->v2->co, vlr->v2->co, cross);
1021 VECCOPY(vlr->v2->n, nor);
1022 vlr->v2->orco= sd->orco;
1023 vlr->v2->accum= vlr->v1->accum;
1025 VECCOPY(vlr->v4->co, vec1);
1026 VecAddf(vlr->v4->co, vlr->v4->co, cross);
1027 VECCOPY(vlr->v4->n, nor);
1028 vlr->v4->orco= sd->orco;
1029 vlr->v4->accum= 1.0f; // accum abuse for strand texco
1031 VECCOPY(vlr->v3->co, vec1);
1032 VecSubf(vlr->v3->co, vlr->v3->co, cross);
1033 VECCOPY(vlr->v3->n, nor);
1034 vlr->v3->orco= sd->orco;
1035 vlr->v3->accum= vlr->v4->accum;
1037 CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
1043 float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
1044 VECCOPY(snor, sd->surfnor);
1048 for(i=0; i<sd->totuv; i++){
1050 mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1);
1051 mtf->uv[0][0]=mtf->uv[1][0]=
1052 mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
1053 mtf->uv[0][1]=mtf->uv[1][1]=
1054 mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
1056 if(sd->override_uv>=0){
1058 mtf=RE_vlakren_get_tface(obr,vlr,sd->override_uv,NULL,0);
1060 mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
1061 mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
1063 mtf->uv[0][1]=mtf->uv[1][1]=0.0f;
1064 mtf->uv[2][1]=mtf->uv[3][1]=1.0f;
1068 for(i=0; i<sd->totcol; i++){
1070 mc=RE_vlakren_get_mcol(obr,vlr,i,NULL,1);
1071 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
1072 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
1076 /* first two vertices of a strand */
1077 else if(sd->first) {
1084 v1= RE_findOrAddVert(obr, obr->totvert++);
1085 v2= RE_findOrAddVert(obr, obr->totvert++);
1087 VECCOPY(v1->co, vec);
1088 VecAddf(v1->co, v1->co, cross);
1089 VECCOPY(v1->n, nor);
1091 v1->accum= -1.0f; // accum abuse for strand texco
1093 VECCOPY(v2->co, vec);
1094 VecSubf(v2->co, v2->co, cross);
1095 VECCOPY(v2->n, nor);
1097 v2->accum= v1->accum;
1099 /* more vertices & faces to strand */
1101 if(sd->adapt==0 || second){
1102 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1106 vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
1107 vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
1109 v1= vlr->v4; // cycle
1110 v2= vlr->v3; // cycle
1121 float dvec[3],pvec[3];
1122 VecSubf(dvec,avec,vec);
1123 Projf(pvec,dvec,vec);
1124 VecSubf(dvec,dvec,pvec);
1126 w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
1127 dx= re->winx*dvec[0]*re->winmat[0][0]/w;
1128 dy= re->winy*dvec[1]*re->winmat[1][1]/w;
1129 w= sqrt(dx*dx + dy*dy);
1130 if(Inpf(anor,nor)<sd->adapt_angle && w>sd->adapt_pix){
1131 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1135 vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
1136 vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
1138 v1= vlr->v4; // cycle
1139 v2= vlr->v3; // cycle
1145 vlr= RE_findOrAddVlak(obr, obr->totvlak-1);
1149 VECCOPY(vlr->v4->co, vec);
1150 VecAddf(vlr->v4->co, vlr->v4->co, cross);
1151 VECCOPY(vlr->v4->n, nor);
1152 vlr->v4->orco= sd->orco;
1153 vlr->v4->accum= -1.0f + 2.0f*sd->time; // accum abuse for strand texco
1155 VECCOPY(vlr->v3->co, vec);
1156 VecSubf(vlr->v3->co, vlr->v3->co, cross);
1157 VECCOPY(vlr->v3->n, nor);
1158 vlr->v3->orco= sd->orco;
1159 vlr->v3->accum= vlr->v4->accum;
1161 CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
1167 float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
1168 VECCOPY(snor, sd->surfnor);
1172 for(i=0; i<sd->totuv; i++){
1174 mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1);
1175 mtf->uv[0][0]=mtf->uv[1][0]=
1176 mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
1177 mtf->uv[0][1]=mtf->uv[1][1]=
1178 mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
1180 if(sd->override_uv>=0){
1182 mtf=RE_vlakren_get_tface(obr,vlr,sd->override_uv,NULL,0);
1184 mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
1185 mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
1187 mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f;
1188 mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f;
1192 for(i=0; i<sd->totcol; i++){
1194 mc=RE_vlakren_get_mcol(obr,vlr,i,NULL,1);
1195 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
1196 mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
1202 static void static_particle_wire(ObjectRen *obr, Material *ma, float *vec, float *vec1, int first, int line)
1208 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1209 vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
1210 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1214 VECCOPY(vlr->v1->co, vec);
1215 VECCOPY(vlr->v2->co, vec1);
1217 VecSubf(vlr->n, vec, vec1);
1219 VECCOPY(vlr->v1->n, vlr->n);
1220 VECCOPY(vlr->v2->n, vlr->n);
1227 v1= RE_findOrAddVert(obr, obr->totvert++);
1228 VECCOPY(v1->co, vec);
1231 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1233 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1237 v1= vlr->v2; // cycle
1238 VECCOPY(v1->co, vec);
1240 VecSubf(vlr->n, vec, vec1);
1242 VECCOPY(v1->n, vlr->n);
1250 static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb)
1254 float xvec[3], yvec[3], zvec[3], bb_center[3];
1255 float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f;
1257 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
1258 vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
1259 vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
1260 vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
1261 vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
1263 psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
1265 VECADD(vlr->v1->co, bb_center, xvec);
1266 VECADD(vlr->v1->co, vlr->v1->co, yvec);
1267 MTC_Mat4MulVecfl(re->viewmat, vlr->v1->co);
1269 VECSUB(vlr->v2->co, bb_center, xvec);
1270 VECADD(vlr->v2->co, vlr->v2->co, yvec);
1271 MTC_Mat4MulVecfl(re->viewmat, vlr->v2->co);
1273 VECSUB(vlr->v3->co, bb_center, xvec);
1274 VECSUB(vlr->v3->co, vlr->v3->co, yvec);
1275 MTC_Mat4MulVecfl(re->viewmat, vlr->v3->co);
1277 VECADD(vlr->v4->co, bb_center, xvec);
1278 VECSUB(vlr->v4->co, vlr->v4->co, yvec);
1279 MTC_Mat4MulVecfl(re->viewmat, vlr->v4->co);
1281 CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
1282 VECCOPY(vlr->v1->n,vlr->n);
1283 VECCOPY(vlr->v2->n,vlr->n);
1284 VECCOPY(vlr->v3->n,vlr->n);
1285 VECCOPY(vlr->v4->n,vlr->n);
1290 if(bb->uv_split > 1){
1291 uvdx = uvdy = 1.0f / (float)bb->uv_split;
1292 if(bb->anim == PART_BB_ANIM_TIME) {
1293 if(bb->split_offset == PART_BB_OFF_NONE)
1295 else if(bb->split_offset == PART_BB_OFF_LINEAR)
1296 time = (float)fmod(bb->time + (float)bb->num / (float)(bb->uv_split * bb->uv_split), 1.0f);
1297 else /* split_offset==PART_BB_OFF_RANDOM */
1298 time = (float)fmod(bb->time + bb->random, 1.0f);
1301 else if(bb->anim == PART_BB_ANIM_ANGLE) {
1302 if(bb->align == PART_BB_VIEW) {
1303 time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0);
1306 float axis1[3] = {0.0f,0.0f,0.0f};
1307 float axis2[3] = {0.0f,0.0f,0.0f};
1308 axis1[(bb->align + 1) % 3] = 1.0f;
1309 axis2[(bb->align + 2) % 3] = 1.0f;
1311 zvec[bb->align] = 0.0f;
1314 time = saacos(Inpf(zvec, axis1)) / (float)M_PI;
1315 if(Inpf(zvec, axis2) < 0.0f)
1316 time = 1.0f - time / 2.0f;
1320 if(bb->split_offset == PART_BB_OFF_LINEAR)
1321 time = (float)fmod(bb->time + (float)bb->num / (float)(bb->uv_split * bb->uv_split), 1.0f);
1322 else if(bb->split_offset == PART_BB_OFF_RANDOM)
1323 time = (float)fmod(bb->time + bb->random, 1.0f);
1326 if(bb->split_offset == PART_BB_OFF_NONE)
1328 else if(bb->split_offset == PART_BB_OFF_LINEAR)
1329 time = (float)fmod((float)bb->num /(float)(bb->uv_split * bb->uv_split) , 1.0f);
1330 else /* split_offset==PART_BB_OFF_RANDOM */
1333 uvx = uvdx * floor((float)(bb->uv_split * bb->uv_split) * (float)fmod((double)time, (double)uvdx));
1334 uvy = uvdy * floor((1.0f - time) * (float)bb->uv_split);
1335 if(fmod(time, 1.0f / bb->uv_split) == 0.0f)
1341 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1);
1342 mtf->uv[0][0] = 1.0f;
1343 mtf->uv[0][1] = 1.0f;
1344 mtf->uv[1][0] = 0.0f;
1345 mtf->uv[1][1] = 1.0f;
1346 mtf->uv[2][0] = 0.0f;
1347 mtf->uv[2][1] = 0.0f;
1348 mtf->uv[3][0] = 1.0f;
1349 mtf->uv[3][1] = 0.0f;
1352 /* time-index UVs */
1354 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1);
1355 mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time;
1356 mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum;
1360 if(bb->uv_split > 1 && bb->uv[2] >= 0){
1361 mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1);
1362 mtf->uv[0][0] = uvx + uvdx;
1363 mtf->uv[0][1] = uvy + uvdy;
1364 mtf->uv[1][0] = uvx;
1365 mtf->uv[1][1] = uvy + uvdy;
1366 mtf->uv[2][0] = uvx;
1367 mtf->uv[2][1] = uvy;
1368 mtf->uv[3][0] = uvx + uvdx;
1369 mtf->uv[3][1] = uvy;
1372 static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, float *loc, float *loc1, int seed)
1376 if(ma->mode&MA_WIRE)
1377 static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
1378 else if(ma->material_type == MA_TYPE_HALO) {
1379 har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed);
1380 if(har) har->lay= obr->ob->lay;
1383 static_particle_strand(re, obr, ma, sd, loc, loc1);
1385 static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd)
1390 if(sd->uvco && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
1391 for(i=0; i<sd->totuv; i++) {
1392 if(num != DMCACHE_NOTFOUND) {
1393 MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
1394 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
1397 psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i);
1400 sd->uvco[2*i] = 0.0f;
1401 sd->uvco[2*i + 1] = 0.0f;
1407 if(sd->mcol && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
1408 for(i=0; i<sd->totcol; i++) {
1409 if(num != DMCACHE_NOTFOUND) {
1410 MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
1411 MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
1414 psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i);
1417 memset(&sd->mcol[i], 0, sizeof(MCol));
1421 static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
1423 Object *ob= obr->ob;
1426 ParticleSystemModifierData *psmd;
1427 ParticleSystem *tpsys=0;
1428 ParticleSettings *part, *tpart=0;
1429 ParticleData *pars, *pa=0,*tpa=0;
1430 ParticleKey *states=0;
1432 ParticleCacheKey *cache=0;
1433 ParticleBillboardData bb;
1434 ParticleStrandData sd;
1435 StrandBuffer *strandbuf=0;
1436 StrandVert *svert=0;
1437 StrandBound *sbound= 0;
1438 StrandRen *strand=0;
1440 float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
1441 float strandlen=0.0f, curlen=0.0f;
1442 float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(re->scene, ob, (float)re->scene->r.cfra, 0.0);
1443 float random, simplify[2];
1444 int i, a, k, max_k=0, totpart, dosimplify = 0, dosurfacecache = 0;
1446 int seed, path_nbr=0, orco1=0, num;
1447 int totface, *origindex = 0;
1450 /* 1. check that everything is ok & updated */
1454 totchild=psys->totchild;
1457 pars=psys->particles;
1459 if(part==NULL || pars==NULL || !psys_check_enabled(ob, psys))
1462 if(part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT)
1465 /* 2. start initialising things */
1466 if(part->phystype==PART_PHYS_KEYED){
1467 if(psys->flag & PSYS_FIRST_KEYED)
1468 psys_count_keyed_targets(ob,psys);
1473 /* last possibility to bail out! */
1474 psmd= psys_get_modifier(ob,psys);
1475 if(!(psmd->modifier.mode & eModifierMode_Render))
1478 if(G.rendering == 0) { /* preview render */
1479 totchild = (int)((float)totchild * (float)part->disp / 100.0f);
1482 psys->flag |= PSYS_DRAWING;
1484 rng= rng_new(psys->seed);
1486 totpart=psys->totpart;
1488 memset(&sd, 0, sizeof(ParticleStrandData));
1489 sd.override_uv = -1;
1491 /* 2.1 setup material stff */
1492 ma= give_render_material(re, ob, part->omat);
1494 #if 0 // XXX old animation system
1496 calc_ipo(ma->ipo, cfra);
1497 execute_ipo((ID *)ma, ma->ipo);
1499 #endif // XXX old animation system
1501 hasize = ma->hasize;
1506 RE_set_customdata_names(obr, &psmd->dm->faceData);
1507 sd.totuv = CustomData_number_of_layers(&psmd->dm->faceData, CD_MTFACE);
1508 sd.totcol = CustomData_number_of_layers(&psmd->dm->faceData, CD_MCOL);
1510 if(ma->texco & TEXCO_UV && sd.totuv) {
1511 sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
1513 if(ma->strand_uvname[0]) {
1514 sd.override_uv = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, ma->strand_uvname);
1515 sd.override_uv -= CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
1522 sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols");
1524 /* 2.2 setup billboards */
1525 if(part->ren_as == PART_DRAW_BB) {
1526 int first_uv = CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
1528 bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[0]);
1530 bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm->faceData, CD_MTFACE);
1532 bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[1]);
1534 bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[2]);
1537 bb.uv[0] -= first_uv;
1538 bb.uv[1] -= first_uv;
1539 bb.uv[2] -= first_uv;
1542 bb.align = part->bb_align;
1543 bb.anim = part->bb_anim;
1544 bb.lock = part->draw & PART_DRAW_BB_LOCK;
1545 bb.ob = (part->bb_ob ? part->bb_ob : re->scene->camera);
1546 bb.offset[0] = part->bb_offset[0];
1547 bb.offset[1] = part->bb_offset[1];
1548 bb.split_offset = part->bb_split_offset;
1549 bb.totnum = totpart+totchild;
1550 bb.uv_split = part->bb_uv_split;
1553 #if 0 // XXX old animation system
1554 /* 2.3 setup time */
1555 if(part->flag&PART_ABS_TIME && part->ipo) {
1556 calc_ipo(part->ipo, cfra);
1557 execute_ipo((ID *)part, part->ipo);
1559 #endif // XXX old animation system
1561 if(part->flag & PART_GLOB_TIME)
1562 cfra = bsystem_time(re->scene, 0, (float)re->scene->r.cfra, 0.0);
1564 /* 2.4 setup reactors */
1565 if(part->type == PART_REACTOR){
1566 psys_get_reactor_target(ob, psys, &tob, &tpsys);
1567 if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
1568 psmd = psys_get_modifier(tob,tpsys);
1569 tpart = tpsys->part;
1573 /* 2.5 setup matrices */
1574 MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
1575 MTC_Mat4Invert(ob->imat, mat); /* need to be that way, for imat texture */
1576 Mat3CpyMat4(nmat, ob->imat);
1579 /* 2.6 setup strand rendering */
1580 if(part->ren_as == PART_DRAW_PATH && psys->pathcache){
1581 path_nbr=(int)pow(2.0,(double) part->ren_step);
1584 if((ma->material_type != MA_TYPE_HALO) && (ma->mode & MA_WIRE)==0) {
1585 sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
1586 set_object_orco(re, psys, sd.orco);
1590 if(part->draw & PART_DRAW_REN_ADAPT) {
1592 sd.adapt_pix = (float)part->adapt_pix;
1593 sd.adapt_angle = cos((float)part->adapt_angle * (float)(M_PI / 180.0));
1596 if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) {
1597 strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
1599 strandbuf->lay= ob->lay;
1600 Mat4CpyMat4(strandbuf->winmat, re->winmat);
1601 strandbuf->winx= re->winx;
1602 strandbuf->winy= re->winy;
1603 strandbuf->maxdepth= 2;
1604 strandbuf->adaptcos= cos((float)part->adapt_angle*(float)(M_PI/180.0));
1605 strandbuf->overrideuv= sd.override_uv;
1606 strandbuf->minwidth= ma->strand_min;
1608 if(ma->strand_widthfade == 0.0f)
1609 strandbuf->widthfade= 0.0f;
1610 else if(ma->strand_widthfade >= 1.0f)
1611 strandbuf->widthfade= 2.0f - ma->strand_widthfade;
1613 strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
1615 if(part->flag & PART_HAIR_BSPLINE)
1616 strandbuf->flag |= R_STRAND_BSPLINE;
1617 if(ma->mode & MA_STR_B_UNITS)
1618 strandbuf->flag |= R_STRAND_B_UNITS;
1620 svert= strandbuf->vert;
1622 if(re->r.mode & R_SPEED)
1624 else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
1628 totface= psmd->dm->getNumFaces(psmd->dm);
1629 origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX);
1631 for(a=0; a<totface; a++)
1632 strandbuf->totbound= MAX2(strandbuf->totbound, origindex[a]);
1633 strandbuf->totbound++;
1635 strandbuf->totbound++;
1636 strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
1637 sbound= strandbuf->bound;
1638 sbound->start= sbound->end= 0;
1643 sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco");
1648 psys->lattice = psys_get_lattice(re->scene, ob, psys);
1650 /* 3. start creating renderable things */
1651 for(a=0,pa=pars; a<totpart+totchild; a++, pa++, seed++) {
1652 random = rng_getFloat(rng);
1653 /* setup per particle individual stuff */
1655 if(pa->flag & PARS_UNEXIST) continue;
1657 pa_time=(cfra-pa->time)/pa->lifetime;
1658 if((part->flag&PART_ABS_TIME) == 0){
1659 #if 0 // XXX old animation system
1661 /* correction for lifetime */
1662 calc_ipo(ma->ipo, 100.0f * pa_time);
1663 execute_ipo((ID *)ma, ma->ipo);
1666 /* correction for lifetime */
1667 calc_ipo(part->ipo, 100.0f*pa_time);
1668 execute_ipo((ID *)part, part->ipo);
1670 #endif // XXX old animation system
1673 hasize = ma->hasize;
1676 if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
1677 tpa=tpsys->particles+pa->num;
1678 psys_particle_on_emitter(psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,sd.orco,0);
1681 psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,sd.orco,0);
1683 /* get uvco & mcol */
1684 num= pa->num_dmcache;
1686 if(num == DMCACHE_NOTFOUND)
1687 if(pa->num < psmd->dm->getNumFaces(psmd->dm))
1690 get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
1694 r_tilt = 1.0f + pa->r_ave[0];
1697 cache = psys->pathcache[a];
1698 max_k = (int)cache->steps;
1701 if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
1704 ChildParticle *cpa= psys->child+a-totpart;
1707 cache = psys->childcache[a-totpart];
1709 if(cache->steps < 0)
1712 max_k = (int)cache->steps;
1715 pa_time = psys_get_child_time(psys, cpa, cfra);
1717 if((part->flag & PART_ABS_TIME) == 0) {
1718 #if 0 // XXX old animation system
1720 /* correction for lifetime */
1721 calc_ipo(ma->ipo, 100.0f * pa_time);
1722 execute_ipo((ID *)ma, ma->ipo);
1725 /* correction for lifetime */
1726 calc_ipo(part->ipo, 100.0f * pa_time);
1727 execute_ipo((ID *)part, part->ipo);
1729 #endif // XXX old animation system
1732 pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);
1734 r_tilt = 2.0f * cpa->rand[2];
1739 if(part->childtype == PART_CHILD_FACES) {
1740 psys_particle_on_emitter(psmd,
1741 PART_FROM_FACE, cpa->num,DMCACHE_ISCHILD,
1742 cpa->fuv,cpa->foffset,co,nor,0,0,sd.orco,0);
1745 ParticleData *par = psys->particles + cpa->parent;
1746 psys_particle_on_emitter(psmd, part->from,
1747 par->num,DMCACHE_ISCHILD,par->fuv,
1748 par->foffset,co,nor,0,0,sd.orco,0);
1751 /* get uvco & mcol */
1752 if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
1753 get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
1756 ParticleData *parent = psys->particles + cpa->parent;
1757 num = parent->num_dmcache;
1759 if(num == DMCACHE_NOTFOUND)
1760 if(parent->num < psmd->dm->getNumFaces(psmd->dm))
1763 get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd);
1766 dosimplify = psys_render_simplify_params(psys, cpa, simplify);
1769 if(origindex[cpa->num]+1 > sbound - strandbuf->bound) {
1770 sbound= strandbuf->bound + origindex[cpa->num]+1;
1771 sbound->start= sbound->end= obr->totstrand;
1776 /* surface normal shading setup */
1777 if(ma->mode_l & MA_STR_SURFDIFF) {
1778 Mat3MulVecfl(nmat, nor);
1784 /* strand render setup */
1786 strand= RE_findOrAddStrand(obr, obr->totstrand++);
1787 strand->buffer= strandbuf;
1788 strand->vert= svert;
1789 VECCOPY(strand->orco, sd.orco);
1792 float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
1793 ssimplify[0]= simplify[0];
1794 ssimplify[1]= simplify[1];
1798 float *snor= RE_strandren_get_surfnor(obr, strand, 1);
1799 VECCOPY(snor, sd.surfnor);
1802 if(dosurfacecache && num >= 0) {
1803 int *facenum= RE_strandren_get_face(obr, strand, 1);
1808 for(i=0; i<sd.totuv; i++) {
1809 if(i != sd.override_uv) {
1810 float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
1812 uv[0]= sd.uvco[2*i];
1813 uv[1]= sd.uvco[2*i+1];
1818 for(i=0; i<sd.totcol; i++) {
1819 MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1);
1827 /* strandco computation setup */
1831 for(k=1; k<=path_nbr; k++)
1833 strandlen += VecLenf((cache+k-1)->co, (cache+k)->co);
1837 /* render strands */
1838 for(k=0; k<=path_nbr; k++){
1840 VECCOPY(state.co,(cache+k)->co);
1841 VECCOPY(state.vel,(cache+k)->vel);
1847 curlen += VecLenf((cache+k-1)->co, (cache+k)->co);
1848 time= curlen/strandlen;
1850 VECCOPY(loc,state.co);
1851 MTC_Mat4MulVecfl(re->viewmat,loc);
1854 VECCOPY(svert->co, loc);
1855 svert->strandco= -1.0f + 2.0f*time;
1865 VECSUB(loc0,loc1,loc);
1866 VECADD(loc0,loc1,loc0);
1868 render_new_particle(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed);
1875 render_new_particle(re, obr, psmd->dm, ma, &sd, loc, loc1, seed);
1883 /* render normal particles */
1886 if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0)
1890 Mat4MulVecfl(psys->parent->obmat, state.co);
1892 VECCOPY(loc,state.co);
1893 if(part->ren_as!=PART_DRAW_BB)
1894 MTC_Mat4MulVecfl(re->viewmat,loc);
1896 switch(part->ren_as) {
1897 case PART_DRAW_LINE:
1902 VECCOPY(vel,state.vel);
1903 MTC_Mat4Mul3Vecfl(re->viewmat,vel);
1906 if(part->draw & PART_DRAW_VEL_LENGTH)
1907 VecMulf(vel,VecLength(state.vel));
1909 VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
1910 VECADDFAC(loc1,loc,vel,part->draw_line[1]);
1912 render_new_particle(re,obr,psmd->dm,ma,&sd,loc0,loc1,seed);
1919 bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
1922 VECCOPY(bb.vec, loc);
1923 VECCOPY(bb.vel, state.vel);
1925 particle_billboard(re, obr, ma, &bb);
1933 har = RE_inithalo_particle(re, obr, psmd->dm, ma, loc, NULL, sd.orco, sd.uvco, hasize, 0.0, seed);
1935 if(har) har->lay= obr->ob->lay;
1945 if(re->test_break(re->tbh))
1950 strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
1953 #if 0 // XXX old animation system
1954 if(ma) do_mat_ipo(re->scene, ma);
1955 #endif // XXX old animation system
1974 psys->flag &= ~PSYS_DRAWING;
1977 end_latt_deform(psys->lattice);
1978 psys->lattice= NULL;
1981 if(path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
1982 calc_vertexnormals(re, obr, 0, 0);
1987 /* ------------------------------------------------------------------------- */
1989 /* ------------------------------------------------------------------------- */
1991 static void make_render_halos(Render *re, ObjectRen *obr, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco)
1993 Object *ob= obr->ob;
1995 float xn, yn, zn, nor[3], view[3];
1996 float vec[3], hasize, mat[4][4], imat[3][3];
1997 int a, ok, seed= ma->seed1;
1999 MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
2000 MTC_Mat3CpyMat4(imat, ob->imat);
2004 for(a=0; a<totvert; a++, mvert++) {
2010 VECCOPY(vec, mvert->co);
2011 MTC_Mat4MulVecfl(mat, vec);
2013 if(ma->mode & MA_HALOPUNO) {
2019 nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
2020 nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
2021 nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
2027 zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
2028 if(zn>=0.0) hasize= 0.0;
2029 else hasize*= zn*zn*zn*zn;
2032 if(orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed);
2033 else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed);
2034 if(har) har->lay= ob->lay;
2041 static int verghalo(const void *a1, const void *a2)
2043 const HaloRen *har1= *(const HaloRen**)a1;
2044 const HaloRen *har2= *(const HaloRen**)a2;
2046 if(har1->zs < har2->zs) return 1;
2047 else if(har1->zs > har2->zs) return -1;
2051 static void sort_halos(Render *re, int totsort)
2054 HaloRen *har= NULL, **haso;
2057 if(re->tothalo==0) return;
2059 re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos");
2060 haso= re->sortedhalos;
2062 for(obr=re->objecttable.first; obr; obr=obr->next) {
2063 for(a=0; a<obr->tothalo; a++) {
2064 if((a & 255)==0) har= obr->bloha[a>>8];
2071 qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo);
2074 /* ------------------------------------------------------------------------- */
2075 /* Displacement Mapping */
2076 /* ------------------------------------------------------------------------- */
2078 static short test_for_displace(Render *re, Object *ob)
2080 /* return 1 when this object uses displacement textures. */
2084 for (i=1; i<=ob->totcol; i++) {
2085 ma=give_render_material(re, ob, i);
2086 /* ma->mapto is ORed total of all mapto channels */
2087 if(ma && (ma->mapto & MAP_DISPLACE)) return 1;
2092 static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale, float mat[][4], float imat[][3])
2095 short texco= shi->mat->texco;
2096 float sample=0, displace[3];
2100 /* shi->co is current render coord, just make sure at least some vector is here */
2101 VECCOPY(shi->co, vr->co);
2102 /* vertex normal is used for textures type 'col' and 'var' */
2103 VECCOPY(shi->vn, vr->n);
2106 Mat4MulVecfl(mat, shi->co);
2109 shi->vn[0]= imat[0][0]*vr->n[0]+imat[0][1]*vr->n[1]+imat[0][2]*vr->n[2];
2110 shi->vn[1]= imat[1][0]*vr->n[0]+imat[1][1]*vr->n[1]+imat[1][2]*vr->n[2];
2111 shi->vn[2]= imat[2][0]*vr->n[0]+imat[2][1]*vr->n[1]+imat[2][2]*vr->n[2];
2114 if (texco & TEXCO_UV) {
2116 shi->actuv= obr->actmtface;
2118 for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) {
2119 ShadeInputUV *suv= &shi->uv[i];
2121 /* shi.uv needs scale correction from tface uv */
2122 suv->uv[0]= 2*tface->uv[vindex][0]-1.0f;
2123 suv->uv[1]= 2*tface->uv[vindex][1]-1.0f;
2130 /* set all rendercoords, 'texco' is an ORed value for all textures needed */
2131 if ((texco & TEXCO_ORCO) && (vr->orco)) {
2132 VECCOPY(shi->lo, vr->orco);
2134 if (texco & TEXCO_STICKY) {
2135 float *sticky= RE_vertren_get_sticky(obr, vr, 0);
2137 shi->sticky[0]= sticky[0];
2138 shi->sticky[1]= sticky[1];
2139 shi->sticky[2]= 0.0f;
2142 if (texco & TEXCO_GLOB) {
2143 VECCOPY(shi->gl, shi->co);
2144 MTC_Mat4MulVecfl(re->viewinv, shi->gl);
2146 if (texco & TEXCO_NORM) {
2147 VECCOPY(shi->orn, shi->vn);
2149 if(texco & TEXCO_REFL) {
2153 shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
2155 do_material_tex(shi);
2157 //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2],
2158 //vr->co[0], vr->co[1], vr->co[2]);
2160 displace[0]= shi->displace[0] * scale[0];
2161 displace[1]= shi->displace[1] * scale[1];
2162 displace[2]= shi->displace[2] * scale[2];
2165 Mat3MulVecfl(imat, displace);
2167 /* 0.5 could become button once? */
2168 vr->co[0] += displace[0];
2169 vr->co[1] += displace[1];
2170 vr->co[2] += displace[2];
2172 //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]);
2174 /* we just don't do this vertex again, bad luck for other face using same vertex with
2175 different material... */
2178 /* Pass sample back so displace_face can decide which way to split the quad */
2179 sample = shi->displace[0]*shi->displace[0];
2180 sample += shi->displace[1]*shi->displace[1];
2181 sample += shi->displace[2]*shi->displace[2];
2184 /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */
2188 static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float *scale, float mat[][4], float imat[][3])
2192 /* Warning, This is not that nice, and possibly a bit slow,
2193 however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
2194 memset(&shi, 0, sizeof(ShadeInput));
2195 /* end warning! - Campbell */
2197 /* set up shadeinput struct for multitex() */
2199 /* memset above means we dont need this */
2200 /*shi.osatex= 0;*/ /* signal not to use dx[] and dy[] texture AA vectors */
2202 shi.vlr= vlr; /* current render face */
2203 shi.mat= vlr->mat; /* current input material */
2206 /* Displace the verts, flag is set when done */
2208 displace_render_vert(re, obr, &shi, vlr->v1,0, scale, mat, imat);
2211 displace_render_vert(re, obr, &shi, vlr->v2, 1, scale, mat, imat);
2214 displace_render_vert(re, obr, &shi, vlr->v3, 2, scale, mat, imat);
2218 displace_render_vert(re, obr, &shi, vlr->v4, 3, scale, mat, imat);
2220 /* closest in displace value. This will help smooth edges. */
2221 if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum))
2222 vlr->flag |= R_DIVIDE_24;
2223 else vlr->flag &= ~R_DIVIDE_24;
2226 /* Recalculate the face normal - if flipped before, flip now */
2228 CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
2231 CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
2235 static void do_displacement(Render *re, ObjectRen *obr, float mat[][4], float imat[][3])
2239 // float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30};
2240 float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn
2241 int i; //, texflag=0;
2244 /* Object Size with parenting */
2247 VecAddf(temp, obt->size, obt->dsize);
2248 scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2];
2252 /* Clear all flags */
2253 for(i=0; i<obr->totvert; i++){
2254 vr= RE_findOrAddVert(obr, i);
2258 for(i=0; i<obr->totvlak; i++){
2259 vlr=RE_findOrAddVlak(obr, i);
2260 displace_render_face(re, obr, vlr, scale, mat, imat);
2263 /* Recalc vertex normals */
2264 calc_vertexnormals(re, obr, 0, 0);
2267 /* ------------------------------------------------------------------------- */
2269 /* ------------------------------------------------------------------------- */
2271 static void init_render_mball(Render *re, ObjectRen *obr)
2273 Object *ob= obr->ob;
2276 VlakRen *vlr, *vlr1;
2278 float *data, *nors, *orco, mat[4][4], imat[3][3], xn, yn, zn;
2279 int a, need_orco, vlakindex, *index;
2281 if (ob!=find_basis_mball(re->scene, ob))
2284 MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
2285 MTC_Mat4Invert(ob->imat, mat);
2286 MTC_Mat3CpyMat4(imat, ob->imat);
2288 ma= give_render_material(re, ob, 1);
2291 if(ma->texco & TEXCO_ORCO) {
2295 makeDispListMBall(re->scene, ob);
2301 orco= get_object_orco(re, ob);
2303 for(a=0; a<dl->nr; a++, data+=3, nors+=3, orco+=3) {
2305 ver= RE_findOrAddVert(obr, obr->totvert++);
2306 VECCOPY(ver->co, data);
2307 MTC_Mat4MulVecfl(mat, ver->co);
2309 /* render normals are inverted */
2315 ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
2316 ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
2317 ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
2319 //if(ob->transflag & OB_NEG_SCALE) VecMulf(ver->n. -1.0);
2321 if(need_orco) ver->orco= orco;
2325 for(a=0; a<dl->parts; a++, index+=4) {
2327 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2328 vlr->v1= RE_findOrAddVert(obr, index[0]);
2329 vlr->v2= RE_findOrAddVert(obr, index[1]);
2330 vlr->v3= RE_findOrAddVert(obr, index[2]);
2333 if(ob->transflag & OB_NEG_SCALE)
2334 CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
2336 CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
2339 vlr->flag= ME_SMOOTH+R_NOPUNOFLIP;
2342 /* mball -too bad- always has triangles, because quads can be non-planar */
2343 if(index[3] && index[3]!=index[2]) {
2344 vlr1= RE_findOrAddVlak(obr, obr->totvlak++);
2345 vlakindex= vlr1->index;
2347 vlr1->index= vlakindex;
2349 vlr1->v3= RE_findOrAddVert(obr, index[3]);
2350 if(ob->transflag & OB_NEG_SCALE)
2351 CalcNormFloat(vlr1->v1->co, vlr1->v2->co, vlr1->v3->co, vlr1->n);
2353 CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n);
2357 /* enforce display lists remade */
2358 freedisplist(&ob->disp);
2360 /* this enforces remake for real, orco displist is small (in scale) */
2361 ob->recalc |= OB_RECALC_DATA;
2364 /* ------------------------------------------------------------------------- */
2365 /* Surfaces and Curves */
2366 /* ------------------------------------------------------------------------- */
2368 /* returns amount of vertices added for orco */
2369 static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4])
2371 Object *ob= obr->ob;
2372 VertRen *v1, *v2, *v3, *v4, *ver;
2373 VlakRen *vlr, *vlr1, *vlr2, *vlr3;
2374 Curve *cu= ob->data;
2376 int u, v, orcoret= 0;
2377 int p1, p2, p3, p4, a;
2378 int sizeu, nsizeu, sizev, nsizev;
2379 int startvert, startvlak;
2381 startvert= obr->totvert;
2382 nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr;
2385 for (u = 0; u < sizeu; u++) {
2386 v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */
2387 VECCOPY(v1->co, data); data += 3;
2389 v1->orco= orco; orco+= 3; orcoret++;
2391 MTC_Mat4MulVecfl(mat, v1->co);
2393 for (v = 1; v < sizev; v++) {
2394 ver= RE_findOrAddVert(obr, obr->totvert++);
2395 VECCOPY(ver->co, data); data += 3;
2397 ver->orco= orco; orco+= 3; orcoret++;
2399 MTC_Mat4MulVecfl(mat, ver->co);
2401 /* if V-cyclic, add extra vertices at end of the row */
2402 if (dl->flag & DL_CYCL_U) {
2403 ver= RE_findOrAddVert(obr, obr->totvert++);
2404 VECCOPY(ver->co, v1->co);
2406 ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0);
2411 /* Done before next loop to get corner vert */
2412 if (dl->flag & DL_CYCL_U) nsizev++;
2413 if (dl->flag & DL_CYCL_V) nsizeu++;
2415 /* if U cyclic, add extra row at end of column */
2416 if (dl->flag & DL_CYCL_V) {
2417 for (v = 0; v < nsizev; v++) {
2418 v1= RE_findOrAddVert(obr, startvert + v);
2419 ver= RE_findOrAddVert(obr, obr->totvert++);
2420 VECCOPY(ver->co, v1->co);
2422 ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v);
2430 startvlak= obr->totvlak;
2432 for(u = 0; u < sizeu - 1; u++) {
2433 p1 = startvert + u * sizev; /* walk through face list */
2438 for(v = 0; v < sizev - 1; v++) {
2439 v1= RE_findOrAddVert(obr, p1);
2440 v2= RE_findOrAddVert(obr, p2);
2441 v3= RE_findOrAddVert(obr, p3);
2442 v4= RE_findOrAddVert(obr, p4);
2444 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2445 vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
2447 CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
2449 VECCOPY(vlr->n, n1);
2451 vlr->mat= matar[ dl->col];
2452 vlr->ec= ME_V1V2+ME_V2V3;
2454 if( (cu->flag & CU_NOPUNOFLIP) ) {
2455 vlr->flag |= R_NOPUNOFLIP;
2458 VecAddf(v1->n, v1->n, n1);
2459 VecAddf(v2->n, v2->n, n1);
2460 VecAddf(v3->n, v3->n, n1);
2461 VecAddf(v4->n, v4->n, n1);
2463 p1++; p2++; p3++; p4++;
2466 /* fix normals for U resp. V cyclic faces */
2467 sizeu--; sizev--; /* dec size for face array */
2468 if (dl->flag & DL_CYCL_V) {
2470 for (v = 0; v < sizev; v++)
2473 vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v));
2474 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v));
2475 VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
2476 VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
2477 VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
2478 VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
2481 if (dl->flag & DL_CYCL_U) {
2483 for (u = 0; u < sizeu; u++)
2486 vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0));
2487 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1));
2488 VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
2489 VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
2490 VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
2491 VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
2494 /* last vertex is an extra case:
2496 ^ ()----()----()----()
2500 ()====()====[]====()
2504 ()----()----()----()
2507 vertex [] is no longer shared, therefore distribute
2508 normals of the surrounding faces to all of the duplicates of []
2511 if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U))
2513 vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
2514 vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0,0)); /* (0,0) */
2515 VecAddf(n1, vlr->n, vlr1->n);
2516 vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0,n) */
2517 VecAddf(n1, n1, vlr2->n);
2518 vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m,0) */
2519 VecAddf(n1, n1, vlr3->n);
2520 VECCOPY(vlr->v3->n, n1);
2521 VECCOPY(vlr1->v1->n, n1);
2522 VECCOPY(vlr2->v2->n, n1);
2523 VECCOPY(vlr3->v4->n, n1);
2525 for(a = startvert; a < obr->totvert; a++) {
2526 ver= RE_findOrAddVert(obr, a);
2534 static void init_render_surf(Render *re, ObjectRen *obr)
2536 Object *ob= obr->ob;
2541 Material *matar[32];
2542 float *orco=NULL, *orcobase=NULL, mat[4][4];
2549 MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
2550 MTC_Mat4Invert(ob->imat, mat);
2552 /* material array */
2553 memset(matar, 0, 4*32);
2554 matar[0]= give_render_material(re, ob, 0);
2555 for(a=0; a<ob->totcol; a++) {
2556 matar[a]= give_render_material(re, ob, a+1);
2557 if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
2562 if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
2564 if(need_orco) orcobase= orco= get_object_orco(re, ob);
2566 displist.first= displist.last= 0;
2567 makeDispListSurf(re->scene, ob, &displist, 1, 0);
2570 /* walk along displaylist and create rendervertices/-faces */
2572 /* watch out: u ^= y, v ^= x !! */
2573 if(dl->type==DL_SURF) {
2574 orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
2579 freedisplist(&displist);
2582 static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
2584 Object *ob= obr->ob;
2589 ListBase olddl={NULL, NULL};
2590 Material *matar[32];
2591 float len, *data, *fp, *orco=NULL, *orcobase= NULL;
2592 float n[3], mat[4][4];
2593 int nr, startvert, startvlak, a, b;
2594 int frontside, need_orco=0;
2597 if(ob->type==OB_FONT && cu->str==NULL) return;
2598 else if(ob->type==OB_CURVE && cu->nurb.first==NULL) return;
2600 /* no modifier call here, is in makedisp */
2603 SWAP(ListBase, olddl, cu->disp);
2606 if(cu->disp.first==NULL)
2607 makeDispListCurveTypes(re->scene, ob, 0);
2609 if(cu->disp.first==NULL) return;
2611 MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
2612 MTC_Mat4Invert(ob->imat, mat);
2614 /* material array */
2615 memset(matar, 0, 4*32);
2616 matar[0]= give_render_material(re, ob, 0);
2617 for(a=0; a<ob->totcol; a++) {
2618 matar[a]= give_render_material(re, ob, a+1);
2619 if(matar[a]->texco & TEXCO_ORCO) {
2624 if(need_orco) orcobase=orco= get_object_orco(re, ob);
2628 if(dl->type==DL_INDEX3) {
2631 startvert= obr->totvert;
2634 n[0]= ob->imat[0][2];
2635 n[1]= ob->imat[1][2];
2636 n[2]= ob->imat[2][2];
2639 for(a=0; a<dl->nr; a++, data+=3) {
2640 ver= RE_findOrAddVert(obr, obr->totvert++);
2641 VECCOPY(ver->co, data);
2643 /* flip normal if face is backfacing, also used in face loop below */
2644 if(ver->co[2] < 0.0) {
2649 ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
2653 MTC_Mat4MulVecfl(mat, ver->co);
2662 startvlak= obr->totvlak;
2664 for(a=0; a<dl->parts; a++, index+=3) {
2666 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2667 vlr->v1= RE_findOrAddVert(obr, startvert+index[0]);
2668 vlr->v2= RE_findOrAddVert(obr, startvert+index[1]);
2669 vlr->v3= RE_findOrAddVert(obr, startvert+index[2]);
2676 vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
2679 vlr->mat= matar[ dl->col ];
2681 if( (cu->flag & CU_NOPUNOFLIP) ) {
2682 vlr->flag |= R_NOPUNOFLIP;
2688 else if (dl->type==DL_SURF) {
2690 /* cyclic U means an extruded full circular curve, we skip bevel splitting then */
2691 if (dl->flag & DL_CYCL_U) {
2692 orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
2698 startvert= obr->totvert;
2699 nr= dl->nr*dl->parts;
2702 ver= RE_findOrAddVert(obr, obr->totvert++);
2704 VECCOPY(ver->co, fp);
2705 MTC_Mat4MulVecfl(mat, ver->co);
2714 if(dl->bevelSplitFlag || timeoffset==0) {
2715 startvlak= obr->totvlak;
2717 for(a=0; a<dl->parts; a++) {
2719 frontside= (a >= dl->nr/2);
2721 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
2729 for(; b<dl->nr; b++) {
2730 vlr= RE_findOrAddVlak(obr, obr->totvlak++);
2731 vlr->v1= RE_findOrAddVert(obr, p2);
2732 vlr->v2= RE_findOrAddVert(obr, p1);
2733 vlr->v3= RE_findOrAddVert(obr, p3);
2734 vlr->v4= RE_findOrAddVert(obr, p4);
2735 vlr->ec= ME_V2V3+ME_V3V4;
2736 if(a==0) vlr->ec+= ME_V1V2;
2740 /* this is not really scientific: the vertices
2741 * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
2742 * front and backside treated different!!
2746 CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
2748 CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
2750 vlr->mat= matar[ dl->col ];
2759 if (dl->bevelSplitFlag) {
2760 for(a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
2761 if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
2762 split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
2765 /* vertex normals */
2766 for(a= startvlak; a<obr->totvlak; a++) {
2767 vlr= RE_findOrAddVlak(obr, a);
2769 VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
2770 VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
2771 VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
2772 VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
2774 for(a=startvert; a<obr->totvert; a++) {
2775 ver= RE_findOrAddVert(obr, a);
2776 len= Normalize(ver->n);
2777 if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */
2780 for(a= startvlak; a<obr->totvlak; a++) {
2781 vlr= RE_findOrAddVlak(obr, a);
2782 if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n);
2783 if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n);
2784 if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n);
2785 if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n);
2794 /* not very elegant... but we want original displist in UI */
2795 if(cu->resolu_ren) {
2796 freedisplist(&cu->disp);
2797 SWAP(ListBase, olddl, cu->disp);
2801 /* ------------------------------------------------------------------------- */
2803 /* ------------------------------------------------------------------------- */
2811 /* edges have to be added with lowest index first for sorting */
2812 static void to_edgesort(struct edgesort *ed, int i1, int i2, int v1, int v2, int f)
2826 static int vergedgesort(const void *v1, const void *v2)
2828 const struct edgesort *x1=v1, *x2=v2;
2830 if( x1->v1 > x2->v1) return 1;
2831 else if( x1->v1 < x2->v1) return -1;
2832 else if( x1->v2 > x2->v2) return 1;
2833 else if( x1->v2 < x2->v2) return -1;