diff options
Diffstat (limited to 'source/blender/render/intern')
-rw-r--r-- | source/blender/render/intern/include/renderdatabase.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 900 | ||||
-rw-r--r-- | source/blender/render/intern/source/renderdatabase.c | 147 | ||||
-rw-r--r-- | source/blender/render/intern/source/texture.c | 8 |
4 files changed, 1017 insertions, 40 deletions
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index 75aea05fee2..dc70ade25ae 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -84,6 +84,8 @@ struct VertRen *RE_findOrAddVert(struct Render *re, int nr); struct HaloRen *RE_findOrAddHalo(struct Render *re, int nr); struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize, float vectsize, int seed); +struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1, + float *orco, float *uvco, float hasize, float vectsize, int seed); void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa); float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index ca9c7652441..87853be6234 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -54,9 +54,11 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_meta_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_object_fluidsim.h" +#include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "DNA_view3d_types.h" @@ -83,8 +85,10 @@ #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_particle.h" #include "BKE_scene.h" #include "BKE_subsurf.h" #include "BKE_texture.h" @@ -125,6 +129,7 @@ /* ------------------------------------------------------------------------- */ static short test_for_displace(Render *re, Object *ob); static void do_displacement(Render *re, Object *ob, int startface, int numface, int startvert, int numvert ); +static int vlakren_customdata_layer_num(int n, int active); /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */ /* or for checking vertex normal flips */ @@ -1217,26 +1222,33 @@ static void render_particle_system(Render *re, Object *ob, Object *par, PartEff if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore... } - /* ------------------------------------------------------------------------- */ /* future thread problem... */ -static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *vec, float *vec1, float ctime, int first) +static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *uvco, int totuv, + float *vec, float *vec1, float ctime, int first, int line, + int adapt, float adapt_angle, float adapt_pix, int override_uv) { static VertRen *v1= NULL, *v2= NULL; VlakRen *vlr; float nor[3], cross[3], w, dx, dy, width; - int flag; + static float anor[3], avec[3]; + int flag, i; + static int second=0; VecSubf(nor, vec, vec1); Normalize(nor); // nor needed as tangent Crossf(cross, vec, nor); - + + if(ma->mode&MA_STR_B_UNITS) + Normalize(cross); + /* turn cross in pixelsize */ w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; dx= re->winx*cross[0]*re->winmat[0][0]/w; dy= re->winy*cross[1]*re->winmat[1][1]/w; w= sqrt(dx*dx + dy*dy); + if(w!=0.0f) { float fac; if(ma->strand_ease!=0.0f) { @@ -1246,8 +1258,19 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * fac= pow(ctime, 1.0/(1.0f-ma->strand_ease)); } else fac= ctime; - - width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end)/w; + + width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end); + + /* use actual Blender units for strand width and fall back to min 1px */ + if(ma->mode & MA_STR_B_UNITS){ + if(width < 1.0f/w) + width= 1.0f/w; + /*cross is the radius of the strand so we want it to be half of full width */ + VecMulf(cross,0.5); + } + else + width/=w; + VecMulf(cross, width); } else width= 1.0f; @@ -1261,8 +1284,75 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * if(ma->strand_sta==1.0f) flag |= R_STRAND; - /* first two vertices */ - if(first) { + /* single face line */ + if(line) { + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->flag= flag; + vlr->ob= ob; + vlr->v1= RE_findOrAddVert(re, re->totvert++); + vlr->v2= RE_findOrAddVert(re, re->totvert++); + vlr->v3= RE_findOrAddVert(re, re->totvert++); + vlr->v4= RE_findOrAddVert(re, re->totvert++); + + VECCOPY(vlr->v1->co, vec); + VecAddf(vlr->v1->co, vlr->v1->co, cross); + VECCOPY(vlr->v1->n, nor); + vlr->v1->orco= orco; + vlr->v1->accum= -1.0f; // accum abuse for strand texco + + VECCOPY(vlr->v2->co, vec); + VecSubf(vlr->v2->co, vlr->v2->co, cross); + VECCOPY(vlr->v2->n, nor); + vlr->v2->orco= orco; + vlr->v2->accum= vlr->v1->accum; + + VECCOPY(vlr->v4->co, vec1); + VecAddf(vlr->v4->co, vlr->v4->co, cross); + VECCOPY(vlr->v4->n, nor); + vlr->v4->orco= orco; + vlr->v4->accum= 1.0f; // accum abuse for strand texco + + VECCOPY(vlr->v3->co, vec1); + VecSubf(vlr->v3->co, vlr->v3->co, cross); + VECCOPY(vlr->v3->n, nor); + vlr->v3->orco= orco; + vlr->v3->accum= vlr->v4->accum; + + CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + + vlr->mat= ma; + vlr->ec= ME_V2V3; + vlr->lay= ob->lay; + + if(uvco){ + for(i=0; i<totuv; i++){ + MTFace *mtf; + mtf=RE_vlakren_get_tface(re,vlr,i,NULL,1); + mtf->uv[0][0]=mtf->uv[1][0]= + mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0]; + mtf->uv[0][1]=mtf->uv[1][1]= + mtf->uv[2][1]=mtf->uv[3][1]=(uvco+2*i)[1]; + } + if(override_uv>=0){ + MTFace *mtf; + mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0); + + mtf->uv[0][0]=mtf->uv[3][0]=0.0f; + mtf->uv[1][0]=mtf->uv[2][0]=1.0f; + + mtf->uv[0][1]=mtf->uv[1][1]=0.0f; + mtf->uv[2][1]=mtf->uv[3][1]=1.0f; + } + } + } + /* first two vertices of a strand */ + else if(first) { + if(adapt){ + VECCOPY(anor, nor); + VECCOPY(avec, vec); + second=1; + } + v1= RE_findOrAddVert(re, re->totvert++); v2= RE_findOrAddVert(re, re->totvert++); @@ -1278,19 +1368,58 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * v2->orco= orco; v2->accum= v1->accum; } + /* more vertices & faces to strand */ else { - - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->flag= flag; - vlr->ob= ob; - vlr->v1= v1; - vlr->v2= v2; - vlr->v3= RE_findOrAddVert(re, re->totvert++); - vlr->v4= RE_findOrAddVert(re, re->totvert++); - - v1= vlr->v4; // cycle - v2= vlr->v3; // cycle - + if(adapt==0 || second){ + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->flag= flag; + vlr->ob= ob; + vlr->v1= v1; + vlr->v2= v2; + vlr->v3= RE_findOrAddVert(re, re->totvert++); + vlr->v4= RE_findOrAddVert(re, re->totvert++); + + v1= vlr->v4; // cycle + v2= vlr->v3; // cycle + + + if(adapt){ + second=0; + VECCOPY(anor,nor); + VECCOPY(avec,vec); + } + + } + else if(adapt){ + float dvec[3],pvec[3]; + VecSubf(dvec,avec,vec); + Projf(pvec,dvec,vec); + VecSubf(dvec,dvec,pvec); + + w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; + dx= re->winx*dvec[0]*re->winmat[0][0]/w; + dy= re->winy*dvec[1]*re->winmat[1][1]/w; + w= sqrt(dx*dx + dy*dy); + if(Inpf(anor,nor)<adapt_angle && w>adapt_pix){ + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->flag= flag; + vlr->ob= ob; + vlr->v1= v1; + vlr->v2= v2; + vlr->v3= RE_findOrAddVert(re, re->totvert++); + vlr->v4= RE_findOrAddVert(re, re->totvert++); + + v1= vlr->v4; // cycle + v2= vlr->v3; // cycle + + VECCOPY(anor,nor); + VECCOPY(avec,vec); + } + else{ + vlr= RE_findOrAddVlak(re, re->totvlak-1); + } + } + VECCOPY(vlr->v4->co, vec); VecAddf(vlr->v4->co, vlr->v4->co, cross); VECCOPY(vlr->v4->n, nor); @@ -1308,7 +1437,660 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * vlr->mat= ma; vlr->ec= ME_V2V3; vlr->lay= ob->lay; + + if(uvco){ + for(i=0; i<totuv; i++){ + MTFace *mtf; + mtf=RE_vlakren_get_tface(re,vlr,i,NULL,1); + mtf->uv[0][0]=mtf->uv[1][0]= + mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0]; + mtf->uv[0][1]=mtf->uv[1][1]= + mtf->uv[2][1]=mtf->uv[3][1]=(uvco+2*i)[1]; + } + if(override_uv>=0){ + MTFace *mtf; + mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0); + + mtf->uv[0][0]=mtf->uv[3][0]=0.0f; + mtf->uv[1][0]=mtf->uv[2][0]=1.0f; + + mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f; + mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f; + } + } + } +} + +static void static_particle_wire(Render *re, Object *ob, Material *ma, float *vec, float *vec1, int first, int line) +{ + VlakRen *vlr; + static VertRen *v1; + + if(line) { + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->ob= ob; + vlr->v1= RE_findOrAddVert(re, re->totvert++); + vlr->v2= RE_findOrAddVert(re, re->totvert++); + vlr->v3= vlr->v2; + vlr->v4= NULL; + + VECCOPY(vlr->v1->co, vec); + VECCOPY(vlr->v2->co, vec1); + + VecSubf(vlr->n, vec, vec1); + Normalize(vlr->n); + VECCOPY(vlr->v1->n, vlr->n); + VECCOPY(vlr->v2->n, vlr->n); + + vlr->mat= ma; + vlr->ec= ME_V1V2; + vlr->lay= ob->lay; + + } + else if(first) { + v1= RE_findOrAddVert(re, re->totvert++); + VECCOPY(v1->co, vec); + } + else { + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->ob= ob; + vlr->v1= v1; + vlr->v2= RE_findOrAddVert(re, re->totvert++); + vlr->v3= vlr->v2; + vlr->v4= NULL; + + v1= vlr->v2; // cycle + VECCOPY(v1->co, vec); + + VecSubf(vlr->n, vec, vec1); + Normalize(vlr->n); + VECCOPY(v1->n, vlr->n); + + vlr->mat= ma; + vlr->ec= ME_V1V2; + vlr->lay= ob->lay; + } + +} +static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align, + int lock, int p, int totpart, short uv_split, short anim, short split_offset, float random, float pa_time, float offset[2], int uv[3]) +{ + VlakRen *vlr; + MTFace *mtf; + float xvec[3]={1.0f,0.0f,0.0f}, yvec[3]={0.0f,1.0f,0.0f}, zvec[3]; + float onevec[3]={0.0f,0.0f,0.0f}, tvec[3],tvec2[3], bb_center[3]; + float uvx=0.0f, uvy=0.0f, uvdx=1.0f, uvdy=1.0f, time=0.0f; + + if(align<PART_BB_VIEW) + onevec[align]=1.0f; + + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->ob= ob; + vlr->v1= RE_findOrAddVert(re, re->totvert++); + vlr->v2= RE_findOrAddVert(re, re->totvert++); + vlr->v3= RE_findOrAddVert(re, re->totvert++); + vlr->v4= RE_findOrAddVert(re, re->totvert++); + + if(lock && align==PART_BB_VIEW){ + VECCOPY(xvec,bb_ob->obmat[0]); + Normalize(xvec); + VECCOPY(yvec,bb_ob->obmat[1]); + Normalize(yvec); + VECCOPY(zvec,bb_ob->obmat[2]); + Normalize(zvec); + } + else if(align==PART_BB_VEL){ + float temp[3]; + VECCOPY(temp,vel); + Normalize(temp); + VECSUB(zvec,bb_ob->obmat[3],vec); + if(lock){ + float fac=-Inpf(zvec,temp); + VECADDFAC(zvec,zvec,temp,fac); + } + Normalize(zvec); + Crossf(xvec,temp,zvec); + Normalize(xvec); + Crossf(yvec,zvec,xvec); + } + else{ + VECSUB(zvec,bb_ob->obmat[3],vec); + if(lock) + zvec[align]=0.0f; + Normalize(zvec); + + if(align<PART_BB_VIEW) + Crossf(xvec,onevec,zvec); + else + Crossf(xvec,bb_ob->obmat[1],zvec); + Normalize(xvec); + Crossf(yvec,zvec,xvec); + } + + VECCOPY(tvec,xvec); + VECCOPY(tvec2,yvec); + + VecMulf(xvec,cos(tilt*(float)M_PI)); + VecMulf(tvec2,sin(tilt*(float)M_PI)); + VECADD(xvec,xvec,tvec2); + + VecMulf(yvec,cos(tilt*(float)M_PI)); + VecMulf(tvec,-sin(tilt*(float)M_PI)); + VECADD(yvec,yvec,tvec); + + VecMulf(xvec,size); + VecMulf(yvec,size); + + VECADDFAC(bb_center,vec,xvec,offset[0]); + VECADDFAC(bb_center,bb_center,yvec,offset[1]); + + VECADD(vlr->v1->co,bb_center,xvec); + VECADD(vlr->v1->co,vlr->v1->co,yvec); + MTC_Mat4MulVecfl(re->viewmat,vlr->v1->co); + + VECSUB(vlr->v2->co,bb_center,xvec); + VECADD(vlr->v2->co,vlr->v2->co,yvec); + MTC_Mat4MulVecfl(re->viewmat,vlr->v2->co); + + VECSUB(vlr->v3->co,bb_center,xvec); + VECSUB(vlr->v3->co,vlr->v3->co,yvec); + MTC_Mat4MulVecfl(re->viewmat,vlr->v3->co); + + VECADD(vlr->v4->co,bb_center,xvec); + VECSUB(vlr->v4->co,vlr->v4->co,yvec); + MTC_Mat4MulVecfl(re->viewmat,vlr->v4->co); + + CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n); + VECCOPY(vlr->v1->n,vlr->n); + VECCOPY(vlr->v2->n,vlr->n); + VECCOPY(vlr->v3->n,vlr->n); + VECCOPY(vlr->v4->n,vlr->n); + + vlr->mat= ma; + vlr->ec= ME_V2V3; + vlr->lay= ob->lay; + + if(uv_split>1){ + uvdx=uvdy=1.0f/(float)uv_split; + if(anim==PART_BB_ANIM_TIME){ + if(split_offset==PART_BB_OFF_NONE) + time=pa_time; + else if(split_offset==PART_BB_OFF_LINEAR) + time=(float)fmod(pa_time+(float)p/(float)(uv_split*uv_split),1.0f); + else /* split_offset==PART_BB_OFF_RANDOM */ + time=(float)fmod(pa_time+random,1.0f); + + } + else if(anim==PART_BB_ANIM_ANGLE){ + if(align==PART_BB_VIEW){ + time=(float)fmod((tilt+1.0f)/2.0f,1.0); + } + else{ + float axis1[3]={0.0f,0.0f,0.0f}; + float axis2[3]={0.0f,0.0f,0.0f}; + axis1[(align+1)%3]=1.0f; + axis2[(align+2)%3]=1.0f; + if(lock==0){ + zvec[align]=0.0f; + Normalize(zvec); + } + time=saacos(Inpf(zvec,axis1))/(float)M_PI; + if(Inpf(zvec,axis2)<0.0f) + time=1.0f-time/2.0f; + else + time=time/2.0f; + } + if(split_offset==PART_BB_OFF_LINEAR) + time=(float)fmod(pa_time+(float)p/(float)(uv_split*uv_split),1.0f); + else if(split_offset==PART_BB_OFF_RANDOM) + time=(float)fmod(pa_time+random,1.0f); + } + else{ + if(split_offset==PART_BB_OFF_NONE) + time=0.0f; + else if(split_offset==PART_BB_OFF_LINEAR) + time=(float)fmod((float)p/(float)(uv_split*uv_split),1.0f); + else /* split_offset==PART_BB_OFF_RANDOM */ + time=random; + } + uvx=uvdx*floor((float)(uv_split*uv_split)*(float)fmod((double)time,(double)uvdx)); + uvy=uvdy*floor((1.0f-time)*(float)uv_split); + if(fmod(time,1.0f/uv_split)==0.0f) + uvy-=uvdy; + } + + /* normal UVs */ + if(uv[0]>=0){ + mtf=RE_vlakren_get_tface(re,vlr,uv[0],NULL,1); + mtf->uv[0][0]=1.0f; + mtf->uv[0][1]=1.0f; + mtf->uv[1][0]=0.0f; + mtf->uv[1][1]=1.0f; + mtf->uv[2][0]=0.0f; + mtf->uv[2][1]=0.0f; + mtf->uv[3][0]=1.0f; + mtf->uv[3][1]=0.0f; + } + + /* time-index UVs */ + if(uv[1]>=0){ + mtf=RE_vlakren_get_tface(re,vlr,uv[1],NULL,1); + mtf->uv[0][0]=mtf->uv[1][0]=mtf->uv[2][0]=mtf->uv[3][0]=pa_time; + mtf->uv[0][1]=mtf->uv[1][1]=mtf->uv[2][1]=mtf->uv[3][1]=(float)p/(float)totpart; + } + + /* split UVs */ + if(uv_split>1 && uv[2]>=0){ + mtf=RE_vlakren_get_tface(re,vlr,uv[2],NULL,1); + mtf->uv[0][0]=uvx+uvdx; + mtf->uv[0][1]=uvy+uvdy; + mtf->uv[1][0]=uvx; + mtf->uv[1][1]=uvy+uvdy; + mtf->uv[2][0]=uvx; + mtf->uv[2][1]=uvy; + mtf->uv[3][0]=uvx+uvdx; + mtf->uv[3][1]=uvy; + } +} +static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line, + float time, float *loc, float *loc1, float *orco, int totuv, float *uvco, + float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix) +{ + HaloRen *har=0; + if(path){ + if(ma->mode&MA_WIRE) + static_particle_wire(re, ob, ma, loc, loc1, first, line); + else if(ma->mode & MA_HALO){ + har= RE_inithalo_particle(re, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed); + if(har) har->lay= ob->lay; + } + else + static_particle_strand(re, ob, ma, orco, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv); + } + else{ + har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed); + if(har) har->lay= ob->lay; + } +} +static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *psys) +{ + Object *tob=0, *bb_ob=re->scene->camera; + Material *ma=0; + CustomDataLayer *layer; + MTFace *mtface; + ParticleSystemModifierData *psmd; + ParticleSystem *tpsys=0; + ParticleSettings *part, *tpart=0; + ParticleData *pars, *pa=0,*tpa=0; + ParticleKey *states=0; + ParticleKey state; + ParticleCacheKey *cache=0; + float loc[3],loc1[3],loc0[3],vel[3],imat[4][4], time; + float *orco=0,*uvco=0; + float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); + float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random; + int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1; + int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; + int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}; + char **uv_name=0; + +/* 1. check that everything is ok & updated */ + if(psys==NULL) + return 0; + + part=psys->part; + pars=psys->particles; + + if(part==NULL || pars==NULL || (psys->flag & PSYS_ENABLED)==0) + return 0; + + if(part->draw_as==PART_DRAW_OB || part->draw_as==PART_DRAW_GR || part->draw_as==PART_DRAW_NOT) + return 1; + +/* 2. start initialising things */ + if(part->phystype==PART_PHYS_KEYED){ + if(psys->flag & PSYS_FIRST_KEYED) + psys_count_keyed_targets(ob,psys); + else + return 1; + } + + psys->flag|=PSYS_DRAWING; + + BLI_srandom(psys->seed); + + psmd= psys_get_modifier(ob,psys); + + ma= give_render_material(re, ob, part->omat); + + if(part->bb_ob) + bb_ob=part->bb_ob; + + if(ma->ipo){ + calc_ipo(ma->ipo, cfra); + execute_ipo((ID *)ma, ma->ipo); + } + + RE_vlakren_set_customdata_names(re, &psmd->dm->faceData); + totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE); + + if(ma->texco & TEXCO_UV && totuv) + uvco = MEM_callocN(totuv*2*sizeof(float),"particle_uvs"); + + if(part->draw_as==PART_DRAW_BB){ + int first_uv=CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE); + + uv[0]=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,psys->bb_uvname[0]); + if(uv[0]<0) + uv[0]=CustomData_get_active_layer_index(&psmd->dm->faceData,CD_MTFACE); + + uv[1]=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,psys->bb_uvname[1]); + //if(uv[1]<0) + // uv[1]=CustomData_get_active_layer_index(&psmd->dm->faceData,CD_MTFACE); + + uv[2]=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,psys->bb_uvname[2]); + //if(uv[2]<0) + // uv[2]=CustomData_get_active_layer_index(&psmd->dm->faceData,CD_MTFACE); + + if(first_uv>=0){ + uv[0]-=first_uv; + uv[1]-=first_uv; + uv[2]-=first_uv; + } } + + if(part->flag&PART_ABS_TIME && part->ipo){ + calc_ipo(part->ipo, cfra); + execute_ipo((ID *)part, part->ipo); + } + + if(part->flag&PART_GLOB_TIME) + cfra=bsystem_time(0,(float)CFRA,0.0); + + if(part->type==PART_REACTOR){ + psys_get_reactor_target(ob, psys, &tob, &tpsys); + if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ + psmd=psys_get_modifier(tob,tpsys); + tpart=tpsys->part; + } + } + + hasize = ma->hasize; + seed = ma->seed1; + + re->flag |= R_HALO; + + Mat4Invert(imat,ob->obmat); + + totvlako= re->totvlak; + totverto= re->totvert; + + totpart=psys->totpart; + + mesh_get_texspace(ob->data, loc_tex, NULL, size_tex); + + if(psys->pathcache){ + path_possible=1; + keys_possible=1; + } + if(part->draw_as==PART_DRAW_PATH){ + if(path_possible){ + path_nbr=(int)pow(2.0,(double) part->ren_step); + //if(part->phystype==PART_PHYS_KEYED && (psys->flag&PSYS_BAKED)==0) + // path_nbr*=psys->totkeyed; + + if(path_nbr){ + if((ma->mode & (MA_HALO|MA_WIRE))==0){ + orco= MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos"); + if (!re->orco_hash) + re->orco_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + BLI_ghash_insert(re->orco_hash, psys, orco); + } + path=1; + } + + if(part->draw&PART_DRAW_REN_ADAPT){ + adapt=1; + adapt_pix=(float)part->adapt_pix; + adapt_angle=cos((float)part->adapt_angle*(float)(M_PI/180.0)); + } + + } + } + else if(keys_possible && part->draw&PART_DRAW_KEYS){ + path_nbr=part->keys_step; + if(path_nbr==0) + baked_keys=1; + } + + if(orco==0){ + orco=MEM_mallocN(3*sizeof(float),"particle orco"); + orco1=1; + } + + if(path_nbr==0) + psys->lattice=psys_get_lattice(ob,psys); + +/* 3. start creating renderable things */ + for(a=0,pa=pars; a<totpart+totchild; a++, pa++) { + random = BLI_frand(); + if(a<totpart){ + if(pa->flag & PARS_UNEXIST) continue; + + pa_time=(cfra-pa->time)/pa->lifetime; + if((part->flag&PART_ABS_TIME)==0){ + if(ma->ipo){ + /* correction for lifetime */ + calc_ipo(ma->ipo, 100.0f*pa_time); + execute_ipo((ID *)ma, ma->ipo); + } + if(part->ipo){ + /* correction for lifetime */ + calc_ipo(part->ipo, 100.0f*pa_time); + execute_ipo((ID *)part, part->ipo); + } + } + + hasize = ma->hasize; + + /* get orco */ + if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ + tpa=tpsys->particles+pa->num; + psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num, -1,tpa->fuv,tpa->foffset,orco,0,0,0); + } + else + psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,orco,0,0,0); + + if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ + layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); + for(i=0; i<totuv; i++){ + int n; + MFace *mface=psmd->dm->getFaceData(psmd->dm,pa->num,CD_MFACE); + + mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); + mtface+=pa->num; + + n= vlakren_customdata_layer_num(i, layer->active); + + psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n); + } + override_uv=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,ma->strand_uvname)- + CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE); + } + + pa_size=pa->size; + + r_tilt=1.0f+pa->r_ave[0]; + + if(path_nbr){ + cache = psys->pathcache[a]; + max_k = (int)cache->steps; + } + + if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue; + } + else{ + ChildParticle *cpa= psys->child+a-totpart; + pa_time=psys_get_child_time(psys, a-totpart, cfra); + + if((part->flag&PART_ABS_TIME)==0){ + if(ma->ipo){ + /* correction for lifetime */ + calc_ipo(ma->ipo, 100.0f*pa_time); + execute_ipo((ID *)ma, ma->ipo); + } + if(part->ipo){ + /* correction for lifetime */ + calc_ipo(part->ipo, 100.0f*pa_time); + execute_ipo((ID *)part, part->ipo); + } + } + + pa_size=psys_get_child_size(psys, a-totpart, cfra, &pa_time); + + r_tilt=2.0f*cpa->rand[2]; + + if(uvco){ + layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); + + if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ + for(i=0; i<totuv; i++){ + if(part->childtype==PART_CHILD_FACES){ + int n; + MFace *mface=psmd->dm->getFaceData(psmd->dm,cpa->num,CD_MFACE); + + mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); + mtface+=cpa->num; + + n= vlakren_customdata_layer_num(i, layer->active); + + psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*n); + } + else{ + uvco[2*i]=uvco[2*i+1]=0.0f; + } + } + } + else if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ + for(i=0; i<totuv; i++){ + ParticleData *parent = psys->particles+cpa->parent; + int n; + MFace *mface=psmd->dm->getFaceData(psmd->dm,parent->num,CD_MFACE); + + mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); + mtface+=parent->num; + + n= vlakren_customdata_layer_num(i, layer->active); + + psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*n); + } + } + } + + if(path_nbr){ + cache = psys->childcache[a-totpart]; + max_k = (int)cache->steps; + } + } + + if(orco) { + orco[0] = (orco[0]-loc_tex[0])/size_tex[0]; + orco[1] = (orco[1]-loc_tex[1])/size_tex[1]; + orco[2] = (orco[2]-loc_tex[2])/size_tex[2]; + } + + for(k=0; k<=path_nbr; k++){ + if(path_nbr){ + time=(float)k/(float)path_nbr; + if(k<=max_k){ + //bti->convert_bake_key(bsys,cache+k,0,(void*)&state); + //copy_particle_key(&state,cache+k,0); + VECCOPY(state.co,(cache+k)->co); + VECCOPY(state.vel,(cache+k)->vel); + } + else + continue; + } + else{ + time=0.0f; + state.time=cfra; + if(psys_get_particle_state(ob,psys,a,&state,0)==0) + continue; + } + + VECCOPY(loc,state.co); + if(part->draw_as!=PART_DRAW_BB) + MTC_Mat4MulVecfl(re->viewmat,loc); + + if(part->draw_as==PART_DRAW_LINE){ + VECCOPY(vel,state.vel); + //VECADD(vel,vel,state.co); + MTC_Mat4Mul3Vecfl(re->viewmat,vel); + //VECSUB(vel,vel,loc); + Normalize(vel); + if(part->draw & PART_DRAW_VEL_LENGTH) + VecMulf(vel,VecLength(state.vel)); + VECADDFAC(loc0,loc,vel,-part->draw_line[0]); + VECADDFAC(loc1,loc,vel,part->draw_line[1]); + + render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1, + orco,totuv,uvco,hasize,seed,override_uv,0,0,0); + } + else if(part->draw_as==PART_DRAW_BB){ + VECCOPY(vel,state.vel); + //MTC_Mat4Mul3Vecfl(re->viewmat,vel); + particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt), + part->bb_align,part->draw&PART_DRAW_BB_LOCK, + a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv); + } + else{ + if(k==1){ + VECSUB(loc0,loc1,loc); + VECADD(loc0,loc1,loc0); + render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0, + orco,totuv,uvco,hasize,seed,override_uv, + adapt,adapt_angle,adapt_pix); + } + + if(path_nbr==0 || k) + render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1, + orco,totuv,uvco,hasize,seed,override_uv, + adapt,adapt_angle,adapt_pix); + + VECCOPY(loc1,loc); + } + } + + if(orco1==0) + orco+=3; + } + +/* 4. clean up */ + if(ma) do_mat_ipo(ma); + + if(orco1) + MEM_freeN(orco); + + if(uvco) + MEM_freeN(uvco); + + if(uv_name) + MEM_freeN(uv_name); + + if(states) + MEM_freeN(states); + + psys->flag &= ~PSYS_DRAWING; + + if(psys->lattice){ + end_latt_deform(); + psys->lattice=0; + } + + if(path && (ma->mode & MA_TANGENT_STR)==0) + calc_vertexnormals(re, totverto, totvlako, 0); + + return 1; } static void render_static_particle_system(Render *re, Object *ob, PartEff *paf) @@ -1463,7 +2245,7 @@ static void render_static_particle_system(Render *re, Object *ob, PartEff *paf) if(ctime + paf->staticstep < mtime) strandco= (ctime-pa->time)/(mtime-pa->time); - static_particle_strand(re, ob, ma, orco, vec, vec1, strandco, first); + static_particle_strand(re, ob, ma, orco, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1); } } @@ -2905,26 +3687,55 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i static double lasttime= 0.0; double time; float mat[4][4]; - int startface, startvert; + int startface, startvert, allow_render=1; startface=re->totvlak; startvert=re->totvert; ob->flag |= OB_DONE; - if(ob->type==OB_LAMP) - add_render_lamp(re, ob); - else if ELEM(ob->type, OB_FONT, OB_CURVE) - init_render_curve(re, ob, only_verts); - else if(ob->type==OB_SURF) - init_render_surf(re, ob); - else if(ob->type==OB_MESH) - init_render_mesh(re, ob, par, only_verts); - else if(ob->type==OB_MBALL) - init_render_mball(re, ob); - else { - MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); - MTC_Mat4Invert(ob->imat, mat); + /* the emitter has to be processed first (render levels of modifiers) */ + /* so here we only check if the emitter should be rendered */ + if(ob->particlesystem.first) { + ParticleSystem *psys = ob->particlesystem.first; + int showe = 0; + for(; psys; psys=psys->next) + showe += psys->part->draw & PART_DRAW_EMITTER; + + /* if no psys has "show emitter" selected don't render emitter */ + if(showe==0) allow_render = 0; + } + + if(allow_render) { + if(ob->type==OB_LAMP) + add_render_lamp(re, ob); + else if ELEM(ob->type, OB_FONT, OB_CURVE) + init_render_curve(re, ob, only_verts); + else if(ob->type==OB_SURF) + init_render_surf(re, ob); + else if(ob->type==OB_MESH) + init_render_mesh(re, ob, par, only_verts); + else if(ob->type==OB_MBALL) + init_render_mball(re, ob); + else { + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); + } + } + + if(ob->particlesystem.first) { + ParticleSystem *psys = ob->particlesystem.first; + DerivedMesh *dm = 0; + + /* the emitter mesh wasn't rendered so the modifier stack wasn't evaluated with render settings */ + if(allow_render==0 && ob->type==OB_MESH) + dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); + + for(; psys; psys=psys->next) + render_new_particle_system(re, ob, psys); + + if(dm) + dm->release(dm); } /* generic post process here */ @@ -3349,6 +4160,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) #endif /* disable yafray */ } else if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { + int pdup=0; if(ob->transflag & OB_DUPLI) { /* exception: mballs! */ @@ -3368,6 +4180,20 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) if(paf->flag & PAF_ANIMATED) build_particle_system(ob); } } + if(ob->transflag & OB_DUPLIPARTS){ + if(ob->particlesystem.first){ + ParticleSystem *psys = ob->particlesystem.first; + ParticleSettings *part; + + for(; psys; psys=psys->next){ + part=psys->part; + + if((part->draw_as==PART_DRAW_OB && part->dup_ob) || (part->draw_as==PART_DRAW_GR && part->dup_group)) + if(part->draw & PART_DRAW_EMITTER) + pdup++; + } + } + } if(ob->type==OB_MBALL) { init_render_object(re, ob, NULL, 0, 0); @@ -3445,6 +4271,9 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) #endif /* disable yafray */ } + /* override not showing object when duplis are used with particles */ + if(pdup) + init_render_object(re, ob, NULL, 0, 0); } if(re->test_break()) break; @@ -3613,7 +4442,6 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) else { init_render_object(re, ob, NULL, 0, 1); } - } if(re->test_break()) break; } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 6d9f0e4eb01..9dc337c1dc4 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -71,6 +71,7 @@ #include "BKE_customdata.h" #include "BKE_texture.h" +#include "BKE_DerivedMesh.h" #include "RE_render_ext.h" /* externtex */ @@ -723,6 +724,152 @@ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1, return har; } +HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma, float *vec, float *vec1, + float *orco, float *uvco, float hasize, float vectsize, int seed) +{ + HaloRen *har; + MTex *mtex; + float tin, tr, tg, tb, ta; + float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3]; + int i; + + if(hasize==0.0) return NULL; + + projectverto(vec, re->winmat, hoco); + if(hoco[3]==0.0) return NULL; + if(vec1) { + projectverto(vec1, re->winmat, hoco1); + if(hoco1[3]==0.0) return NULL; + } + + har= RE_findOrAddHalo(re, re->tothalo++); + VECCOPY(har->co, vec); + har->hasize= hasize; + + /* actual projectvert is done in function project_renderdata() because of parts/border/pano */ + /* we do it here for sorting of halos */ + zn= hoco[3]; + har->xs= 0.5*re->winx*(hoco[0]/zn); + har->ys= 0.5*re->winy*(hoco[1]/zn); + har->zs= 0x7FFFFF*(hoco[2]/zn); + + har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); + + /* halovect */ + if(vec1) { + + har->type |= HA_VECT; + + xn= har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]); + yn= har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]); + if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0; + else zn= atan2(yn, xn); + + har->sin= sin(zn); + har->cos= cos(zn); + zn= VecLenf(vec1, vec)*0.5; + + har->hasize= vectsize*zn + (1.0-vectsize)*hasize; + + VecSubf(har->no, vec, vec1); + Normalize(har->no); + } + + if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA; + + har->alfa= ma->alpha; + har->r= ma->r; + har->g= ma->g; + har->b= ma->b; + har->add= (255.0*ma->add); + har->mat= ma; + har->hard= ma->har; + har->seed= seed % 256; + + if(ma->mode & MA_STAR) har->starpoints= ma->starc; + if(ma->mode & MA_HALO_LINES) har->linec= ma->linec; + if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc; + if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec; + + if((ma->mode & MA_HALOTEX) && ma->mtex[0]){ + har->tex= 1; + i=1; + } + + for(i=0; i<MAX_MTEX; i++) + if(ma->mtex[i] && (ma->septex & (1<<i))==0) { + mtex= ma->mtex[i]; + VECCOPY(texvec, vec); + + if(mtex->texco & TEXCO_NORM) { + ; + } + else if(mtex->texco & TEXCO_OBJECT) { + if(mtex->object){ + float imat[4][4]; + /* imat should really be cached somewhere before this */ + Mat4Invert(imat,mtex->object->obmat); + Mat4MulVecfl(imat,texvec); + } + /* texvec[0]+= imatbase->ivec[0]; */ + /* texvec[1]+= imatbase->ivec[1]; */ + /* texvec[2]+= imatbase->ivec[2]; */ + /* Mat3MulVecfl(imatbase->imat, texvec); */ + } + else if(mtex->texco & TEXCO_GLOB){ + VECCOPY(texvec,vec); + } + else if(mtex->texco & TEXCO_UV && uvco){ + int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname); + if(uv_index<0) + uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE); + + uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE); + + texvec[0]=2.0f*uvco[2*uv_index]-1.0f; + texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f; + texvec[2]=0.0f; + } + else if(orco) { + VECCOPY(texvec, orco); + } + + externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta); + + //yn= tin*mtex->colfac; + //zn= tin*mtex->varfac; + if(mtex->mapto & MAP_COL) { + tex[0]=tr; + tex[1]=tg; + tex[2]=tb; + out[0]=har->r; + out[1]=har->g; + out[2]=har->b; + + texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype); + // zn= 1.0-yn; + //har->r= (yn*tr+ zn*ma->r); + //har->g= (yn*tg+ zn*ma->g); + //har->b= (yn*tb+ zn*ma->b); + har->r= in[0]; + har->g= in[1]; + har->b= in[2]; + } + if(mtex->mapto & MAP_ALPHA) + har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_ALPHA); + if(mtex->mapto & MAP_HAR) + har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_HAR); + if(mtex->mapto & MAP_RAYMIRR) + har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_RAYMIRR); + /* now what on earth is this good for?? */ + //if(mtex->texco & 16) { + // har->alfa= tin; + //} + } + + return har; +} + /* -------------------------- operations on entire database ----------------------- */ /* ugly function for halos in panorama */ diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index f541b161e0a..7930fc97f2d 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1242,7 +1242,7 @@ int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, Te /* in = destination, tex = texture, out = previous color */ /* fact = texture strength, facg = button strength value */ -static void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype) +void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype) { float facm, col; @@ -1330,7 +1330,7 @@ static void texture_rgb_blend(float *in, float *tex, float *out, float fact, flo } -static float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip) +float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip) { float in=0.0, facm, col; @@ -1406,7 +1406,7 @@ void do_material_tex(ShadeInput *shi) tex= mtex->tex; if(tex==0) continue; - + /* which coords */ if(mtex->texco==TEXCO_ORCO) { co= shi->lo; dx= shi->dxlo; dy= shi->dylo; @@ -1486,7 +1486,7 @@ void do_material_tex(ShadeInput *shi) dy[1]= dy[2]= 0.0f; } else continue; // can happen when texco defines disappear and it renders old files - + /* de pointer defines if bumping happens */ if(mtex->mapto & (MAP_NORM|MAP_DISPLACE|MAP_WARP)) { texres.nor= norvec; |