diff options
Diffstat (limited to 'source/blender/renderconverter/intern/convertBlenderScene.c')
-rw-r--r-- | source/blender/renderconverter/intern/convertBlenderScene.c | 2943 |
1 files changed, 2943 insertions, 0 deletions
diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c new file mode 100644 index 00000000000..2b08f4d131d --- /dev/null +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -0,0 +1,2943 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * Interface to transform the Blender scene into renderable data. + */ + +/* check for dl->flag, 1 or 2 should be replaced be the def's below */ +#define STRUBI hack +#define DL_CYCLIC_U 1 +#define DL_CYCLIC_V 2 + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <limits.h> /* for INT_MAX */ + +#include "MTC_matrixops.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" + +#include "DNA_scene_types.h" +#include "DNA_lamp_types.h" +#include "DNA_camera_types.h" +#include "DNA_material_types.h" +#include "DNA_curve_types.h" +#include "DNA_texture_types.h" +#include "DNA_lattice_types.h" +#include "DNA_effect_types.h" +#include "DNA_ika_types.h" +#include "DNA_armature_types.h" +#include "DNA_object_types.h" +#include "DNA_view3d_types.h" +#include "DNA_mesh_types.h" + +#include "BKE_mesh.h" +#include "BKE_key.h" +#include "BKE_action.h" +#include "BKE_curve.h" +#include "BKE_armature.h" +#include "BKE_object.h" +#include "BKE_texture.h" +#include "BKE_material.h" +#include "BKE_main.h" +#include "BKE_mball.h" +#include "BKE_anim.h" +#include "BKE_global.h" +#include "BKE_effect.h" +#include "BKE_world.h" +#include "BKE_ipo.h" +#include "BKE_ika.h" +#include "BKE_displist.h" +#include "BKE_lattice.h" +#include "BKE_constraint.h" +#include "BKE_utildefines.h" +#include "BKE_subsurf.h" +#include "BKE_world.h" + +#include "render.h" + +#include "RE_renderconverter.h" +#include "blendertimer.h" /* MISC_test_break */ + +#include "BIF_space.h" +#include "BIF_editkey.h" + +#include "BSE_sequence.h" + +#include "BPY_extern.h" + +#include "nla.h" + +/* ------------------------------------------------------------------------- */ +/* Local functions */ +/* ------------------------------------------------------------------------- */ +static Material *give_render_material(Object *ob, int nr); + + + +/* blenderWorldManipulation.c */ +static void split_u_renderfaces(int startvlak, int startvert, int usize, int plek, int cyclu); +static void split_v_renderfaces(int startvlak, int startvert, int usize, int vsize, int plek, int cyclu, int cyclv); +static int contrpuntnormr(float *n, float *puno); +static void normalenrender(int startvert, int startvlak); +static void as_addvert(VertRen *v1, VlakRen *vlr); +static void as_freevert(VertRen *ver); +static void autosmooth(int startvert, int startvlak, int degr); +static void make_render_halos(Object *ob, Mesh *me, Material *ma, float *extverts); +static int mesh_test_flipnorm(Object *ob, MFace *mface, VlakRen *vlr, float imat[][3]); +static void render_particle_system(Object *ob, PartEff *paf); +static void render_static_particle_system(Object *ob, PartEff *paf); +static void init_render_displist_mesh(Object *ob); +static int verghalo(const void *a1, const void *a2); +static void sort_halos(void); +static void init_render_mball(Object *ob); +static void init_render_mesh(Object *ob); +static void init_render_surf(Object *ob); +static void init_render_curve(Object *ob); +static int test_flipnorm(float *v1, float *v2, float *v3, VlakRen *vlr, float imat[][3]); +static void init_render_object(Object *ob); +static HaloRen *initstar(float *vec, float hasize); + +/* more prototypes for autosmoothing below */ + + +/* ------------------------------------------------------------------------- */ +/* tool functions/defines for ad hoc simplification and possible future + cleanup */ +/* ------------------------------------------------------------------------- */ + +#define UVTOINDEX(u,v) (startvlak + (u) * sizev + (v)) +#define GETNORMAL(face,normal) CalcNormFloat4(face->v1->co, face->v2->co, face->v3->co, face->v4->co, normal) +/* + +NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !! + +^ ()----p4----p3----() +| | | | | +u | | F1 | F2 | + | | | | + ()----p1----p2----() + v -> +*/ + +/* ------------------------------------------------------------------------- */ + +/* Stuff for stars. This sits here because it uses gl-things. Part of + this code may move down to the converter. */ +/* ------------------------------------------------------------------------- */ +/* this is a bad beast, since it is misused by the 3d view drawing as well. */ + +extern unsigned char hash[512]; + +/* - er moet een 'vast' aantal sterren gegenereerd worden tussen near en far. + * - alle sterren moeten bij voorkeur op de far liggen en uitsluitend in + * helderheid / kleur verschillen. + * - + */ + +void RE_make_stars(void (*initfunc)(void), + void (*vertexfunc)(float*), + void (*termfunc)(void)) +{ + HaloRen *har; + double dblrand, hlfrand; + float vec[4], fx, fy, fz; + float fac, starmindist, clipend; + float mat[4][4], stargrid, maxrand, force, alpha; +/* float loc_far_var, loc_near_var; */ + int x, y, z, sx, sy, sz, ex, ey, ez, maxjit, done = 0; + Camera * camera; + + if(initfunc) R.wrld= *(G.scene->world); + + stargrid = R.wrld.stardist; /* om de hoeveel een ster ? */ + maxrand = 2.0; /* hoeveel mag een ster verschuiven (uitgedrukt in grid eenheden) */ + maxjit = (256.0* R.wrld.starcolnoise); /* hoeveel mag een kleur veranderen */ + +/* loc_far_var = R.far; */ +/* loc_near_var = R.near; */ + + + /* afmeting sterren */ + force = ( R.wrld.starsize ); + + /* minimale vrije ruimte */ + starmindist= R.wrld.starmindist; + + if (stargrid <= 0.10) return; + + if (!initfunc) R.flag |= R_HALO; + else stargrid *= 1.0; /* tekent er minder */ + + + MTC_Mat4Invert(mat, R.viewmat); + + /* BOUNDINGBOX BEREKENING + * bbox loopt van z = loc_near_var | loc_far_var, + * x = -z | +z, + * y = -z | +z + */ + + camera = G.scene->camera->data; + clipend = camera->clipend; + + /* omzetten naar grid coordinaten */ + + sx = ((mat[3][0] - clipend) / stargrid) - maxrand; + sy = ((mat[3][1] - clipend) / stargrid) - maxrand; + sz = ((mat[3][2] - clipend) / stargrid) - maxrand; + + ex = ((mat[3][0] + clipend) / stargrid) + maxrand; + ey = ((mat[3][1] + clipend) / stargrid) + maxrand; + ez = ((mat[3][2] + clipend) / stargrid) + maxrand; + + dblrand = maxrand * stargrid; + hlfrand = 2.0 * dblrand; + + if (initfunc) { + initfunc(); + } + + for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) { + for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) { + for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) { + + BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8)); + vec[0] = fx + (hlfrand * BLI_drand()) - dblrand; + vec[1] = fy + (hlfrand * BLI_drand()) - dblrand; + vec[2] = fz + (hlfrand * BLI_drand()) - dblrand; + vec[3] = 1.0; + + if (vertexfunc) { + if(done & 1) vertexfunc(vec); + done++; + } + else { + MTC_Mat4MulVecfl(R.viewmat, vec); + + /* in vec staan globale coordinaten + * bereken afstand tot de kamera + * en bepaal aan de hand daarvan de alpha + */ + + { + float tx, ty, tz; + + tx = vec[0]; + ty = vec[1]; + tz = vec[2]; + + alpha = sqrt(tx * tx + ty * ty + tz * tz); + + if (alpha >= clipend) alpha = 0.0; + else if (alpha <= starmindist) alpha = 0.0; + else if (alpha <= 2.0 * starmindist) { + alpha = (alpha - starmindist) / starmindist; + } else { + alpha -= 2.0 * starmindist; + alpha /= (clipend - 2.0 * starmindist); + alpha = 1.0 - alpha; + } + } + + + if (alpha != 0.0) { + fac = force * BLI_drand(); + + har = initstar(vec, fac); + + if (har) { + har->alfa = sqrt(sqrt(alpha)); + har->add= 255; + har->r = har->g = har->b = 255; + if (maxjit) { + har->r += ((maxjit * BLI_drand()) ) - maxjit; + har->g += ((maxjit * BLI_drand()) ) - maxjit; + har->b += ((maxjit * BLI_drand()) ) - maxjit; + } + har->hard = 32; + + har->type |= HA_ONLYSKY; + done++; + } + } + } + } + if(done > MAXVERT) { + printf("Too many stars\n"); + break; + } + if(MISC_test_break()) break; + } + if(done > MAXVERT) break; + + if(MISC_test_break()) break; + } + if (termfunc) termfunc(); +} + +/* ------------------------------------------------------------------------ */ +/* more star stuff */ +static HaloRen *initstar(float *vec, float hasize) +{ + HaloRen *har; + float hoco[4]; + + RE_projectverto(vec, hoco); + + if( (R.r.mode & R_PANORAMA) || RE_testclip(hoco)==0 ) { + har= RE_findOrAddHalo(R.tothalo++); + + /* projectvert wordt in zbufvlaggen overgedaan ivm parts */ + VECCOPY(har->co, vec); + har->hasize= hasize; + + har->zd= 0.0; + + return har; + } + return NULL; +} + + + +/* ------------------------------------------------------------------------- */ + +static void split_u_renderfaces(int startvlak, int startvert, int usize, int plek, int cyclu) +{ + VlakRen *vlr; + VertRen *v1, *v2; + int a, v; + + if(cyclu) cyclu= 1; + + /* geef eerst alle betreffende vertices een pointer naar de nieuwe mee */ + v= startvert+ plek*usize; + for(a=0; a<usize; a++) { + v2= RE_findOrAddVert(R.totvert++); + v1= RE_findOrAddVert(v++); + *v2= *v1; + v1->sticky= (float *)v2; + } + + /* loop betreffende vlakken af en vervang pointers */ + v= startvlak+plek*(usize-1+cyclu); + for(a=1-cyclu; a<usize; a++) { + vlr= RE_findOrAddVlak(v++); + vlr->v1= (VertRen *)(vlr->v1->sticky); + vlr->v2= (VertRen *)(vlr->v2->sticky); + } + +} + +/* ------------------------------------------------------------------------- */ + +static void split_v_renderfaces(int startvlak, int startvert, int usize, int vsize, int plek, int cyclu, int cyclv) +{ + VlakRen *vlr; + VertRen *v1=0; + int a, vlak, ofs; + + if(vsize<2) return; + + /* loop betreffende vlakken af en maak dubbels */ + /* omdat (evt) split_u al gedaan is kan niet met vertex->sticky pointers worden gewerkt */ + /* want vlakken delen al geen punten meer */ + + if(plek+cyclu==usize) plek= -1; + + vlak= startvlak+(plek+cyclu); + ofs= (usize-1+cyclu); + + for(a=1; a<vsize; a++) { + + vlr= RE_findOrAddVlak(vlak); + if (vlr->v1 == 0) return; /* OEPS, als niet cyclic */ + + v1= RE_findOrAddVert(R.totvert++); + *v1= *(vlr->v1); + + vlr->v1= v1; + + /* vlr= findOrAddVlak(vlak+1); */ + /* vlr->v1= v1; */ + + if(a>1) { + vlr= RE_findOrAddVlak(vlak-ofs); + if(vlr->v4->sticky) { + v1= RE_findOrAddVert(R.totvert++); + *v1= *(vlr->v4); + vlr->v4= v1; + } + else vlr->v4= v1; + } + + if(a== vsize-1) { + if(cyclv) { + ; + } + else { + vlr= RE_findOrAddVlak(vlak); + v1= RE_findOrAddVert(R.totvert++); + *v1= *(vlr->v4); + vlr->v4= v1; + } + } + + vlak+= ofs; + } + +} + +/* ------------------------------------------------------------------------- */ + +static int contrpuntnormr(float *n, float *puno) +{ + float inp; + + inp=n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2]; + if(inp<0.0) return 1; + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void normalenrender(int startvert, int startvlak) +{ + VlakRen *vlr; + VertRen *ver, *adrve1, *adrve2, *adrve3, *adrve4; + float n1[3], n2[3], n3[3], n4[3], *adrco, *tfl, fac, *temp; + int a; + + if(R.totvlak==0 || R.totvert==0) return; + if(startvert==R.totvert || startvlak==R.totvlak) return; + + adrco= (float *)MEM_callocN(12+4*sizeof(float)*(R.totvlak-startvlak), "normalen1"); + + tfl= adrco; + /* berekenen cos hoeken en puntmassa's */ + for(a= startvlak; a<R.totvlak; a++) { + vlr= RE_findOrAddVlak(a); + + adrve1= vlr->v1; + adrve2= vlr->v2; + adrve3= vlr->v3; + adrve4= vlr->v4; + + VecSubf(n1, adrve2->co, adrve1->co); + Normalise(n1); + VecSubf(n2, adrve3->co, adrve2->co); + Normalise(n2); + if(adrve4==0) { + VecSubf(n3, adrve1->co, adrve3->co); + Normalise(n3); + + *(tfl++)= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]); + *(tfl++)= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); + *(tfl++)= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); + } + else { + VecSubf(n3, adrve4->co, adrve3->co); + Normalise(n3); + VecSubf(n4, adrve1->co, adrve4->co); + Normalise(n4); + + *(tfl++)= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]); + *(tfl++)= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); + *(tfl++)= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); + *(tfl++)= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]); + } + } + + /* alle puntnormalen leegmaken */ + for(a=startvert; a<R.totvert; a++) { + ver= RE_findOrAddVert(a); + + ver->n[0]=ver->n[1]=ver->n[2]= 0.0; + } + + /* berekenen normalen en optellen bij puno's */ + tfl= adrco; + for(a=startvlak; a<R.totvlak; a++) { + vlr= RE_findOrAddVlak(a); + + adrve1= vlr->v1; + adrve2= vlr->v2; + adrve3= vlr->v3; + adrve4= vlr->v4; + + temp= adrve1->n; + fac= *(tfl++); + if( vlr->flag & R_NOPUNOFLIP); + else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ; + *(temp++) +=fac*vlr->n[0]; + *(temp++) +=fac*vlr->n[1]; + *(temp) +=fac*vlr->n[2]; + + temp= adrve2->n; + fac= *(tfl++); + if( vlr->flag & R_NOPUNOFLIP); + else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ; + *(temp++) +=fac*vlr->n[0]; + *(temp++) +=fac*vlr->n[1]; + *(temp) +=fac*vlr->n[2]; + + temp= adrve3->n; + fac= *(tfl++); + if( vlr->flag & R_NOPUNOFLIP); + else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ; + *(temp++) +=fac*vlr->n[0]; + *(temp++) +=fac*vlr->n[1]; + *(temp) +=fac*vlr->n[2]; + + if(adrve4) { + temp= adrve4->n; + fac= *(tfl++); + if( vlr->flag & R_NOPUNOFLIP); + else if( contrpuntnormr(vlr->n, temp) ) fac= -fac ; + *(temp++) +=fac*vlr->n[0]; + *(temp++) +=fac*vlr->n[1]; + *(temp) +=fac*vlr->n[2]; + } + } + + /* normaliseren puntnormalen */ + for(a=startvert; a<R.totvert; a++) { + ver= RE_findOrAddVert(a); + + Normalise(ver->n); + } + + /* puntnormaal omklap-vlaggen voor bij shade */ + for(a=startvlak; a<R.totvlak; a++) { + vlr= RE_findOrAddVlak(a); + + if((vlr->flag & R_NOPUNOFLIP)==0) { + adrve1= vlr->v1; + adrve2= vlr->v2; + adrve3= vlr->v3; + adrve4= vlr->v4; + + vlr->puno= 0; + fac= vlr->n[0]*adrve1->n[0]+vlr->n[1]*adrve1->n[1]+vlr->n[2]*adrve1->n[2]; + if(fac<0.0) vlr->puno= 1; + fac= vlr->n[0]*adrve2->n[0]+vlr->n[1]*adrve2->n[1]+vlr->n[2]*adrve2->n[2]; + if(fac<0.0) vlr->puno+= 2; + fac= vlr->n[0]*adrve3->n[0]+vlr->n[1]*adrve3->n[1]+vlr->n[2]*adrve3->n[2]; + if(fac<0.0) vlr->puno+= 4; + + if(adrve4) { + fac= vlr->n[0]*adrve4->n[0]+vlr->n[1]*adrve4->n[1]+vlr->n[2]*adrve4->n[2]; + if(fac<0.0) vlr->puno+= 8; + } + } + } + + MEM_freeN(adrco); +} + +/* ------------------------------------------------------------------------- */ +/* Autosmoothing: */ +/* ------------------------------------------------------------------------- */ + +typedef struct ASvert { + int totface; + ListBase faces; +} ASvert; + +typedef struct ASface { + struct ASface *next, *prev; + VlakRen *vlr[4]; + VertRen *nver[4]; +} ASface; + +/* prototypes: */ +static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh); +static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh); + + +static void as_addvert(VertRen *v1, VlakRen *vlr) +{ + ASvert *asv; + ASface *asf; + int a; + + if(v1 == NULL) return; + + if(v1->svert==0) { + v1->svert= MEM_callocN(sizeof(ASvert), "asvert"); + asv= v1->svert; + asf= MEM_callocN(sizeof(ASface), "asface"); + BLI_addtail(&asv->faces, asf); + } + + asv= v1->svert; + asf= asv->faces.last; + for(a=0; a<4; a++) { + if(asf->vlr[a]==0) { + asf->vlr[a]= vlr; + asv->totface++; + break; + } + } + + /* new face struct */ + if(a==4) { + asf= MEM_callocN(sizeof(ASface), "asface"); + BLI_addtail(&asv->faces, asf); + asf->vlr[0]= vlr; + asv->totface++; + } +} + +static void as_freevert(VertRen *ver) +{ + ASvert *asv; + + asv= ver->svert; + BLI_freelistN(&asv->faces); + MEM_freeN(asv); + ver->svert= NULL; +} + +static int as_testvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh) +{ + /* return 1: vertex needs a copy */ + ASface *asf; + float inp; + int a; + + if(vlr==0) return 0; + + asf= asv->faces.first; + while(asf) { + for(a=0; a<4; a++) { + if(asf->vlr[a] && asf->vlr[a]!=vlr) { + 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] ); + if(inp < thresh) return 1; + } + } + asf= asf->next; + } + + return 0; +} + +static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thresh) +{ + /* return when new vertex already was made */ + ASface *asf; + float inp; + int a; + + asf= asv->faces.first; + while(asf) { + for(a=0; a<4; a++) { + if(asf->vlr[a] && asf->vlr[a]!=vlr) { + /* this face already made a copy for this vertex! */ + if(asf->nver[a]) { + 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] ); + if(inp >= thresh) { + return asf->nver[a]; + } + } + } + } + asf= asf->next; + } + + return NULL; +} + +static void autosmooth(int startvert, int startvlak, int degr) +{ + ASvert *asv; + ASface *asf; + VertRen *ver, *v1; + VlakRen *vlr; + float thresh; + int a, b, totvert; + + thresh= cos( M_PI*((float)degr)/180.0 ); + + /* initialize */ + for(a=startvert; a<R.totvert; a++) { + ver= RE_findOrAddVert(a); + ver->svert= 0; + } + + /* step one: construct listbase of all vertices and pointers to faces */ + for(a=startvlak; a<R.totvlak; a++) { + vlr= RE_findOrAddVlak(a); + + as_addvert(vlr->v1, vlr); + as_addvert(vlr->v2, vlr); + as_addvert(vlr->v3, vlr); + as_addvert(vlr->v4, vlr); + } + + /* we now test all vertices, when faces have a normal too much different: they get a new vertex */ + totvert= R.totvert; + for(a=startvert; a<totvert; a++) { + ver= RE_findOrAddVert(a); + asv= ver->svert; + if(asv && asv->totface>1) { + + asf= asv->faces.first; + while(asf) { + for(b=0; b<4; b++) { + + /* is there a reason to make a new vertex? */ + vlr= asf->vlr[b]; + if( as_testvertex(vlr, ver, asv, thresh) ) { + + /* already made a new vertex within threshold? */ + v1= as_findvertex(vlr, ver, asv, thresh); + if(v1==0) { + /* make a new vertex */ + v1= RE_findOrAddVert(R.totvert++); + *v1= *ver; + v1->svert= 0; + } + asf->nver[b]= v1; + if(vlr->v1==ver) vlr->v1= v1; + if(vlr->v2==ver) vlr->v2= v1; + if(vlr->v3==ver) vlr->v3= v1; + if(vlr->v4==ver) vlr->v4= v1; + } + } + asf= asf->next; + } + } + } + + /* free */ + for(a=startvert; a<R.totvert; a++) { + ver= RE_findOrAddVert(a); + if(ver->svert) as_freevert(ver); + } + +} + +/* ------------------------------------------------------------------------- */ +/* End of autosmoothing: */ +/* ------------------------------------------------------------------------- */ + +static void make_render_halos(Object *ob, Mesh *me, Material *ma, float *extverts) +{ + HaloRen *har; + MVert *mvert; + float xn, yn, zn, nor[3], view[3]; + float *orco, vec[3], hasize, mat[4][4], imat[3][3]; + int start, end, a, ok; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat3CpyMat4(imat, ob->imat); + + R.flag |= R_HALO; + mvert= me->mvert; + + orco= me->orco; + + start= 0; + end= me->totvert; + set_buildvars(ob, &start, &end); + mvert+= start; + if(extverts) extverts+= 3*start; + + ma->ren->seed1= ma->seed1; + + for(a=start; a<end; a++, mvert++) { + ok= 1; + + if(ok) { + hasize= ma->hasize; + + if(extverts) { + VECCOPY(vec, extverts); + extverts+= 3; + } + else { + VECCOPY(vec, mvert->co); + } + MTC_Mat4MulVecfl(mat, vec); + + if(ma->mode & MA_HALOPUNO) { + xn= mvert->no[0]; + yn= mvert->no[1]; + zn= mvert->no[2]; + + /* transpose ! */ + nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(nor); + + VECCOPY(view, vec); + Normalise(view); + + zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; + if(zn>=0.0) hasize= 0.0; + else hasize*= zn*zn*zn*zn; + } + + if(orco) har= RE_inithalo(ma, vec, 0, orco, hasize, 0); + else har= RE_inithalo(ma, vec, 0, mvert->co, hasize, 0); + if(har) har->lay= ob->lay; + } + if(orco) orco+= 3; + ma->ren->seed1++; + } +} + +/* ------------------------------------------------------------------------- */ + +static int test_flipnorm(float *v1, float *v2, float *v3, VlakRen *vlr, float imat[][3]) +{ + float nor[3], vec[3]; + float xn; + + CalcNormFloat(v1, v2, v3, nor); + vec[0]= imat[0][0]*nor[0]+ imat[0][1]*nor[1]+ imat[0][2]*nor[2]; + vec[1]= imat[1][0]*nor[0]+ imat[1][1]*nor[1]+ imat[1][2]*nor[2]; + vec[2]= imat[2][0]*nor[0]+ imat[2][1]*nor[1]+ imat[2][2]*nor[2]; + + xn= vec[0]*vlr->n[0]+vec[1]*vlr->n[1]+vec[2]*vlr->n[2]; + + return (xn<0.0); +} + +static int mesh_test_flipnorm(Object *ob, MFace *mface, VlakRen *vlr, float imat[][3]) +{ + DispList *dl; + Mesh *me= ob->data; + float *v1, *v2, *v3; + + dl= find_displist(&ob->disp, DL_VERTS); + if(dl) { + v1= dl->verts + 3*mface->v1; + v2= dl->verts + 3*mface->v2; + v3= dl->verts + 3*mface->v3; + } + else { + v1= (me->mvert+mface->v1)->co; + v2= (me->mvert+mface->v2)->co; + v3= (me->mvert+mface->v3)->co; + } + + return test_flipnorm(v1, v2, v3, vlr, imat); +} + + +/* ------------------------------------------------------------------------- */ + + + +/* ------------------------------------------------------------------------- */ + +static void render_particle_system(Object *ob, PartEff *paf) +{ + Particle *pa=0; + HaloRen *har=0; + Material *ma=0; + float xn, yn, zn, imat[3][3], mat[4][4], hasize, ptime, ctime, vec[3], vec1[3], view[3], nor[3]; + int a, mat_nr=1; + + pa= paf->keys; + if(pa==0) { + build_particle_system(ob); + pa= paf->keys; + if(pa==0) return; + } + + ma= give_render_material(ob, 1); + if(ma==0) ma= &defmaterial; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); /* hoort zo, voor imat texture */ + + MTC_Mat4Invert(mat, R.viewmat); /* particles hebben geen ob transform meer */ + MTC_Mat3CpyMat4(imat, mat); + + R.flag |= R_HALO; + + if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf; + else ptime= 0.0; + ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, ptime); + ma->ren->seed1= ma->seed1; + + for(a=0; a<paf->totpart; a++, pa+=paf->totkey) { + + if(ctime > pa->time) { + if(ctime < pa->time+pa->lifetime) { + + /* let op: ook nog de normaal van de particle berekenen */ + if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) { + where_is_particle(paf, pa, ctime, vec); + MTC_Mat4MulVecfl(R.viewmat, vec); + where_is_particle(paf, pa, ctime+1.0, vec1); + MTC_Mat4MulVecfl(R.viewmat, vec1); + } + else { + where_is_particle(paf, pa, ctime, vec); + MTC_Mat4MulVecfl(R.viewmat, vec); + } + + if(pa->mat_nr != mat_nr) { + mat_nr= pa->mat_nr; + ma= give_render_material(ob, mat_nr); + if(ma==0) ma= &defmaterial; + } + + if(ma->ipo) { + /* correctie voor lifetime */ + ptime= 100.0*(ctime-pa->time)/pa->lifetime; + calc_ipo(ma->ipo, ptime); + execute_ipo((ID *)ma, ma->ipo); + } + + hasize= ma->hasize; + + if(ma->mode & MA_HALOPUNO) { + xn= pa->no[0]; + yn= pa->no[1]; + zn= pa->no[2]; + + /* transpose ! */ + nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(nor); + + VECCOPY(view, vec); + Normalise(view); + + zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; + if(zn>=0.0) hasize= 0.0; + else hasize*= zn*zn*zn*zn; + } + + if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize); + else { + har= RE_inithalo(ma, vec, 0, pa->co, hasize, 0); + if(har && ma->mode & MA_HALO_SHADE) { + VecSubf(har->no, vec, vec1); + Normalise(har->no); + } + } + if(har) har->lay= ob->lay; + } + } + ma->ren->seed1++; + } + +} + + +/* ------------------------------------------------------------------------- */ + +static void render_static_particle_system(Object *ob, PartEff *paf) +{ + Particle *pa=0; + HaloRen *har=0; + Material *ma=0; + float xn, yn, zn, imat[3][3], mat[4][4], hasize; + float mtime, ptime, ctime, vec[3], vec1[3], view[3], nor[3]; + int a, mat_nr=1; + + pa= paf->keys; + if(pa==0) { + build_particle_system(ob); + pa= paf->keys; + if(pa==0) return; + } + + ma= give_render_material(ob, 1); + if(ma==0) ma= &defmaterial; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); /* hoort zo, voor imat texture */ + + MTC_Mat3CpyMat4(imat, ob->imat); + + R.flag |= R_HALO; + + if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf; + else ptime= 0.0; + ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, ptime); + ma->ren->seed1= ma->seed1; + + for(a=0; a<paf->totpart; a++, pa+=paf->totkey) { + + where_is_particle(paf, pa, pa->time, vec1); + MTC_Mat4MulVecfl(mat, vec1); + + mtime= pa->time+pa->lifetime+paf->staticstep-1; + + for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) { + + /* make sure hair grows until the end.. */ + if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime; + + + /* let op: ook nog de normaal van de particle berekenen */ + if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) { + where_is_particle(paf, pa, ctime+1.0, vec); + MTC_Mat4MulVecfl(mat, vec); + } + else { + where_is_particle(paf, pa, ctime, vec); + MTC_Mat4MulVecfl(mat, vec); + } + + if(pa->mat_nr != mat_nr) { + mat_nr= pa->mat_nr; + ma= give_render_material(ob, mat_nr); + if(ma==0) ma= &defmaterial; + } + + if(ma->ipo) { + /* correctie voor lifetime */ + ptime= 100.0*(ctime-pa->time)/pa->lifetime; + calc_ipo(ma->ipo, ptime); + execute_ipo((ID *)ma, ma->ipo); + } + + hasize= ma->hasize; + + if(ma->mode & MA_HALOPUNO) { + xn= pa->no[0]; + yn= pa->no[1]; + zn= pa->no[2]; + + /* transpose ! */ + nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(nor); + + VECCOPY(view, vec); + Normalise(view); + + zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2]; + if(zn>=0.0) hasize= 0.0; + else hasize*= zn*zn*zn*zn; + } + + if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize); + else { + har= RE_inithalo(ma, vec, 0, pa->co, hasize, 0); + if(har && (ma->mode & MA_HALO_SHADE)) { + VecSubf(har->no, vec, vec1); + Normalise(har->no); + har->lay= ob->lay; + } + } + + VECCOPY(vec1, vec); + } + ma->ren->seed1++; + } + +} + +/* ------------------------------------------------------------------------- */ + +static void init_render_displist_mesh(Object *ob) +{ + Mesh *me; + DispList *dl; + VlakRen *vlr; + Material *matar[32]; + VertRen *ver, *v1, *v2, *v3, *v4; + float xn, yn, zn; + float mat[4][4], imat[3][3], *data, *nors, *orco=0, n1[3], flen; + int a, b, flipnorm= -1, need_orco=0, startvert, p1, p2, p3, p4; + int old_totvert= R.totvert; + int old_totvlak= R.totvlak; + + me= ob->data; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + MTC_Mat3CpyMat4(imat, ob->imat); + + /* material array */ + memset(matar, 0, sizeof(matar)); + matar[0]= &defmaterial; + for(a=0; a<ob->totcol; a++) { + matar[a]= give_render_material(ob, a+1); + if(matar[a]==0) matar[a]= &defmaterial; + if(matar[a]->ren->texco & TEXCO_ORCO) { + need_orco= 1; + } + } + + dl= me->disp.first; + + /* Force a displist rebuild if this is a subsurf and we have a different subdiv level */ +#if 1 + if((dl==0) || ((me->subdiv != me->subdivr))){ + object_deform(ob); + subsurf_make_mesh(ob, me->subdivr); + dl = me->disp.first; + + } + else{ + makeDispList(ob); + dl= me->disp.first; + } +#else + tempdiv = me->subdiv; + me->subdiv = me->subdivr; + makeDispList(ob); + dl= me->disp.first; +#endif + if(dl==0) return; + + if(need_orco) { + make_orco_displist_mesh(ob, me->subdivr); + orco= me->orco; + } + +#if 0 + me->subdiv = tempdiv; +#endif + + while(dl) { + if(dl->type==DL_SURF) { + startvert= R.totvert; + a= dl->nr*dl->parts; + data= dl->verts; + nors= dl->nors; + + while(a--) { + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, data); + if(orco) { + ver->orco= orco; + orco+= 3; + } + else { + ver->orco= data; + } + + MTC_Mat4MulVecfl(mat, ver->co); + + xn= nors[0]; + yn= nors[1]; + zn= nors[2]; + + /* transpose ! */ + ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + + Normalise(ver->n); + + data+= 3; + nors+= 3; + } + + for(a=0; a<dl->parts; a++) { + + DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts); + p1+= startvert; + p2+= startvert; + p3+= startvert; + p4+= startvert; + + for(; b<dl->nr; b++) { + v1= RE_findOrAddVert(p1); + v2= RE_findOrAddVert(p2); + v3= RE_findOrAddVert(p3); + v4= RE_findOrAddVert(p4); + + flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1); + if(flen!=0.0) { + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= v1; + vlr->v2= v3; + vlr->v3= v4; + vlr->v4= v2; + VECCOPY(vlr->n, n1); + vlr->len= flen; + vlr->lay= ob->lay; + + vlr->mat= matar[ dl->col]; + vlr->ec= ME_V1V2+ME_V2V3; + vlr->flag= ME_SMOOTH; + + if(flipnorm== -1) flipnorm= mesh_test_flipnorm(ob, me->mface, vlr, imat); + + if(flipnorm) { + vlr->n[0]= -vlr->n[0]; + vlr->n[1]= -vlr->n[1]; + vlr->n[2]= -vlr->n[2]; + } + + /* vlr->flag |= R_NOPUNOFLIP; */ + /* vlr->puno= 15; */ + vlr->puno= 0; + } + + p4= p3; + p3++; + p2= p1; + p1++; + } + } + } else if (dl->type==DL_MESH) { + DispListMesh *dlm= dl->mesh; + int i; + + startvert= R.totvert; + for (i=0; i<dlm->totvert; i++) { + MVert *mv= &dlm->mvert[i]; + + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, mv->co); + MTC_Mat4MulVecfl(mat, ver->co); + + xn= mv->no[0]; + yn= mv->no[1]; + zn= mv->no[2]; + + /* transpose ! */ + ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + + Normalise(ver->n); + + if (orco) + ver->orco= &orco[i*3]; + } + + for (i=0; i<dlm->totface; i++) { + MFaceInt *mf= &dlm->mface[i]; + + if (!mf->v3) + continue; + + v1= RE_findOrAddVert(startvert+mf->v1); + v2= RE_findOrAddVert(startvert+mf->v2); + v3= RE_findOrAddVert(startvert+mf->v3); + + if (mf->v4) { + v4= RE_findOrAddVert(startvert+mf->v4); + flen= CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, n1); + } else { + v4= 0; + flen= CalcNormFloat(v1->co, v2->co, v3->co, n1); + } + + if(flen!=0.0) { + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= v1; + vlr->v2= v2; + vlr->v3= v3; + vlr->v4= v4; + + VECCOPY(vlr->n, n1); + vlr->len= flen; + vlr->lay= ob->lay; + + vlr->mat= matar[mf->mat_nr]; + vlr->flag= mf->flag; + vlr->ec= mf->edcode; + vlr->puno= mf->puno; + + if(flipnorm== -1) flipnorm= test_flipnorm(v1->co, v2->co, v3->co, vlr, imat); + + if(flipnorm) { + vlr->n[0]= -vlr->n[0]; + vlr->n[1]= -vlr->n[1]; + vlr->n[2]= -vlr->n[2]; + } + + if (dlm->tface) { + vlr->tface= &dlm->tface[i]; + vlr->vcol= vlr->tface->col; + } else if (dlm->mcol) + vlr->vcol= (unsigned int *) &dlm->mcol[i*4]; + } + } + } + + dl= dl->next; + } + + + normalenrender(old_totvert, old_totvlak); + +} + +/* ------------------------------------------------------------------------- */ + +static int verghalo(const void *a1, const void *a2) +{ + const struct halosort *x1=a1, *x2=a2; + + if( x1->z < x2->z ) return 1; + else if( x1->z > x2->z) return -1; + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void sort_halos(void) +{ + struct halosort *hablock, *haso; + HaloRen *har = NULL, **bloha; + int a; + + if(R.tothalo==0) return; + + /* datablok maken met halopointers, sorteren */ + haso= hablock= MEM_mallocN(sizeof(struct halosort)*R.tothalo, "hablock"); + + for(a=0; a<R.tothalo; a++) { + if((a & 255)==0) har= R.bloha[a>>8]; + else har++; + haso->har= har; + haso->z= har->zs; + haso++; + } + + qsort(hablock, R.tothalo, sizeof(struct halosort), verghalo); + + /* opnieuw samenstellen van R.bloha */ + + bloha= R.bloha; + R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(MAXVERT>>8),"Bloha"); + + haso= hablock; + for(a=0; a<R.tothalo; a++) { + har= RE_findOrAddHalo(a); + *har= *(haso->har); + + haso++; + } + + /* vrijgeven */ + a= 0; + while(bloha[a]) { + MEM_freeN(bloha[a]); + a++; + } + MEM_freeN(bloha); + MEM_freeN(hablock); + +} + + + +static Material *give_render_material(Object *ob, int nr) +{ + Object *temp; + + if(ob->flag & OB_FROMDUPLI) { + temp= (Object *)ob->id.newid; + if(temp && temp->type==OB_FONT) { + ob= temp; + } + } + + return give_current_material(ob, nr); +} + +/* ------------------------------------------------------------------------- */ +static void init_render_mball(Object *ob) +{ + DispList *dl, *dlo; + VertRen *ver; + VlakRen *vlr, *vlr1; + Material *ma; + float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn; + int a, need_orco, startvert, *index; + + if (ob!=find_basis_mball(ob)) + return; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + MTC_Mat3CpyMat4(imat, ob->imat); + + ma= give_render_material(ob, 1); + if(ma==0) ma= &defmaterial; + + need_orco= 0; + if(ma->ren->texco & TEXCO_ORCO) { + need_orco= 1; + } + + dlo= ob->disp.first; + if(dlo) BLI_remlink(&ob->disp, dlo); + + makeDispList(ob); + dl= ob->disp.first; + if(dl==0) return; + + startvert= R.totvert; + data= dl->verts; + nors= dl->nors; + + for(a=0; a<dl->nr; a++, data+=3, nors+=3) { + + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, data); + MTC_Mat4MulVecfl(mat, ver->co); + + /* rendernormalen zijn omgekeerd */ + xn= -nors[0]; + yn= -nors[1]; + zn= -nors[2]; + + /* transpose ! */ + ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(ver->n); + + if(need_orco) ver->orco= data; + } + + index= dl->index; + for(a=0; a<dl->parts; a++, index+=4) { + + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= RE_findOrAddVert(startvert+index[0]); + vlr->v2= RE_findOrAddVert(startvert+index[1]); + vlr->v3= RE_findOrAddVert(startvert+index[2]); + vlr->v4= 0; + + /* rendernormalen zijn omgekeerd */ + vlr->len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + + vlr->mface= 0; + vlr->mat= ma; + vlr->puno= 0; + vlr->flag= ME_SMOOTH+R_NOPUNOFLIP; + vlr->ec= 0; + vlr->lay= ob->lay; + + /* mball -helaas- altijd driehoeken maken omdat vierhoeken erg onregelmatig zijn */ + if(index[3]) { + vlr1= RE_findOrAddVlak(R.totvlak++); + *vlr1= *vlr; + vlr1->v2= vlr1->v3; + vlr1->v3= RE_findOrAddVert(startvert+index[3]); + vlr->len= CalcNormFloat(vlr1->v3->co, vlr1->v2->co, vlr1->v1->co, vlr1->n); + } + } + + if(need_orco) { + /* displist bewaren en scalen */ + make_orco_mball(ob); + if(dlo) BLI_addhead(&ob->disp, dlo); + + } + else { + freedisplist(&ob->disp); + if(dlo) BLI_addtail(&ob->disp, dlo); + } +} +/* ------------------------------------------------------------------------- */ +/* convert */ +static void init_render_mesh(Object *ob) +{ + MFace *mface; + MVert *mvert; + Mesh *me; + VlakRen *vlr, *vlr1; + VertRen *ver; + Material *ma; + MSticky *ms; + PartEff *paf; + DispList *dl; + TFace *tface; + unsigned int *vertcol; + float xn, yn, zn, nor[3], imat[3][3], mat[4][4]; + float *extverts=0, *orco; + int a, a1, ok, do_puno, need_orco=0, totvlako, totverto, vertofs; + int start, end, flipnorm; + + me= ob->data; + if (rendermesh_uses_displist(me) && me->subdivr>0) { + init_render_displist_mesh(ob); + return; + } + + paf = give_parteff(ob); + if(paf) { + if(paf->flag & PAF_STATIC) render_static_particle_system(ob, paf); + else render_particle_system(ob, paf); + return; + } + + /* object_deform changes imat */ + do_puno= object_deform(ob); + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + MTC_Mat3CpyMat4(imat, ob->imat); + + if(me->totvert==0) return; + mvert= me->mvert; + + dl= find_displist(&ob->disp, DL_VERTS); + if(dl) extverts= dl->verts; + + totvlako= R.totvlak; + totverto= R.totvert; + + if(me->key) do_puno= 1; + + if(ob->effect.first) { + Effect *eff= ob->effect.first; + while(eff) { + if(eff->type==EFF_WAVE) do_puno= 1; + eff= eff->next; + } + } + + if(me->orco==0) { + need_orco= 0; + for(a=1; a<=ob->totcol; a++) { + ma= give_render_material(ob, a); + if(ma) { + if(ma->ren->texco & TEXCO_ORCO) { + need_orco= 1; + break; + } + } + } + if(need_orco) { + make_orco_mesh(me); + } + } + + orco= me->orco; + ms= me->msticky; + tface= me->tface; + if(tface) vertcol= ((TFace *)me->tface)->col; + else vertcol= (unsigned int *)me->mcol; + + ma= give_render_material(ob, 1); + if(ma==0) ma= &defmaterial; + + + if(ma->mode & MA_HALO) { + make_render_halos(ob, me, ma, extverts); + } + else { + + for(a=0; a<me->totvert; a++, mvert++) { + + ver= RE_findOrAddVert(R.totvert++); + if(extverts) { + VECCOPY(ver->co, extverts); + extverts+= 3; + } + else { + VECCOPY(ver->co, mvert->co); + } + MTC_Mat4MulVecfl(mat, ver->co); + + xn= mvert->no[0]; + yn= mvert->no[1]; + zn= mvert->no[2]; + if(do_puno==0) { + /* transpose ! */ + ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(ver->n); + } + if(orco) { + ver->orco= orco; + orco+=3; + } + if(ms) { + ver->sticky= (float *)ms; + ms++; + } + } + /* nog doen bij keys: de juiste lokale textu coordinaat */ + + flipnorm= -1; + /* Testen of er een flip in de matrix zit: dan vlaknormaal ook flippen */ + + /* vlakken in volgorde colblocks */ + vertofs= R.totvert- me->totvert; + for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) { + + ma= give_render_material(ob, a1+1); + if(ma==0) ma= &defmaterial; + + /* testen op 100% transparant */ + ok= 1; + if(ma->alpha==0.0 && ma->spectra==0.0) { + ok= 0; + /* texture op transp? */ + for(a=0; a<8; a++) { + if(ma->mtex[a] && ma->mtex[a]->tex) { + if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1; + } + } + } + + if(ok) { + + start= 0; + end= me->totface; + set_buildvars(ob, &start, &end); + mvert= me->mvert; + mface= me->mface; + mface+= start; + if(tface) { + tface= me->tface; + tface+= start; + } + + for(a=start; a<end; a++, mface++) { + + if( mface->mat_nr==a1 ) { + + if(mface->v3) { + + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= RE_findOrAddVert(vertofs+mface->v1); + vlr->v2= RE_findOrAddVert(vertofs+mface->v2); + vlr->v3= RE_findOrAddVert(vertofs+mface->v3); + if(mface->v4) vlr->v4= RE_findOrAddVert(vertofs+mface->v4); + else vlr->v4= 0; + + /* rendernormalen zijn omgekeerd */ + if(vlr->v4) vlr->len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, + vlr->v1->co, vlr->n); + else vlr->len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, + vlr->n); + vlr->mface= mface; + vlr->mat= ma; + vlr->puno= mface->puno; + vlr->flag= mface->flag; + if(me->flag & ME_NOPUNOFLIP) { + vlr->flag |= R_NOPUNOFLIP; + vlr->puno= 15; + } + vlr->ec= mface->edcode; + vlr->lay= ob->lay; + + if(vlr->len==0) R.totvlak--; + else { + if(flipnorm== -1) { /* per object 1 x testen */ + flipnorm= mesh_test_flipnorm(ob, mface, vlr, imat); + } + if(flipnorm) { + vlr->n[0]= -vlr->n[0]; + vlr->n[1]= -vlr->n[1]; + vlr->n[2]= -vlr->n[2]; + } + + if(vertcol) { + if(tface) vlr->vcol= vertcol+sizeof(TFace)*a/4; /* vertcol is int */ + else vlr->vcol= vertcol+sizeof(int)*a; + } + else vlr->vcol= 0; + + vlr->tface= tface; + + /* testen of een vierhoek als driehoek gerenderd moet */ + if(vlr->v4) { + + if(ma->mode & MA_WIRE); + else { + CalcNormFloat(vlr->v4->co, vlr->v3->co, vlr->v1->co, nor); + if(flipnorm) { + nor[0]= -nor[0]; + nor[1]= -nor[1]; + nor[2]= -nor[2]; + } + + xn= nor[0]*vlr->n[0] + nor[1]*vlr->n[1] + nor[2]*vlr->n[2]; + if( xn < 0.9990 ) { + /* recalc this nor, previous calc was with calcnormfloat4 */ + if(flipnorm) CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n); + else CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + + vlr1= RE_findOrAddVlak(R.totvlak++); + *vlr1= *vlr; + vlr1->flag |= R_FACE_SPLIT; + VECCOPY(vlr1->n, nor); + vlr1->v2= vlr->v3; + vlr1->v3= vlr->v4; + vlr->v4= vlr1->v4= 0; + + vlr1->puno= 0; + if(vlr->puno & ME_FLIPV1) vlr1->puno |= ME_FLIPV1; + if(vlr->puno & ME_FLIPV3) vlr1->puno |= ME_FLIPV2; + if(vlr->puno & ME_FLIPV4) vlr1->puno |= ME_FLIPV3; + + } + } + } + } + } + else if(mface->v2 && (ma->mode & MA_WIRE)) { + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= RE_findOrAddVert(vertofs+mface->v1); + vlr->v2= RE_findOrAddVert(vertofs+mface->v2); + vlr->v3= vlr->v2; + vlr->v4= 0; + + vlr->n[0]=vlr->n[1]=vlr->n[2]= 0.0; + + vlr->mface= mface; + vlr->mat= ma; + vlr->puno= mface->puno; + vlr->flag= mface->flag; + vlr->ec= ME_V1V2; + vlr->lay= ob->lay; + } + } + + if(tface) tface++; + } + } + } + } + + if(me->flag & ME_AUTOSMOOTH) { + autosmooth(totverto, totvlako, me->smoothresh); + do_puno= 1; + } + + if(do_puno) normalenrender(totverto, totvlako); + +} + +/* ------------------------------------------------------------------------- */ +/* If lar takes more lamp data, the decoupling will be better. */ +void RE_add_render_lamp(Object *ob, int doshadbuf) +{ + Lamp *la; + LampRen *lar; + float mat[4][4], hoek, xn, yn; + int c; + + if(R.totlamp>=MAXLAMP) { + printf("lamp overflow\n"); + return; + } + la= ob->data; + lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren"); + R.la[R.totlamp++]= lar; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + + MTC_Mat3CpyMat4(lar->imat, ob->imat); + + lar->bufsize = la->bufsize; + lar->samp = la->samp; + lar->soft = la->soft; + lar->shadhalostep = la->shadhalostep; + lar->clipsta = la->clipsta; + lar->clipend = la->clipend; + lar->bias = la->bias; + + lar->type= la->type; + lar->mode= la->mode; + + lar->energy= la->energy; + lar->energy= la->energy*R.wrld.exposure; + if(la->mode & LA_NEG) lar->energy= -lar->energy; + + lar->vec[0]= -mat[2][0]; + lar->vec[1]= -mat[2][1]; + lar->vec[2]= -mat[2][2]; + Normalise(lar->vec); + lar->co[0]= mat[3][0]; + lar->co[1]= mat[3][1]; + lar->co[2]= mat[3][2]; + lar->dist= la->dist; + lar->haint= la->haint; + lar->distkw= lar->dist*lar->dist; + lar->r= lar->energy*la->r; + lar->g= lar->energy*la->g; + lar->b= lar->energy*la->b; + lar->spotsi= 0.5; + + lar->spotsi= cos( M_PI*la->spotsize/360.0 ); + lar->spotbl= (1.0-lar->spotsi)*la->spotblend; + + memcpy(lar->mtex, la->mtex, 8*4); + + + lar->lay= ob->lay; + + lar->ld1= la->att1; + lar->ld2= la->att2; + + if(lar->type==LA_SPOT) { + + Normalise(lar->imat[0]); + Normalise(lar->imat[1]); + Normalise(lar->imat[2]); + + xn= saacos(lar->spotsi); + xn= sin(xn)/cos(xn); + lar->spottexfac= 1.0/(xn); + + if(lar->mode & LA_ONLYSHADOW) { + if((lar->mode & LA_SHAD)==0) lar->mode -= LA_ONLYSHADOW; + else if((R.r.mode & R_SHADOW)==0) lar->mode -= LA_ONLYSHADOW; + } + + } + + /* imat bases */ + + + /* flag zetten voor spothalo en initvars */ + if(la->type==LA_SPOT && (la->mode & LA_HALO)) { + if(la->haint>0.0) { + R.flag |= R_LAMPHALO; + + /* camerapos (0,0,0) roteren rondom lamp */ + lar->sh_invcampos[0]= -lar->co[0]; + lar->sh_invcampos[1]= -lar->co[1]; + lar->sh_invcampos[2]= -lar->co[2]; + MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos); + + /* z factor, zodat het volume genormaliseerd is */ + hoek= saacos(lar->spotsi); + xn= lar->spotsi; + yn= sin(hoek); + lar->sh_zfac= yn/xn; + /* alvast goed scalen */ + lar->sh_invcampos[2]*= lar->sh_zfac; + + } + } + + for(c=0; c<6; c++) { + if(la->mtex[c] && la->mtex[c]->tex) { + lar->mode |= LA_TEXTURE; + + if(R.flag & R_RENDERING) { + if(R.osa) { + if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX; + } + } + } + } + + if( (R.r.mode & R_SHADOW) + && (lar->mode & LA_SHAD) + && (la->type==LA_SPOT) + && doshadbuf + ) + { + /* Per lamp, one shadow buffer is made. */ + if (R.r.mode & R_UNIFIED) { + int mode; + /* For the UR, I want to stick to the cpp version. I can + * put a switch here for the different shadow buffers. At + * this point, the type of shadow buffer is + * determined. The actual calculations are done during the + * render pre operations. */ + if (lar->mode & LA_DEEP_SHADOW) { + mode = 0; /* dummy, for testing */ + } else if (2) { + mode = 2; /* old-style buffer */ + } + lar->shadowBufOb = (void*) RE_createShadowBuffer(lar, + ob->obmat, + mode); + } else { + RE_createShadowBuffer(lar, + ob->obmat, + 1); /* mode = 1 is old buffer */ + } + } + + lar->org= MEM_dupallocN(lar); +} + +/* ------------------------------------------------------------------------- */ +static void init_render_surf(Object *ob) +{ + Nurb *nu=0; + Curve *cu; + ListBase displist; + DispList *dl; + VertRen *ver, *v1, *v2, *v3, *v4; + VlakRen *vlr; + Material *matar[32]; + float *data, *fp, *orco, n1[3], flen, mat[4][4]; + int len, a, need_orco=0, startvlak, startvert, p1, p2, p3, p4; +#ifdef STRUBI + int u, v; + int sizeu, sizev; + VlakRen *vlr1, *vlr2, *vlr3; + float n2[3], vn[3]; + int index; +#endif + + cu= ob->data; + nu= cu->nurb.first; + if(nu==0) return; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + + /* material array */ + memset(matar, 0, 4*32); + matar[0]= &defmaterial; + for(a=0; a<ob->totcol; a++) { + matar[a]= give_render_material(ob, a+1); + if(matar[a]==0) matar[a]= &defmaterial; + if(matar[a] && matar[a]->ren->texco & TEXCO_ORCO) { + need_orco= 1; + } + } + + if(ob->parent && (ob->parent->type==OB_IKA || ob->parent->type==OB_LATTICE)) need_orco= 1; + + if(cu->orco==0 && need_orco) make_orco_surf(cu); + orco= cu->orco; + + /* een complete displist maken, de basedisplist kan compleet anders zijn */ + displist.first= displist.last= 0; + nu= cu->nurb.first; + while(nu) { + if(nu->pntsv>1) { + // if (dl->flag & DL_CYCLIC_V) { + len= nu->resolu*nu->resolv; + /* makeNurbfaces wil nullen */ + + dl= MEM_callocN(sizeof(DispList)+len*3*sizeof(float), "makeDispList1"); + dl->verts= MEM_callocN(len*3*sizeof(float), "makeDispList01"); + BLI_addtail(&displist, dl); + + dl->parts= nu->resolu; /* andersom want makeNurbfaces gaat zo */ + dl->nr= nu->resolv; + dl->col= nu->mat_nr; + dl->rt= nu->flag; + + data= dl->verts; + dl->type= DL_SURF; + /* if nurbs cyclic (u/v) set flags in displist accordingly */ + if(nu->flagv & 1) dl->flag |= DL_CYCLIC_V; + if(nu->flagu & 1) dl->flag |= DL_CYCLIC_U; + + makeNurbfaces(nu, data); + } + nu= nu->next; + } + + if(ob->parent && ob->parent->type==OB_LATTICE) { + init_latt_deform(ob->parent, ob); + dl= displist.first; + while(dl) { + + fp= dl->verts; + len= dl->nr*dl->parts; + for(a=0; a<len; a++, fp+=3) calc_latt_deform(fp); + + dl= dl->next; + } + end_latt_deform(); + } + +#ifdef __NLA + if(ob->parent && ob->parent->type==OB_ARMATURE) { +/* bArmature *arm= ob->parent->data; */ + init_armature_deform(ob->parent, ob); + dl= displist.first; + while(dl) { + + fp= dl->verts; + len= dl->nr*dl->parts; + for(a=0; a<len; a++, fp+=3) + calc_armature_deform(ob->parent, fp, a); + + dl= dl->next; + } + } +#endif + + if(ob->parent && ob->parent->type==OB_IKA) { + Ika *ika= ob->parent->data; + + init_skel_deform(ob->parent, ob); + dl= displist.first; + while(dl) { + + fp= dl->verts; + len= dl->nr*dl->parts; + for(a=0; a<len; a++, fp+=3) calc_skel_deform(ika, fp); + + dl= dl->next; + } + } + + dl= displist.first; + /* walk along displaylist and create rendervertices/-faces */ + while(dl) { +#ifdef STRUBI +/* watch out: u ^= y, v ^= x !! */ + if(dl->type==DL_SURF) { + startvert= R.totvert; + sizeu = dl->parts; sizev = dl->nr; + + data= dl->verts; + for (u = 0; u < sizeu; u++) { + v1 = RE_findOrAddVert(R.totvert++); /* save this for possible V wrapping */ + VECCOPY(v1->co, data); data += 3; + if(orco) { + v1->orco= orco; orco+= 3; + } + MTC_Mat4MulVecfl(mat, v1->co); + + for (v = 1; v < sizev; v++) { + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, data); data += 3; + if(orco) { + ver->orco= orco; orco+= 3; + } + MTC_Mat4MulVecfl(mat, ver->co); + } + /* if V-cyclic, add extra vertices at end of the row */ + if (dl->flag & DL_CYCLIC_V) { + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, v1->co); + ver->orco= orco; + orco+= 3; + } + } + + if (dl->flag & DL_CYCLIC_V) sizev++; /* adapt U dimension */ + + + /* if U cyclic, add extra row at end of column */ + if (dl->flag & DL_CYCLIC_U) { + for (v = 0; v < sizev; v++) { + v1= RE_findOrAddVert(startvert + v); + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, v1->co); + ver->orco= orco; + orco +=3; + + } + sizeu++; + } + + + + + startvlak= R.totvlak; + + /* process generic surface */ + for(u = 0; u < sizeu - 1; u++) { + +/* DL_SURFINDEX(dl->flag & DL_CYCLIC_U, dl->flag & DL_CYCLIC_V, dl->nr, dl->parts); + DL_SURFINDEX(0, 0, dl->nr, dl->parts); +*/ + + +/* + + ^ ()----p4----p3----() + | | | | | + u | | | | + | | | | + ()----p1----p2----() + v -> +*/ + + p1 = startvert + u * sizev; /* walk through face list */ + p2 = p1 + 1; + p3 = p2 + sizev; + p4 = p3 - 1; + + + for(v = 0; v < sizev - 1; v++) { + v1= RE_findOrAddVert(p1); + v2= RE_findOrAddVert(p2); + v3= RE_findOrAddVert(p3); + v4= RE_findOrAddVert(p4); + + flen= CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, n1); +/* flen can be 0 if there are double nurbs control vertices + so zero area faces can be generated + ->> there is at the moment no proper way to fix this except + generating empty render faces */ + +// if(flen!=0.0) { + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4; + VECCOPY(vlr->n, n1); + vlr->len= flen; + vlr->lay= ob->lay; + vlr->mat= matar[ dl->col]; + vlr->ec= ME_V1V2+ME_V2V3; + vlr->flag= dl->rt; + if(cu->flag & CU_NOPUNOFLIP) { + vlr->flag |= R_NOPUNOFLIP; + vlr->puno= 15; + } +// } + + VecAddf(v1->n, v1->n, n1); + VecAddf(v2->n, v2->n, n1); + VecAddf(v3->n, v3->n, n1); + VecAddf(v4->n, v4->n, n1); + + p1++; p2++; p3++; p4++; + } + } + /* fix normals for U resp. V cyclic faces */ + sizeu--; sizev--; /* dec size for face array */ + if (dl->flag & DL_CYCLIC_U) { + + for (v = 0; v < sizev; v++) + { + /* optimize! :*/ + index = startvlak + v; + // vlr= RE_findOrAddVlak(index + (sizeu-1) * sizev); + vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, v)); + GETNORMAL(vlr, n1); + vlr1= RE_findOrAddVlak(UVTOINDEX(0, v)); + GETNORMAL(vlr1, n2); + VecAddf(vlr1->v1->n, vlr1->v1->n, n1); + VecAddf(vlr1->v2->n, vlr1->v2->n, n1); + VecAddf(vlr->v3->n, vlr->v3->n, n2); + VecAddf(vlr->v4->n, vlr->v4->n, n2); + } + } + if (dl->flag & DL_CYCLIC_V) { + + for (u = 0; u < sizeu; u++) + { + /* optimize! :*/ + index = startvlak + u * sizev; + //vlr= RE_findOrAddVlak(index); + vlr= RE_findOrAddVlak(UVTOINDEX(u, 0)); + GETNORMAL(vlr, n1); + vlr1= RE_findOrAddVlak(UVTOINDEX(u, sizev-1)); + // vlr1= RE_findOrAddVlak(index + (sizev - 1)); + GETNORMAL(vlr1, n2); + VecAddf(vlr1->v2->n, vlr1->v2->n, n1); + VecAddf(vlr1->v3->n, vlr1->v3->n, n1); + VecAddf(vlr->v1->n, vlr->v1->n, n2); + VecAddf(vlr->v4->n, vlr->v4->n, n2); + } + } + /* last vertex is an extra case: + + ^ ()----()----()----() + | | | || | + u | |(0,n)||(0,0)| + | | || | + ()====()====[]====() + | | || | + | |(m,n)||(m,0)| + | | || | + ()----()----()----() + v -> + + vertex [] is no longer shared, therefore distribute + normals of the surrounding faces to all of the duplicates of [] + */ + + if (dl->flag & DL_CYCLIC_U && dl->flag & DL_CYCLIC_V) + { + vlr= RE_findOrAddVlak(UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */ + GETNORMAL(vlr, n1); + vlr1= RE_findOrAddVlak(UVTOINDEX(0,0)); /* (0,0) */ + GETNORMAL(vlr1, vn); + VecAddf(vn, vn, n1); + vlr2= RE_findOrAddVlak(UVTOINDEX(0, sizev-1)); /* (0,n) */ + GETNORMAL(vlr2, n1); + VecAddf(vn, vn, n1); + vlr3= RE_findOrAddVlak(UVTOINDEX(sizeu-1, 0)); /* (m,0) */ + GETNORMAL(vlr3, n1); + VecAddf(vn, vn, n1); + VECCOPY(vlr->v3->n, vn); + VECCOPY(vlr1->v1->n, vn); + VECCOPY(vlr2->v2->n, vn); + VECCOPY(vlr3->v4->n, vn); + } + for(a = startvert; a < R.totvert; a++) { + ver= RE_findOrAddVert(a); + Normalise(ver->n); + } + + + } +#else + + if(dl->type==DL_SURF) { + startvert= R.totvert; + a= dl->nr*dl->parts; + data= dl->verts; + while(a--) { + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, data); + if(orco) { + ver->orco= orco; + orco+= 3; + } + MTC_Mat4MulVecfl(mat, ver->co); + data+= 3; + } + + startvlak= R.totvlak; + + for(a=0; a<dl->parts; a++) { + + DL_SURFINDEX(dl->flag & DL_CYCLIC_V, dl->flag & DL_CYCLIC_U, dl->nr, dl->parts); + p1+= startvert; + p2+= startvert; + p3+= startvert; + p4+= startvert; + + for(; b<dl->nr; b++) { + v1= RE_findOrAddVert(p1); + v2= RE_findOrAddVert(p2); + v3= RE_findOrAddVert(p3); + v4= RE_findOrAddVert(p4); + + flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1); + if(flen!=0.0) { + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= v1; + vlr->v2= v3; + vlr->v3= v4; + vlr->v4= v2; + VECCOPY(vlr->n, n1); + vlr->len= flen; + vlr->lay= ob->lay; + vlr->mat= matar[ dl->col]; + vlr->ec= ME_V1V2+ME_V2V3; + vlr->flag= dl->rt; + if(cu->flag & CU_NOPUNOFLIP) { + vlr->flag |= R_NOPUNOFLIP; + vlr->puno= 15; + } + } + + VecAddf(v1->n, v1->n, n1); + VecAddf(v2->n, v2->n, n1); + VecAddf(v3->n, v3->n, n1); + VecAddf(v4->n, v4->n, n1); + + p4= p3; + p3++; + p2= p1; + p1++; + } + } + + for(a=startvert; a<R.totvert; a++) { + ver= RE_findOrAddVert(a); + Normalise(ver->n); + } + + + } +#endif + dl= dl->next; + } + freedisplist(&displist); +} + +static void init_render_curve(Object *ob) +{ + Ika *ika=0; + + Lattice *lt=0; + Curve *cu; + VertRen *ver; + VlakRen *vlr; + ListBase dlbev; + Nurb *nu=0; + DispList *dlb, *dl; + BevList *bl; + BevPoint *bevp; + Material *matar[32]; + float len, *data, *fp, *fp1, fac; + float n[3], vec[3], widfac, size[3], mat[4][4]; + int nr, startvert, startvlak, a, b, p1, p2, p3, p4; + int totvert, frontside, need_orco=0, firststartvert, *index; + + cu= ob->data; + nu= cu->nurb.first; + if(nu==0) return; + + /* displist testen */ + if(cu->disp.first==0) makeDispList(ob); + dl= cu->disp.first; + if(cu->disp.first==0) return; + + if(dl->type!=DL_INDEX3) { + curve_to_filledpoly(cu, &cu->disp); + } + + if(cu->bev.first==0) makeBevelList(ob); + + firststartvert= R.totvert; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + + /* material array */ + memset(matar, 0, 4*32); + matar[0]= &defmaterial; + for(a=0; a<ob->totcol; a++) { + matar[a]= give_render_material(ob, a+1); + if(matar[a]==0) matar[a]= &defmaterial; + if(matar[a]->ren->texco & TEXCO_ORCO) { + need_orco= 1; + } + } + + /* bevelcurve in displist */ + dlbev.first= dlbev.last= 0; + + if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj!=0) { + makebevelcurve(ob, &dlbev); + } + + /* uv orco's? aantal punten tellen en malloccen */ + if(need_orco && (cu->flag & CU_UV_ORCO)) { + if(cu->flag & CU_PATH); + else { + totvert= 0; + bl= cu->bev.first; + while(bl) { + dlb= dlbev.first; + while(dlb) { + totvert+= dlb->nr*bl->nr; + dlb= dlb->next; + } + bl= bl->next; + } + + if(totvert) { + fp= cu->orco= MEM_mallocN(3*sizeof(float)*totvert, "cu->orco"); + + bl= cu->bev.first; + while(bl) { + dlb= dlbev.first; + while(dlb) { + for(b=0; b<dlb->nr; b++) { + fac= (2.0*b/(float)(dlb->nr-1)) - 1.0; + for(a=0; a<bl->nr; a++, fp+=3) { + fp[0]= (2.0*a/(float)(bl->nr-1)) - 1.0; + fp[1]= fac; + fp[2]= 0.0; + } + } + dlb= dlb->next; + } + bl= bl->next; + } + } + } + } + + if(ob->parent && ob->parent->type==OB_LATTICE) { + lt= ob->parent->data; + init_latt_deform(ob->parent, ob); + need_orco= 1; + } + + if(ob->parent && ob->parent->type==OB_IKA) { + ika= ob->parent->data; + init_skel_deform(ob->parent, ob); + need_orco= 1; + } + + if(ob->parent && ob->parent->type==OB_ARMATURE) { + init_armature_deform(ob->parent, ob); + need_orco= 1; + } + + /* keypos doen? NOTITIE: pas op : orco's */ + + /* effect op text? */ + + /* boundboxclip nog doen */ + + /* polyzijvlakken: met bevellist werken */ + widfac= (cu->width-1.0); + + bl= cu->bev.first; + nu= cu->nurb.first; + while(bl) { + + if(dlbev.first) { /* anders alleen een poly */ + + dlb= dlbev.first; /* bevel lus */ + while(dlb) { + data= MEM_mallocN(3*sizeof(float)*dlb->nr*bl->nr, "init_render_curve3"); + fp= data; + + /* voor ieder punt van bevelcurve de hele poly doen */ + fp1= dlb->verts; + b= dlb->nr; + while(b--) { + + bevp= (BevPoint *)(bl+1); + a= bl->nr; + while(a--) { + + if(cu->flag & CU_3D) { + vec[0]= fp1[1]+widfac; + vec[1]= fp1[2]; + vec[2]= 0.0; + + MTC_Mat3MulVecfl(bevp->mat, vec); + + fp[0]= bevp->x+ vec[0]; + fp[1]= bevp->y+ vec[1]; + fp[2]= bevp->z+ vec[2]; + } + else { + + fp[0]= bevp->x+ (widfac+fp1[1])*bevp->sina; + fp[1]= bevp->y+ (widfac+fp1[1])*bevp->cosa; + fp[2]= bevp->z+ fp1[2]; + /* hier niet al MatMullen: polyfill moet uniform werken, ongeacht frame */ + } + fp+= 3; + bevp++; + } + fp1+=3; + } + + /* rendervertices maken */ + fp= data; + startvert= R.totvert; + nr= dlb->nr*bl->nr; + + while(nr--) { + ver= RE_findOrAddVert(R.totvert++); + + if(lt) calc_latt_deform(fp); + else if(ika) calc_skel_deform(ika, fp); + + VECCOPY(ver->co, fp); + MTC_Mat4MulVecfl(mat, ver->co); + fp+= 3; + } + + startvlak= R.totvlak; + + for(a=0; a<dlb->nr; a++) { + + frontside= (a >= dlb->nr/2); + + DL_SURFINDEX(bl->poly>0, dlb->type==DL_POLY, bl->nr, dlb->nr); + p1+= startvert; + p2+= startvert; + p3+= startvert; + p4+= startvert; + + for(; b<bl->nr; b++) { + + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= RE_findOrAddVert(p2); + vlr->v2= RE_findOrAddVert(p1); + vlr->v3= RE_findOrAddVert(p3); + vlr->v4= RE_findOrAddVert(p4); + vlr->ec= ME_V2V3+ME_V3V4; + if(a==0) vlr->ec+= ME_V1V2; + + vlr->flag= nu->flag; + vlr->lay= ob->lay; + + /* dit is niet echt wetenschappelijk: de vertices + * 2, 3 en 4 geven betere puno's dan 1 2 3: voor en achterkant anders!! + */ + + if(frontside) + vlr->len= CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n); + else + vlr->len= CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n); + + vlr->mat= matar[ nu->mat_nr ]; + + p4= p3; + p3++; + p2= p1; + p1++; + + } + + } + + /* dubbele punten maken: POLY SPLITSEN */ + if(dlb->nr==4 && cu->bevobj==0) { + split_u_renderfaces(startvlak, startvert, bl->nr, 1, bl->poly>0); + split_u_renderfaces(startvlak, startvert, bl->nr, 2, bl->poly>0); + } + /* dubbele punten maken: BEVELS SPLITSEN */ + bevp= (BevPoint *)(bl+1); + for(a=0; a<bl->nr; a++) { + if(bevp->f1) + split_v_renderfaces(startvlak, startvert, bl->nr, dlb->nr, a, bl->poly>0, + dlb->type==DL_POLY); + bevp++; + } + + /* puntnormalen */ + for(a= startvlak; a<R.totvlak; a++) { + vlr= RE_findOrAddVlak(a); + + VecAddf(vlr->v1->n, vlr->v1->n, vlr->n); + VecAddf(vlr->v3->n, vlr->v3->n, vlr->n); + VecAddf(vlr->v2->n, vlr->v2->n, vlr->n); + VecAddf(vlr->v4->n, vlr->v4->n, vlr->n); + } + for(a=startvert; a<R.totvert; a++) { + ver= RE_findOrAddVert(a); + len= Normalise(ver->n); + if(len==0.0) ver->sticky= (float *)1; + else ver->sticky= 0; + } + for(a= startvlak; a<R.totvlak; a++) { + vlr= RE_findOrAddVlak(a); + if(vlr->v1->sticky) VECCOPY(vlr->v1->n, vlr->n); + if(vlr->v2->sticky) VECCOPY(vlr->v2->n, vlr->n); + if(vlr->v3->sticky) VECCOPY(vlr->v3->n, vlr->n); + if(vlr->v4->sticky) VECCOPY(vlr->v4->n, vlr->n); + } + + dlb= dlb->next; + + MEM_freeN(data); + } + + } + bl= bl->next; + nu= nu->next; + } + + if(dlbev.first) { + freedisplist(&dlbev); + } + + if(cu->flag & CU_PATH) return; + + /* uit de displist kunnen de vulvlakken worden gehaald */ + dl= cu->disp.first; + + while(dl) { + if(dl->type==DL_INDEX3) { + + startvert= R.totvert; + data= dl->verts; + + n[0]= ob->imat[0][2]; + n[1]= ob->imat[1][2]; + n[2]= ob->imat[2][2]; + Normalise(n); + + for(a=0; a<dl->nr; a++, data+=3) { + + ver= RE_findOrAddVert(R.totvert++); + VECCOPY(ver->co, data); + MTC_Mat4MulVecfl(mat, ver->co); + + VECCOPY(ver->n, n); + } + + startvlak= R.totvlak; + index= dl->index; + for(a=0; a<dl->parts; a++, index+=3) { + + vlr= RE_findOrAddVlak(R.totvlak++); + vlr->v1= RE_findOrAddVert(startvert+index[0]); + vlr->v2= RE_findOrAddVert(startvert+index[1]); + vlr->v3= RE_findOrAddVert(startvert+index[2]); + vlr->v4= 0; + + VECCOPY(vlr->n, n); + + vlr->mface= 0; + vlr->mat= matar[ dl->col ]; + vlr->puno= 0; + vlr->flag= 0; + vlr->ec= 0; + vlr->lay= ob->lay; + } + + } + dl= dl->next; + } + + if(lt) { + end_latt_deform(); + } + + if(need_orco) { /* de domme methode: snel vervangen; rekening houden met keys! */ + + VECCOPY(size, cu->size); + + nr= R.totvert-firststartvert; + if(nr) { + if(cu->orco) { + fp= cu->orco; + while(nr--) { + ver= RE_findOrAddVert(firststartvert++); + ver->orco= fp; + fp+= 3; + } + } + else { + fp= cu->orco= MEM_mallocN(sizeof(float)*3*nr, "cu orco"); + while(nr--) { + ver= RE_findOrAddVert(firststartvert++); + ver->orco= fp; + + VECCOPY(fp, ver->co); + MTC_Mat4MulVecfl(ob->imat, fp); + + fp[0]= (fp[0]-cu->loc[0])/size[0]; + fp[1]= (fp[1]-cu->loc[1])/size[1]; + fp[2]= (fp[2]-cu->loc[2])/size[2]; + fp+= 3; + } + } + } + } +} + +static void init_render_object(Object *ob) +{ + float mat[4][4]; + + ob->flag |= OB_DONE; + + if(ob->type==OB_LAMP) + RE_add_render_lamp(ob, 1); + else if ELEM(ob->type, OB_FONT, OB_CURVE) + init_render_curve(ob); + else if(ob->type==OB_SURF) + init_render_surf(ob); + else if(ob->type==OB_MESH) + init_render_mesh(ob); + else if(ob->type==OB_MBALL) + init_render_mball(ob); + else { + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + } +} + +void RE_freeRotateBlenderScene(void) +{ + ShadBuf *shb; + Object *ob = NULL; + Mesh *me; + Curve *cu; + DispList *dl; + unsigned long *ztile; + int a, b, v; + char *ctile; + + /* VRIJGEVEN */ + + for(a=0; a<R.totlamp; a++) { + + /* for the shadow buf object integration */ + if (R.la[a]->shadowBufOb) { + RE_deleteShadowBuffer((RE_ShadowBufferHandle) R.la[a]->shadowBufOb); + } + + if(R.la[a]->shb) { + shb= R.la[a]->shb; + v= (shb->size*shb->size)/256; + ztile= shb->zbuf; + ctile= shb->cbuf; + for(b=0; b<v; b++, ztile++, ctile++) { + if(*ctile) MEM_freeN((void *) *ztile); + } + + MEM_freeN(shb->zbuf); + MEM_freeN(shb->cbuf); + MEM_freeN(R.la[a]->shb); + } + if(R.la[a]->org) MEM_freeN(R.la[a]->org); + MEM_freeN(R.la[a]); + } + a=0; + while(R.blove[a]) { + MEM_freeN(R.blove[a]); + R.blove[a]=0; + a++; + } + a=0; + while(R.blovl[a]) { + MEM_freeN(R.blovl[a]); + R.blovl[a]=0; + a++; + } + a=0; + while(R.bloha[a]) { + MEM_freeN(R.bloha[a]); + R.bloha[a]=0; + a++; + } + + /* orco vrijgeven. ALle ob's aflopen ivm dupli's en sets */ + ob= G.main->object.first; + while(ob) { + + if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { + cu= ob->data; + if(cu->orco) { + MEM_freeN(cu->orco); + cu->orco= 0; + } + } + else if(ob->type==OB_MESH) { + me= ob->data; + if(me->orco) { + MEM_freeN(me->orco); + me->orco= 0; + } + if (rendermesh_uses_displist(me) && (me->subdiv!=me->subdivr)){ + makeDispList(ob); + } + } + else if(ob->type==OB_MBALL) { + if(ob->disp.first && ob->disp.first!=ob->disp.last) { + dl= ob->disp.first; + BLI_remlink(&ob->disp, dl); + freedisplist(&ob->disp); + BLI_addtail(&ob->disp, dl); + } + } + ob= ob->id.next; + } + + end_render_textures(); + end_render_materials(); + + R.totvlak=R.totvert=R.totlamp=R.tothalo= 0; +} + + +extern int slurph_opt; /* key.c */ +extern ListBase duplilist; +void RE_rotateBlenderScene(void) +{ + Base *base; + Object *ob, *obd; + Scene *sce; + unsigned int lay; + float mat[4][4]; + + if(G.scene->camera==0) return; + + O.dxwin[0]= 0.5/(float)R.r.xsch; + O.dywin[1]= 0.5/(float)R.r.ysch; + + slurph_opt= 0; + + R.totvlak=R.totvert=R.totlamp=R.tothalo= 0; + + do_all_ipos(); + BPY_do_all_scripts(SCRIPT_FRAMECHANGED); + do_all_keys(); +#ifdef __NLA + do_all_actions(); +#endif + do_all_ikas(); + test_all_displists(); + + /* niet erg nette calc_ipo en where_is forceer */ + ob= G.main->object.first; + while(ob) { + ob->ctime= -123.456; + ob= ob->id.next; + } + + if(G.special1 & G_HOLO) RE_holoview(); + + /* ivm met optimale berekening track / lattices / etc: extra where_is_ob */ + + base= G.scene->base.first; + while(base) { + clear_object_constraint_status(base->object); + if (base->object->type==OB_ARMATURE) + where_is_armature (base->object); + else + + where_is_object(base->object); + + if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; + else base= base->next; + } + + MTC_Mat4CpyMat4(R.viewinv, G.scene->camera->obmat); + MTC_Mat4Ortho(R.viewinv); + MTC_Mat4Invert(R.viewmat, R.viewinv); + + /* is niet netjes: nu is de viewinv ongelijk aan de viewmat. voor Texco's enzo. Beter doen! */ + if(R.r.mode & R_ORTHO) R.viewmat[3][2]*= 100.0; + + RE_setwindowclip(1,-1); /* geen jit:(-1) */ + + /* imatflags wissen */ + ob= G.main->object.first; + while(ob) { + ob->flag &= ~OB_DO_IMAT; + ob= ob->id.next; + } + + init_render_world(); /* moet eerst ivm ambient */ + init_render_textures(); + init_render_materials(); + + /* MAAK RENDERDATA */ + + /* elk object maar 1 x renderen */ + ob= G.main->object.first; + while(ob) { + ob->flag &= ~OB_DONE; + ob= ob->id.next; + } + + + /* layers: in foreground current 3D window renderen */ + lay= G.scene->lay; + sce= G.scene; + + base= G.scene->base.first; + while(base) { + + ob= base->object; + + if(ob->flag & OB_DONE); + else { + where_is_object(ob); + + if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & G.scene->lay)) ) { + + if(ob->transflag & OB_DUPLI) { + /* exception: mballs! */ + make_duplilist(sce, ob); + if(ob->type==OB_MBALL) { + init_render_object(ob); + } + else { + obd= duplilist.first; + if(obd) { + /* exception, in background render it doesnt make the displist */ + if ELEM(obd->type, OB_CURVE, OB_SURF) { + Curve *cu; + + cu= obd->data; + if(cu->disp.first==0) { + obd->flag &= ~OB_FROMDUPLI; + makeDispList(obd); + obd->flag |= OB_FROMDUPLI; + } + } + } + + obd= duplilist.first; + while(obd) { + if(obd->type!=OB_MBALL) init_render_object(obd); + obd= obd->id.next; + } + } + free_duplilist(); + } + else init_render_object(ob); + + } + else { + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + } + + ob->flag &= ~OB_DO_IMAT; + } + if(MISC_test_break()) break; + + if(base->next==0 && G.scene->set && base==G.scene->base.last) { + base= G.scene->set->base.first; + sce= G.scene->set; + } + else base= base->next; + + } + + /* imat objecten */ + ob= G.main->object.first; + while(ob) { + if(ob->flag & OB_DO_IMAT) { + + ob->flag &= ~OB_DO_IMAT; + + MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); + MTC_Mat4Invert(ob->imat, mat); + } + ob= ob->id.next; + } + + sort_halos(); + + if(R.wrld.mode & WO_STARS) RE_make_stars(NULL, NULL, NULL); + + slurph_opt= 1; + + if(MISC_test_break()) return; + + /* if(R.totlamp==0) defaultlamp(); */ + + set_normalflags(); +} + |