diff options
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_utildefines.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 20 | ||||
-rw-r--r-- | source/blender/render/intern/include/occlusion.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 16 | ||||
-rw-r--r-- | source/blender/render/intern/include/strand.h | 6 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 198 | ||||
-rw-r--r-- | source/blender/render/intern/source/occlusion.c | 73 | ||||
-rw-r--r-- | source/blender/render/intern/source/strand.c | 69 |
9 files changed, 249 insertions, 138 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index af5713b565d..3358cfbfd2b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -215,7 +215,7 @@ void free_keyed_keys(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); void psys_free_children(struct ParticleSystem *psys); -void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy); +void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset); void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot); int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index d08f42375ac..fc22f6787b1 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -112,6 +112,7 @@ #define VECADD(v1,v2,v3) {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);} #define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);} #define VECADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac);} +#define QUATADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac); *(v1+3)= *(v2+3) + *(v3+3)*(fac);} #define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] ) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 5b92eb12d4f..f30c6197911 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -394,6 +394,7 @@ typedef struct ParticleRenderData { int winx, winy; int dosimplify; + int timeoffset; ParticleRenderElem *elems; int *origindex; } ParticleRenderData; @@ -455,13 +456,15 @@ static float psys_render_projected_area(ParticleSystem *psys, float *center, flo return area; } -void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy) +void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset) { ParticleRenderData*data; ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); if(!G.rendering) return; + if(psys->renderdata) + return; data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData"); @@ -489,6 +492,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float data->winx= winx; data->winy= winy; + data->timeoffset= timeoffset; + psys->renderdata= data; } @@ -554,7 +559,13 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; - if(!ctx->psys->renderdata || !(part->simplify_flag & PART_SIMPLIFY_ENABLE)) + if(!ctx->psys->renderdata) + return tot; + + data= ctx->psys->renderdata; + if(data->timeoffset) + return 0; + if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) return tot; mvert= dm->getVertArray(dm); @@ -571,7 +582,6 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea"); elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem"); - data= ctx->psys->renderdata; if(data->elems) MEM_freeN(data->elems); @@ -2076,7 +2086,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, rough_t = t; if(part->rough1 != 0.0 && pa_rough1 != 0.0) - do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); + do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); if(part->rough2 != 0.0 && pa_rough2 != 0.0) do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state); @@ -3517,7 +3527,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle part->kink_amp, part->kink, part->kink_axis, ob->obmat); if(part->rough1 != 0.0) - do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state); + do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state); if(part->rough2 != 0.0) do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state); diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h index 3f10d50ab2e..646ad30b318 100644 --- a/source/blender/render/intern/include/occlusion.h +++ b/source/blender/render/intern/include/occlusion.h @@ -45,7 +45,5 @@ void sample_occ(struct Render *re, struct ShadeInput *shi); void cache_occ_samples(struct Render *re, struct RenderPart *pa, struct ShadeSample *ssamp); void free_occ_samples(struct Render *re, struct RenderPart *pa); -void *cache_occ_mesh(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4]); - #endif diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 46b5face22a..16c46ec550f 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -161,7 +161,7 @@ struct Render /* occlusion tree */ void *occlusiontree; - ListBase occlusionmesh; + ListBase strandsurface; /* use this instead of R.r.cfra */ float cfra; @@ -337,6 +337,18 @@ typedef struct StrandVert { float strandco; } StrandVert; +typedef struct StrandSurface { + struct StrandSurface *next, *prev; + ObjectRen obr; + int (*face)[4]; + float (*co)[3]; + /* for occlusion caching */ + float (*col)[3]; /* for occlusion */ + /* for speedvectors */ + float (*prevco)[3], (*nextco)[3]; + int totvert, totface; +} StrandSurface; + typedef struct StrandBuffer { struct StrandBuffer *next, *prev; struct StrandVert *vert; @@ -344,7 +356,7 @@ typedef struct StrandBuffer { struct ObjectRen *obr; struct Material *ma; - void *occlusionmesh; + struct StrandSurface *surface; unsigned int lay; int overrideuv; int flag, maxdepth; diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h index f1c0b6d1e3a..8e34fa27342 100644 --- a/source/blender/render/intern/include/strand.h +++ b/source/blender/render/intern/include/strand.h @@ -44,6 +44,9 @@ struct RenderBuckets; struct RenderPrimitiveIterator; struct ZSpan; struct ObjectInstanceRen; +struct StrandSurface; +struct DerivedMesh; +struct ObjectRen; typedef struct StrandPoint { /* position within segment */ @@ -89,6 +92,9 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, int totzspan, StrandSegment *sseg); void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); +struct StrandSurface *cache_strand_surface(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4], int timeoffset); +void free_strand_surface(struct Render *re); + struct RenderBuckets *init_buckets(struct Render *re); void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim); void free_buckets(struct RenderBuckets *buckets); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 69ae280dc4c..7a8d151c738 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -108,6 +108,7 @@ #include "radio.h" #include "shadbuf.h" #include "shading.h" +#include "strand.h" #include "texture.h" #include "sss.h" #include "zbuf.h" @@ -1465,7 +1466,7 @@ static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mat if(har) har->lay= obr->ob->lay; } } -static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys) +static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset) { Object *ob= obr->ob; Object *tob=0, *bb_ob=re->scene->camera; @@ -1487,7 +1488,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; - int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, doapproxao = 0; + int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0; 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}, num; char **uv_name=0; @@ -1647,9 +1648,11 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem svert= strandbuf->vert; - if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) + if(re->r.mode & R_SPEED) + dosurfacecache= 1; + else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) if(ma->amb != 0.0f) - doapproxao= 1; + dosurfacecache= 1; } } } @@ -1827,7 +1830,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem VECCOPY(snor, surfnor); } - if(doapproxao && num >= 0) { + if(dosurfacecache && num >= 0) { int *facenum= RE_strandren_get_face(obr, strand, 1); *facenum= num; } @@ -1931,8 +1934,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem break; } - if(doapproxao) - strandbuf->occlusionmesh= cache_occ_mesh(re, obr, psmd->dm, mat); + if(dosurfacecache) + strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset); /* 4. clean up */ if(ma) do_mat_ipo(ma); @@ -2543,7 +2546,7 @@ static void init_render_surf(Render *re, ObjectRen *obr) freedisplist(&displist); } -static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) +static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; Curve *cu; @@ -2621,7 +2624,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) } } - if(only_verts==0) { + if(timeoffset==0) { startvlak= obr->totvlak; index= dl->index; for(a=0; a<dl->parts; a++, index+=3) { @@ -2674,7 +2677,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) } } - if(dl->bevelSplitFlag || only_verts==0) { + if(dl->bevelSplitFlag || timeoffset==0) { startvlak= obr->totvlak; for(a=0; a<dl->parts; a++) { @@ -2890,7 +2893,7 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, } } -static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) +static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; Mesh *me; @@ -2949,12 +2952,12 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) /* check autosmooth and displacement, we then have to skip only-verts optimize */ do_autosmooth |= (me->flag & ME_AUTOSMOOTH); if(do_autosmooth) - only_verts= 0; + timeoffset= 0; if(test_for_displace(re, ob ) ) - only_verts= 0; + timeoffset= 0; mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; - if(!only_verts) + if(!timeoffset) if(need_orco) mask |= CD_MASK_ORCO; @@ -3020,7 +3023,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) } } - if(!only_verts) { + if(!timeoffset) { /* store customdata names, because DerivedMesh is freed */ RE_set_customdata_names(obr, &dm->faceData); @@ -3174,7 +3177,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) } } - if(!only_verts) { + if(!timeoffset) { if (test_for_displace(re, ob ) ) { calc_vertexnormals(re, obr, 0); do_displacement(re, obr); @@ -3834,7 +3837,7 @@ static void check_non_flat_quads(ObjectRen *obr) } } -static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts) +static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; @@ -3845,7 +3848,7 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts) if(ob->type!=OB_MESH && test_for_displace(re, ob)) do_displacement(re, obr); - if(!only_verts) { + if(!timeoffset) { /* phong normal interpolation can cause error in tracing * (terminator problem) */ ob->smoothresh= 0.0; @@ -3934,7 +3937,7 @@ static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex) return NULL; } -static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) +static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; ParticleSystem *psys; @@ -3952,20 +3955,20 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) for(psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++) psys= psys->next; - render_new_particle_system(re, obr, psys); + render_new_particle_system(re, obr, psys, timeoffset); } else { if ELEM(ob->type, OB_FONT, OB_CURVE) - init_render_curve(re, obr, only_verts); + init_render_curve(re, obr, timeoffset); else if(ob->type==OB_SURF) init_render_surf(re, obr); else if(ob->type==OB_MESH) - init_render_mesh(re, obr, only_verts); + init_render_mesh(re, obr, timeoffset); else if(ob->type==OB_MBALL) init_render_mball(re, obr); } - finalize_render_object(re, obr, only_verts); + finalize_render_object(re, obr, timeoffset); re->totvert += obr->totvert; re->totvlak += obr->totvlak; @@ -3973,7 +3976,7 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) re->totstrand += obr->totstrand; } -static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable) +static void add_render_object(Render *re, Object *ob, Object *par, int index, int timeoffset, int instanceable) { ObjectRen *obr; ParticleSystem *psys; @@ -3985,7 +3988,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in show_emitter= 0; for(psys=ob->particlesystem.first; psys; psys=psys->next) { show_emitter += psys->part->draw & PART_DRAW_EMITTER; - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); + psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); } /* if no psys has "show emitter" selected don't render emitter */ @@ -4000,7 +4003,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in obr->flag |= R_INSTANCEABLE; Mat4CpyMat4(obr->obmat, ob->obmat); } - init_render_object_data(re, obr, only_verts); + init_render_object_data(re, obr, timeoffset); /* only add instance for objects that have not been used for dupli */ if(!(ob->transflag & OB_RENDER_DUPLI)) @@ -4018,7 +4021,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in obr->flag |= R_INSTANCEABLE; Mat4CpyMat4(obr->obmat, ob->obmat); } - init_render_object_data(re, obr, only_verts); + init_render_object_data(re, obr, timeoffset); psys_render_restore(ob, psys); /* only add instance for objects that have not been used for dupli */ @@ -4032,7 +4035,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in /* par = pointer to duplicator parent, needed for object lookup table */ /* index = when duplicater copies same object (particle), the counter */ -static void init_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable) +static void init_render_object(Render *re, Object *ob, Object *par, int index, int timeoffset, int instanceable) { static double lasttime= 0.0; double time; @@ -4041,7 +4044,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i if(ob->type==OB_LAMP) add_render_lamp(re, ob); else if(render_object_type(ob->type)) - add_render_object(re, ob, par, index, only_verts, instanceable); + add_render_object(re, ob, par, index, timeoffset, instanceable); else { MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); MTC_Mat4Invert(ob->imat, mat); @@ -4119,6 +4122,7 @@ void RE_Database_Free(Render *re) free_sss(re); free_occ(re); + free_strand_surface(re); re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->i.convertdone= 0; @@ -4174,7 +4178,7 @@ static int allow_render_dupli_instance(Render *re, DupliObject *dob, Object *obd !(re->r.mode & R_RADIO)); } -static void dupli_render_particle_set(Render *re, Object *ob, int level, int enable) +static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, int level, int enable) { /* ugly function, but we need to set particle systems to their render * settings before calling object_duplilist, to get render level duplis */ @@ -4190,7 +4194,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena for(psys=ob->particlesystem.first; psys; psys=psys->next) { if(ELEM(psys->part->draw_as, PART_DRAW_OB, PART_DRAW_GR)) { if(enable) - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); + psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); else psys_render_restore(ob, psys); } @@ -4212,10 +4216,10 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena group= ob->dup_group; for(go= group->gobject.first; go; go= go->next) - dupli_render_particle_set(re, go->ob, level+1, enable); + dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable); } -static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int only_verts) +static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int timeoffset) { Base *base; Object *ob; @@ -4243,16 +4247,16 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int if(ob->flag & OB_DONE) { if(ob->transflag & OB_RENDER_DUPLI) if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts, 1); + init_render_object(re, ob, NULL, 0, timeoffset, 1); } else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) { DupliObject *dob; ListBase *lb; - dupli_render_particle_set(re, ob, 0, 1); + dupli_render_particle_set(re, ob, timeoffset, 0, 1); lb= object_duplilist(sce, ob); - dupli_render_particle_set(re, ob, 0, 0); + dupli_render_particle_set(re, ob, timeoffset, 0, 0); for(dob= lb->first; dob; dob= dob->next) { Object *obd= dob->ob; @@ -4294,7 +4298,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int } } else - init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); + init_render_object(re, obd, ob, dob->index, timeoffset, !dob->animated); psysindex= 1; for(psys=obd->particlesystem.first; psys; psys=psys->next) { @@ -4319,17 +4323,17 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int } } else - init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); + init_render_object(re, obd, ob, dob->index, timeoffset, !dob->animated); if(re->test_break()) break; } free_object_duplilist(lb); if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts, 0); + init_render_object(re, ob, NULL, 0, timeoffset, 0); } else if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts, 0); + init_render_object(re, ob, NULL, 0, timeoffset, 0); } if(re->test_break()) break; @@ -4513,7 +4517,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) } /* MAKE RENDER DATA */ - database_init_objects(re, lay, 0, 0, 0, 1); + database_init_objects(re, lay, 0, 0, 0, timeoffset); if(!re->test_break()) project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); @@ -4608,14 +4612,49 @@ static void calculate_speedvector(float *vectors, int step, float winsq, float w } } +static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen *obi, StrandSurface *mesh) +{ + float winsq= re->winx*re->winy, winroot= sqrt(winsq), (*winspeed)[4]; + float ho[4], prevho[4], nextho[4], winmat[4][4], vec[2]; + int a; + + if(mesh->co && mesh->prevco && mesh->nextco) { + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(winmat, obi->mat, re->winmat); + else + Mat4CpyMat4(winmat, re->winmat); + + winspeed= MEM_callocN(sizeof(float)*4*mesh->totvert, "StrandSurfWin"); + + for(a=0; a<mesh->totvert; a++) { + projectvert(mesh->co[a], winmat, ho); + + projectvert(mesh->prevco[a], winmat, prevho); + speedvector_project(NULL, vec, mesh->prevco[a], prevho); + calculate_speedvector(vec, 0, winsq, winroot, mesh->co[a], ho, winspeed[a]); + + projectvert(mesh->nextco[a], winmat, nextho); + speedvector_project(NULL, vec, mesh->nextco[a], nextho); + calculate_speedvector(vec, 1, winsq, winroot, mesh->co[a], ho, winspeed[a]); + } + + return (float*)winspeed; + } + + return NULL; +} + static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) { ObjectRen *obr= obi->obr; VertRen *ver= NULL; StrandRen *strand= NULL; - float *speed, ho[4], winmat[4][4]; + StrandBuffer *strandbuf; + StrandSurface *mesh= NULL; + float *speed, (*winspeed)[4]=NULL, ho[4], winmat[4][4]; + float *co1, *co2, *co3, *co4, w[4]; float winsq= re->winx*re->winy, winroot= sqrt(winsq); - int a; + int a, *face, *index; if(obi->flag & R_TRANSFORMED) Mat4MulMat4(winmat, obi->mat, re->winmat); @@ -4634,13 +4673,42 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve } if(obr->strandnodes) { - for(a=0; a<obr->totstrand; a++, vectors+=2) { - if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; - else strand++; + strandbuf= obr->strandbufs.first; + mesh= (strandbuf)? strandbuf->surface: NULL; + + /* compute speed vectors at surface vertices */ + if(mesh) + winspeed= (float(*)[4])calculate_strandsurface_speedvectors(re, obi, mesh); - speed= RE_strandren_get_winspeed(obi, strand, 1); - projectvert(strand->vert->co, winmat, ho); - calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed); + if(winspeed) { + for(a=0; a<obr->totstrand; a++, vectors+=2) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; + else strand++; + + index= RE_strandren_get_face(obr, strand, 0); + if(index && *index) { + speed= RE_strandren_get_winspeed(obi, strand, 1); + + /* interpolate speed vectors from strand surface */ + face= mesh->face[*index]; + + co1= mesh->co[face[0]]; + co2= mesh->co[face[1]]; + co3= mesh->co[face[2]]; + co4= (face[3])? mesh->co[face[3]]: NULL; + + InterpWeightsQ3Dfl(co1, co2, co3, co4, strand->vert->co, w); + + speed[0]= speed[1]= speed[2]= speed[3]= 0.0f; + QUATADDFAC(speed, speed, winspeed[face[0]], w[0]); + QUATADDFAC(speed, speed, winspeed[face[1]], w[1]); + QUATADDFAC(speed, speed, winspeed[face[2]], w[2]); + if(face[3]) + QUATADDFAC(speed, speed, winspeed[face[3]], w[3]); + } + } + + MEM_freeN(winspeed); } } } @@ -4731,7 +4799,6 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) ObjectInstanceRen *obi, *obilb; ObjectRen *obr; VertRen *ver= NULL; - StrandRen *strand= NULL; float *vec, ho[4], winmat[4][4]; int a, totvector; @@ -4742,7 +4809,7 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) memcpy(obilb, obi, sizeof(ObjectInstanceRen)); BLI_addtail(lb, obilb); - obilb->totvector= totvector= obr->totvert + obr->totstrand; + obilb->totvector= totvector= obr->totvert; if(totvector > 0) { vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); @@ -4759,14 +4826,6 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) projectvert(ver->co, winmat, ho); speedvector_project(NULL, vec, ver->co, ho); } - - for(a=0; a<obr->totstrand; a++, vec+=2) { - if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; - else strand++; - - projectvert(strand->vert->co, winmat, ho); - speedvector_project(NULL, vec, strand->vert->co, ho); - } } } } @@ -4784,8 +4843,10 @@ static void free_dbase_object_vectors(ListBase *lb) void RE_Database_FromScene_Vectors(Render *re, Scene *sce) { ObjectInstanceRen *obi, *oldobi; + StrandSurface *mesh; ListBase *table; ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL}; + ListBase strandsurface; int step; re->i.infostr= "Calculating previous vectors"; @@ -4800,7 +4861,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) copy_dbase_object_vectors(re, &oldtable); /* free dbase and make the future one */ + strandsurface= re->strandsurface; + memset(&re->strandsurface, 0, sizeof(ListBase)); RE_Database_Free(re); + re->strandsurface= strandsurface; if(!re->test_break()) { /* creates entire dbase */ @@ -4812,7 +4876,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) copy_dbase_object_vectors(re, &newtable); /* free dbase and make the real one */ + strandsurface= re->strandsurface; + memset(&re->strandsurface, 0, sizeof(ListBase)); RE_Database_Free(re); + re->strandsurface= strandsurface; if(!re->test_break()) RE_Database_FromScene(re, sce, 1); @@ -4829,7 +4896,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) for(obi= re->instancetable.first; obi && oldobi; obi= obi->next, oldobi= oldobi->next) { int ok= 1; - obi->totvector= obi->obr->totvert + obi->obr->totstrand; + obi->totvector= obi->obr->totvert; /* find matching object in old table */ if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) { @@ -4867,6 +4934,17 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) free_dbase_object_vectors(&oldtable); free_dbase_object_vectors(&newtable); + + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { + if(mesh->prevco) { + MEM_freeN(mesh->prevco); + mesh->prevco= NULL; + } + if(mesh->nextco) { + MEM_freeN(mesh->nextco); + mesh->nextco= NULL; + } + } re->i.infostr= NULL; re->stats_draw(&re->i); diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index 7d7ed5bcdce..e1d491c69d9 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -35,14 +35,12 @@ #include "MEM_guardedalloc.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_memarena.h" #include "BLI_threads.h" -#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_utildefines.h" @@ -74,15 +72,6 @@ typedef struct OcclusionCache { int x, y, w, h, step; } OcclusionCache; -typedef struct OcclusionCacheMesh { - struct OcclusionCacheMesh *next, *prev; - ObjectRen *obr; - int (*face)[4]; - float (*co)[3]; - float (*col)[3]; - int totvert, totface; -} OcclusionCacheMesh; - typedef struct OccFace { int obi; int facenr; @@ -1418,10 +1407,10 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int return 0; } -static void sample_occ_cache_mesh(ShadeInput *shi) +static void sample_occ_surface(ShadeInput *shi) { StrandRen *strand= shi->strand; - OcclusionCacheMesh *mesh= strand->buffer->occlusionmesh; + StrandSurface *mesh= strand->buffer->surface; int *face, *index = RE_strandren_get_face(shi->obr, strand, 0); float w[4], *co1, *co2, *co3, *co4; @@ -1449,53 +1438,11 @@ static void sample_occ_cache_mesh(ShadeInput *shi) } } -void *cache_occ_mesh(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4]) -{ - OcclusionCacheMesh *mesh; - MFace *mface; - MVert *mvert; - int a, totvert, totface; - - totvert= dm->getNumVerts(dm); - totface= dm->getNumFaces(dm); - - mesh= re->occlusionmesh.last; - if(mesh && mesh->obr->ob == obr->ob && mesh->obr->par == obr->par - && mesh->totvert==totvert && mesh->totface==totface) - return mesh; - - mesh= MEM_callocN(sizeof(OcclusionCacheMesh), "OcclusionCacheMesh"); - mesh->obr= obr; - mesh->totvert= totvert; - mesh->totface= totface; - mesh->co= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCo"); - mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "OcclusionMeshFaces"); - mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCol"); - - mvert= dm->getVertArray(dm); - for(a=0; a<mesh->totvert; a++, mvert++) { - VECCOPY(mesh->co[a], mvert->co); - Mat4MulVecfl(mat, mesh->co[a]); - } - - mface= dm->getFaceArray(dm); - for(a=0; a<mesh->totface; a++, mface++) { - mesh->face[a][0]= mface->v1; - mesh->face[a][1]= mface->v2; - mesh->face[a][2]= mface->v3; - mesh->face[a][3]= mface->v4; - } - - BLI_addtail(&re->occlusionmesh, mesh); - - return mesh; -} - /* ------------------------- External Functions --------------------------- */ void make_occ_tree(Render *re) { - OcclusionCacheMesh *mesh; + StrandSurface *mesh; float col[3], co[3], n[3], *co1, *co2, *co3, *co4; int a, *face, *count; @@ -1511,7 +1458,7 @@ void make_occ_tree(Render *re) if(re->wrld.ao_approx_passes) occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes); - for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) { + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount"); for(a=0; a<mesh->totface; a++) { @@ -1558,20 +1505,10 @@ void make_occ_tree(Render *re) void free_occ(Render *re) { - OcclusionCacheMesh *mesh; - if(re->occlusiontree) { occ_free_tree(re->occlusiontree); re->occlusiontree = NULL; } - - for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) { - if(mesh->co) MEM_freeN(mesh->co); - if(mesh->col) MEM_freeN(mesh->col); - if(mesh->face) MEM_freeN(mesh->face); - } - - BLI_freelistN(&re->occlusionmesh); } void sample_occ(Render *re, ShadeInput *shi) @@ -1584,7 +1521,7 @@ void sample_occ(Render *re, ShadeInput *shi) if(tree) { if(shi->strand) { - sample_occ_cache_mesh(shi); + sample_occ_surface(shi); } /* try to get result from the cache if possible */ else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) { diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 3a1d98572ca..bf58c023998 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -35,12 +35,14 @@ #include "DNA_key_types.h" #include "DNA_material_types.h" +#include "DNA_meshdata_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_memarena.h" +#include "BKE_DerivedMesh.h" #include "BKE_key.h" #include "BKE_utildefines.h" @@ -1313,3 +1315,70 @@ void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], fl #endif } +StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4], int timeoffset) +{ + StrandSurface *mesh; + MFace *mface; + MVert *mvert; + float (*co)[3]; + int a, totvert, totface; + + totvert= dm->getNumVerts(dm); + totface= dm->getNumFaces(dm); + + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) + if(mesh->obr.ob == obr->ob && mesh->obr.par == obr->par + && mesh->obr.index == obr->index && mesh->totvert==totvert && mesh->totface==totface) + break; + + if(!mesh) { + mesh= MEM_callocN(sizeof(StrandSurface), "StrandSurface"); + mesh->obr= *obr; + mesh->totvert= totvert; + mesh->totface= totface; + mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces"); + mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCol"); + BLI_addtail(&re->strandsurface, mesh); + } + + if(timeoffset == -1 && !mesh->prevco) + mesh->prevco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); + else if(timeoffset == 0 && !mesh->co) + mesh->co= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); + else if(timeoffset == 1 && !mesh->nextco) + mesh->nextco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); + else + return mesh; + + mvert= dm->getVertArray(dm); + for(a=0; a<mesh->totvert; a++, mvert++) { + VECCOPY(co[a], mvert->co); + Mat4MulVecfl(mat, co[a]); + } + + mface= dm->getFaceArray(dm); + for(a=0; a<mesh->totface; a++, mface++) { + mesh->face[a][0]= mface->v1; + mesh->face[a][1]= mface->v2; + mesh->face[a][2]= mface->v3; + mesh->face[a][3]= mface->v4; + } + + return mesh; +} + +void free_strand_surface(Render *re) +{ + StrandSurface *mesh; + + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { + if(mesh->co) MEM_freeN(mesh->co); + if(mesh->prevco) MEM_freeN(mesh->prevco); + if(mesh->nextco) MEM_freeN(mesh->nextco); + if(mesh->col) MEM_freeN(mesh->col); + if(mesh->face) MEM_freeN(mesh->face); + } + + BLI_freelistN(&re->strandsurface); +} + |