Fix for strand render + simplification + vector blur. With the number
of strands changing between frames, vector blur couldn't work. Now speed vectors are interpolated from the surface. This also means child particles don't have to be computed in the previous and next frames, so saves time too.
This commit is contained in:
@@ -215,7 +215,7 @@ void free_keyed_keys(struct ParticleSystem *psys);
|
|||||||
void psys_free(struct Object * ob, struct ParticleSystem * psys);
|
void psys_free(struct Object * ob, struct ParticleSystem * psys);
|
||||||
void psys_free_children(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);
|
void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
|
||||||
int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot);
|
int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot);
|
||||||
int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
|
int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
|
||||||
|
|||||||
@@ -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 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 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 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] )
|
#define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] )
|
||||||
|
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ typedef struct ParticleRenderData {
|
|||||||
int winx, winy;
|
int winx, winy;
|
||||||
|
|
||||||
int dosimplify;
|
int dosimplify;
|
||||||
|
int timeoffset;
|
||||||
ParticleRenderElem *elems;
|
ParticleRenderElem *elems;
|
||||||
int *origindex;
|
int *origindex;
|
||||||
} ParticleRenderData;
|
} ParticleRenderData;
|
||||||
@@ -455,13 +456,15 @@ static float psys_render_projected_area(ParticleSystem *psys, float *center, flo
|
|||||||
return area;
|
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;
|
ParticleRenderData*data;
|
||||||
ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
|
ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
|
||||||
|
|
||||||
if(!G.rendering)
|
if(!G.rendering)
|
||||||
return;
|
return;
|
||||||
|
if(psys->renderdata)
|
||||||
|
return;
|
||||||
|
|
||||||
data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
|
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->winx= winx;
|
||||||
data->winy= winy;
|
data->winy= winy;
|
||||||
|
|
||||||
|
data->timeoffset= timeoffset;
|
||||||
|
|
||||||
psys->renderdata= data;
|
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))
|
if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
|
||||||
return tot;
|
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;
|
return tot;
|
||||||
|
|
||||||
mvert= dm->getVertArray(dm);
|
mvert= dm->getVertArray(dm);
|
||||||
@@ -571,7 +582,6 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
|
|||||||
facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea");
|
facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea");
|
||||||
elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem");
|
elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem");
|
||||||
|
|
||||||
data= ctx->psys->renderdata;
|
|
||||||
if(data->elems)
|
if(data->elems)
|
||||||
MEM_freeN(data->elems);
|
MEM_freeN(data->elems);
|
||||||
|
|
||||||
@@ -2076,7 +2086,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
|
|||||||
rough_t = t;
|
rough_t = t;
|
||||||
|
|
||||||
if(part->rough1 != 0.0 && pa_rough1 != 0.0)
|
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)
|
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);
|
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);
|
part->kink_amp, part->kink, part->kink_axis, ob->obmat);
|
||||||
|
|
||||||
if(part->rough1 != 0.0)
|
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)
|
if(part->rough2 != 0.0)
|
||||||
do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state);
|
do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state);
|
||||||
|
|||||||
@@ -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 cache_occ_samples(struct Render *re, struct RenderPart *pa, struct ShadeSample *ssamp);
|
||||||
void free_occ_samples(struct Render *re, struct RenderPart *pa);
|
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
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ struct Render
|
|||||||
|
|
||||||
/* occlusion tree */
|
/* occlusion tree */
|
||||||
void *occlusiontree;
|
void *occlusiontree;
|
||||||
ListBase occlusionmesh;
|
ListBase strandsurface;
|
||||||
|
|
||||||
/* use this instead of R.r.cfra */
|
/* use this instead of R.r.cfra */
|
||||||
float cfra;
|
float cfra;
|
||||||
@@ -337,6 +337,18 @@ typedef struct StrandVert {
|
|||||||
float strandco;
|
float strandco;
|
||||||
} StrandVert;
|
} 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 {
|
typedef struct StrandBuffer {
|
||||||
struct StrandBuffer *next, *prev;
|
struct StrandBuffer *next, *prev;
|
||||||
struct StrandVert *vert;
|
struct StrandVert *vert;
|
||||||
@@ -344,7 +356,7 @@ typedef struct StrandBuffer {
|
|||||||
|
|
||||||
struct ObjectRen *obr;
|
struct ObjectRen *obr;
|
||||||
struct Material *ma;
|
struct Material *ma;
|
||||||
void *occlusionmesh;
|
struct StrandSurface *surface;
|
||||||
unsigned int lay;
|
unsigned int lay;
|
||||||
int overrideuv;
|
int overrideuv;
|
||||||
int flag, maxdepth;
|
int flag, maxdepth;
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ struct RenderBuckets;
|
|||||||
struct RenderPrimitiveIterator;
|
struct RenderPrimitiveIterator;
|
||||||
struct ZSpan;
|
struct ZSpan;
|
||||||
struct ObjectInstanceRen;
|
struct ObjectInstanceRen;
|
||||||
|
struct StrandSurface;
|
||||||
|
struct DerivedMesh;
|
||||||
|
struct ObjectRen;
|
||||||
|
|
||||||
typedef struct StrandPoint {
|
typedef struct StrandPoint {
|
||||||
/* position within segment */
|
/* 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 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);
|
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);
|
struct RenderBuckets *init_buckets(struct Render *re);
|
||||||
void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim);
|
void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim);
|
||||||
void free_buckets(struct RenderBuckets *buckets);
|
void free_buckets(struct RenderBuckets *buckets);
|
||||||
|
|||||||
@@ -108,6 +108,7 @@
|
|||||||
#include "radio.h"
|
#include "radio.h"
|
||||||
#include "shadbuf.h"
|
#include "shadbuf.h"
|
||||||
#include "shading.h"
|
#include "shading.h"
|
||||||
|
#include "strand.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "sss.h"
|
#include "sss.h"
|
||||||
#include "zbuf.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;
|
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 *ob= obr->ob;
|
||||||
Object *tob=0, *bb_ob=re->scene->camera;
|
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 *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 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];
|
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 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;
|
int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num;
|
||||||
char **uv_name=0;
|
char **uv_name=0;
|
||||||
@@ -1647,9 +1648,11 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
|
|||||||
|
|
||||||
svert= strandbuf->vert;
|
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)
|
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);
|
VECCOPY(snor, surfnor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doapproxao && num >= 0) {
|
if(dosurfacecache && num >= 0) {
|
||||||
int *facenum= RE_strandren_get_face(obr, strand, 1);
|
int *facenum= RE_strandren_get_face(obr, strand, 1);
|
||||||
*facenum= num;
|
*facenum= num;
|
||||||
}
|
}
|
||||||
@@ -1931,8 +1934,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doapproxao)
|
if(dosurfacecache)
|
||||||
strandbuf->occlusionmesh= cache_occ_mesh(re, obr, psmd->dm, mat);
|
strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
|
||||||
|
|
||||||
/* 4. clean up */
|
/* 4. clean up */
|
||||||
if(ma) do_mat_ipo(ma);
|
if(ma) do_mat_ipo(ma);
|
||||||
@@ -2543,7 +2546,7 @@ static void init_render_surf(Render *re, ObjectRen *obr)
|
|||||||
freedisplist(&displist);
|
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;
|
Object *ob= obr->ob;
|
||||||
Curve *cu;
|
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;
|
startvlak= obr->totvlak;
|
||||||
index= dl->index;
|
index= dl->index;
|
||||||
for(a=0; a<dl->parts; a++, index+=3) {
|
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;
|
startvlak= obr->totvlak;
|
||||||
|
|
||||||
for(a=0; a<dl->parts; a++) {
|
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;
|
Object *ob= obr->ob;
|
||||||
Mesh *me;
|
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 */
|
/* check autosmooth and displacement, we then have to skip only-verts optimize */
|
||||||
do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
|
do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
|
||||||
if(do_autosmooth)
|
if(do_autosmooth)
|
||||||
only_verts= 0;
|
timeoffset= 0;
|
||||||
if(test_for_displace(re, ob ) )
|
if(test_for_displace(re, ob ) )
|
||||||
only_verts= 0;
|
timeoffset= 0;
|
||||||
|
|
||||||
mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
|
mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
|
||||||
if(!only_verts)
|
if(!timeoffset)
|
||||||
if(need_orco)
|
if(need_orco)
|
||||||
mask |= CD_MASK_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 */
|
/* store customdata names, because DerivedMesh is freed */
|
||||||
RE_set_customdata_names(obr, &dm->faceData);
|
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 ) ) {
|
if (test_for_displace(re, ob ) ) {
|
||||||
calc_vertexnormals(re, obr, 0);
|
calc_vertexnormals(re, obr, 0);
|
||||||
do_displacement(re, obr);
|
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;
|
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))
|
if(ob->type!=OB_MESH && test_for_displace(re, ob))
|
||||||
do_displacement(re, obr);
|
do_displacement(re, obr);
|
||||||
|
|
||||||
if(!only_verts) {
|
if(!timeoffset) {
|
||||||
/* phong normal interpolation can cause error in tracing
|
/* phong normal interpolation can cause error in tracing
|
||||||
* (terminator problem) */
|
* (terminator problem) */
|
||||||
ob->smoothresh= 0.0;
|
ob->smoothresh= 0.0;
|
||||||
@@ -3934,7 +3937,7 @@ static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex)
|
|||||||
return NULL;
|
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;
|
Object *ob= obr->ob;
|
||||||
ParticleSystem *psys;
|
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++)
|
for(psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++)
|
||||||
psys= psys->next;
|
psys= psys->next;
|
||||||
|
|
||||||
render_new_particle_system(re, obr, psys);
|
render_new_particle_system(re, obr, psys, timeoffset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ELEM(ob->type, OB_FONT, OB_CURVE)
|
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)
|
else if(ob->type==OB_SURF)
|
||||||
init_render_surf(re, obr);
|
init_render_surf(re, obr);
|
||||||
else if(ob->type==OB_MESH)
|
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)
|
else if(ob->type==OB_MBALL)
|
||||||
init_render_mball(re, obr);
|
init_render_mball(re, obr);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize_render_object(re, obr, only_verts);
|
finalize_render_object(re, obr, timeoffset);
|
||||||
|
|
||||||
re->totvert += obr->totvert;
|
re->totvert += obr->totvert;
|
||||||
re->totvlak += obr->totvlak;
|
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;
|
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;
|
ObjectRen *obr;
|
||||||
ParticleSystem *psys;
|
ParticleSystem *psys;
|
||||||
@@ -3985,7 +3988,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in
|
|||||||
show_emitter= 0;
|
show_emitter= 0;
|
||||||
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
|
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
|
||||||
show_emitter += psys->part->draw & PART_DRAW_EMITTER;
|
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 */
|
/* 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;
|
obr->flag |= R_INSTANCEABLE;
|
||||||
Mat4CpyMat4(obr->obmat, ob->obmat);
|
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 */
|
/* only add instance for objects that have not been used for dupli */
|
||||||
if(!(ob->transflag & OB_RENDER_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;
|
obr->flag |= R_INSTANCEABLE;
|
||||||
Mat4CpyMat4(obr->obmat, ob->obmat);
|
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);
|
psys_render_restore(ob, psys);
|
||||||
|
|
||||||
/* only add instance for objects that have not been used for dupli */
|
/* 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 */
|
/* par = pointer to duplicator parent, needed for object lookup table */
|
||||||
/* index = when duplicater copies same object (particle), the counter */
|
/* 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;
|
static double lasttime= 0.0;
|
||||||
double time;
|
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)
|
if(ob->type==OB_LAMP)
|
||||||
add_render_lamp(re, ob);
|
add_render_lamp(re, ob);
|
||||||
else if(render_object_type(ob->type))
|
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 {
|
else {
|
||||||
MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
|
MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
|
||||||
MTC_Mat4Invert(ob->imat, mat);
|
MTC_Mat4Invert(ob->imat, mat);
|
||||||
@@ -4119,6 +4122,7 @@ void RE_Database_Free(Render *re)
|
|||||||
|
|
||||||
free_sss(re);
|
free_sss(re);
|
||||||
free_occ(re);
|
free_occ(re);
|
||||||
|
free_strand_surface(re);
|
||||||
|
|
||||||
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
|
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
|
||||||
re->i.convertdone= 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));
|
!(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
|
/* ugly function, but we need to set particle systems to their render
|
||||||
* settings before calling object_duplilist, to get render level duplis */
|
* 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) {
|
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
|
||||||
if(ELEM(psys->part->draw_as, PART_DRAW_OB, PART_DRAW_GR)) {
|
if(ELEM(psys->part->draw_as, PART_DRAW_OB, PART_DRAW_GR)) {
|
||||||
if(enable)
|
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
|
else
|
||||||
psys_render_restore(ob, psys);
|
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;
|
group= ob->dup_group;
|
||||||
|
|
||||||
for(go= group->gobject.first; go; go= go->next)
|
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;
|
Base *base;
|
||||||
Object *ob;
|
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->flag & OB_DONE) {
|
||||||
if(ob->transflag & OB_RENDER_DUPLI)
|
if(ob->transflag & OB_RENDER_DUPLI)
|
||||||
if(allow_render_object(ob, nolamps, onlyselected, actob))
|
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)) ) {
|
else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) {
|
||||||
if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
|
if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
|
||||||
DupliObject *dob;
|
DupliObject *dob;
|
||||||
ListBase *lb;
|
ListBase *lb;
|
||||||
|
|
||||||
dupli_render_particle_set(re, ob, 0, 1);
|
dupli_render_particle_set(re, ob, timeoffset, 0, 1);
|
||||||
lb= object_duplilist(sce, ob);
|
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) {
|
for(dob= lb->first; dob; dob= dob->next) {
|
||||||
Object *obd= dob->ob;
|
Object *obd= dob->ob;
|
||||||
@@ -4294,7 +4298,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
psysindex= 1;
|
||||||
for(psys=obd->particlesystem.first; psys; psys=psys->next) {
|
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
|
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;
|
if(re->test_break()) break;
|
||||||
}
|
}
|
||||||
free_object_duplilist(lb);
|
free_object_duplilist(lb);
|
||||||
|
|
||||||
if(allow_render_object(ob, nolamps, onlyselected, actob))
|
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))
|
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;
|
if(re->test_break()) break;
|
||||||
@@ -4513,7 +4517,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* MAKE RENDER DATA */
|
/* 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())
|
if(!re->test_break())
|
||||||
project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
|
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)
|
static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step)
|
||||||
{
|
{
|
||||||
ObjectRen *obr= obi->obr;
|
ObjectRen *obr= obi->obr;
|
||||||
VertRen *ver= NULL;
|
VertRen *ver= NULL;
|
||||||
StrandRen *strand= 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);
|
float winsq= re->winx*re->winy, winroot= sqrt(winsq);
|
||||||
int a;
|
int a, *face, *index;
|
||||||
|
|
||||||
if(obi->flag & R_TRANSFORMED)
|
if(obi->flag & R_TRANSFORMED)
|
||||||
Mat4MulMat4(winmat, obi->mat, re->winmat);
|
Mat4MulMat4(winmat, obi->mat, re->winmat);
|
||||||
@@ -4634,13 +4673,42 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(obr->strandnodes) {
|
if(obr->strandnodes) {
|
||||||
for(a=0; a<obr->totstrand; a++, vectors+=2) {
|
strandbuf= obr->strandbufs.first;
|
||||||
if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
|
mesh= (strandbuf)? strandbuf->surface: NULL;
|
||||||
else strand++;
|
|
||||||
|
|
||||||
speed= RE_strandren_get_winspeed(obi, strand, 1);
|
/* compute speed vectors at surface vertices */
|
||||||
projectvert(strand->vert->co, winmat, ho);
|
if(mesh)
|
||||||
calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed);
|
winspeed= (float(*)[4])calculate_strandsurface_speedvectors(re, obi, mesh);
|
||||||
|
|
||||||
|
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;
|
ObjectInstanceRen *obi, *obilb;
|
||||||
ObjectRen *obr;
|
ObjectRen *obr;
|
||||||
VertRen *ver= NULL;
|
VertRen *ver= NULL;
|
||||||
StrandRen *strand= NULL;
|
|
||||||
float *vec, ho[4], winmat[4][4];
|
float *vec, ho[4], winmat[4][4];
|
||||||
int a, totvector;
|
int a, totvector;
|
||||||
|
|
||||||
@@ -4742,7 +4809,7 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb)
|
|||||||
memcpy(obilb, obi, sizeof(ObjectInstanceRen));
|
memcpy(obilb, obi, sizeof(ObjectInstanceRen));
|
||||||
BLI_addtail(lb, obilb);
|
BLI_addtail(lb, obilb);
|
||||||
|
|
||||||
obilb->totvector= totvector= obr->totvert + obr->totstrand;
|
obilb->totvector= totvector= obr->totvert;
|
||||||
|
|
||||||
if(totvector > 0) {
|
if(totvector > 0) {
|
||||||
vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array");
|
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);
|
projectvert(ver->co, winmat, ho);
|
||||||
speedvector_project(NULL, vec, ver->co, 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)
|
void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
|
||||||
{
|
{
|
||||||
ObjectInstanceRen *obi, *oldobi;
|
ObjectInstanceRen *obi, *oldobi;
|
||||||
|
StrandSurface *mesh;
|
||||||
ListBase *table;
|
ListBase *table;
|
||||||
ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL};
|
ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL};
|
||||||
|
ListBase strandsurface;
|
||||||
int step;
|
int step;
|
||||||
|
|
||||||
re->i.infostr= "Calculating previous vectors";
|
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);
|
copy_dbase_object_vectors(re, &oldtable);
|
||||||
|
|
||||||
/* free dbase and make the future one */
|
/* free dbase and make the future one */
|
||||||
|
strandsurface= re->strandsurface;
|
||||||
|
memset(&re->strandsurface, 0, sizeof(ListBase));
|
||||||
RE_Database_Free(re);
|
RE_Database_Free(re);
|
||||||
|
re->strandsurface= strandsurface;
|
||||||
|
|
||||||
if(!re->test_break()) {
|
if(!re->test_break()) {
|
||||||
/* creates entire dbase */
|
/* creates entire dbase */
|
||||||
@@ -4812,7 +4876,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
|
|||||||
copy_dbase_object_vectors(re, &newtable);
|
copy_dbase_object_vectors(re, &newtable);
|
||||||
|
|
||||||
/* free dbase and make the real one */
|
/* free dbase and make the real one */
|
||||||
|
strandsurface= re->strandsurface;
|
||||||
|
memset(&re->strandsurface, 0, sizeof(ListBase));
|
||||||
RE_Database_Free(re);
|
RE_Database_Free(re);
|
||||||
|
re->strandsurface= strandsurface;
|
||||||
|
|
||||||
if(!re->test_break())
|
if(!re->test_break())
|
||||||
RE_Database_FromScene(re, sce, 1);
|
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) {
|
for(obi= re->instancetable.first; obi && oldobi; obi= obi->next, oldobi= oldobi->next) {
|
||||||
int ok= 1;
|
int ok= 1;
|
||||||
|
|
||||||
obi->totvector= obi->obr->totvert + obi->obr->totstrand;
|
obi->totvector= obi->obr->totvert;
|
||||||
|
|
||||||
/* find matching object in old table */
|
/* find matching object in old table */
|
||||||
if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) {
|
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(&oldtable);
|
||||||
free_dbase_object_vectors(&newtable);
|
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->i.infostr= NULL;
|
||||||
re->stats_draw(&re->i);
|
re->stats_draw(&re->i);
|
||||||
|
|||||||
@@ -35,14 +35,12 @@
|
|||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_meshdata_types.h"
|
|
||||||
|
|
||||||
#include "BLI_arithb.h"
|
#include "BLI_arithb.h"
|
||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLI_memarena.h"
|
#include "BLI_memarena.h"
|
||||||
#include "BLI_threads.h"
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
#include "BKE_DerivedMesh.h"
|
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_utildefines.h"
|
#include "BKE_utildefines.h"
|
||||||
|
|
||||||
@@ -74,15 +72,6 @@ typedef struct OcclusionCache {
|
|||||||
int x, y, w, h, step;
|
int x, y, w, h, step;
|
||||||
} OcclusionCache;
|
} 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 {
|
typedef struct OccFace {
|
||||||
int obi;
|
int obi;
|
||||||
int facenr;
|
int facenr;
|
||||||
@@ -1418,10 +1407,10 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sample_occ_cache_mesh(ShadeInput *shi)
|
static void sample_occ_surface(ShadeInput *shi)
|
||||||
{
|
{
|
||||||
StrandRen *strand= shi->strand;
|
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);
|
int *face, *index = RE_strandren_get_face(shi->obr, strand, 0);
|
||||||
float w[4], *co1, *co2, *co3, *co4;
|
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 --------------------------- */
|
/* ------------------------- External Functions --------------------------- */
|
||||||
|
|
||||||
void make_occ_tree(Render *re)
|
void make_occ_tree(Render *re)
|
||||||
{
|
{
|
||||||
OcclusionCacheMesh *mesh;
|
StrandSurface *mesh;
|
||||||
float col[3], co[3], n[3], *co1, *co2, *co3, *co4;
|
float col[3], co[3], n[3], *co1, *co2, *co3, *co4;
|
||||||
int a, *face, *count;
|
int a, *face, *count;
|
||||||
|
|
||||||
@@ -1511,7 +1458,7 @@ void make_occ_tree(Render *re)
|
|||||||
if(re->wrld.ao_approx_passes)
|
if(re->wrld.ao_approx_passes)
|
||||||
occ_compute_passes(re, re->occlusiontree, 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");
|
count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount");
|
||||||
|
|
||||||
for(a=0; a<mesh->totface; a++) {
|
for(a=0; a<mesh->totface; a++) {
|
||||||
@@ -1558,20 +1505,10 @@ void make_occ_tree(Render *re)
|
|||||||
|
|
||||||
void free_occ(Render *re)
|
void free_occ(Render *re)
|
||||||
{
|
{
|
||||||
OcclusionCacheMesh *mesh;
|
|
||||||
|
|
||||||
if(re->occlusiontree) {
|
if(re->occlusiontree) {
|
||||||
occ_free_tree(re->occlusiontree);
|
occ_free_tree(re->occlusiontree);
|
||||||
re->occlusiontree = NULL;
|
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)
|
void sample_occ(Render *re, ShadeInput *shi)
|
||||||
@@ -1584,7 +1521,7 @@ void sample_occ(Render *re, ShadeInput *shi)
|
|||||||
|
|
||||||
if(tree) {
|
if(tree) {
|
||||||
if(shi->strand) {
|
if(shi->strand) {
|
||||||
sample_occ_cache_mesh(shi);
|
sample_occ_surface(shi);
|
||||||
}
|
}
|
||||||
/* try to get result from the cache if possible */
|
/* 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)) {
|
else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
|
||||||
|
|||||||
@@ -35,12 +35,14 @@
|
|||||||
|
|
||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
|
||||||
#include "BLI_arithb.h"
|
#include "BLI_arithb.h"
|
||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLI_ghash.h"
|
#include "BLI_ghash.h"
|
||||||
#include "BLI_memarena.h"
|
#include "BLI_memarena.h"
|
||||||
|
|
||||||
|
#include "BKE_DerivedMesh.h"
|
||||||
#include "BKE_key.h"
|
#include "BKE_key.h"
|
||||||
#include "BKE_utildefines.h"
|
#include "BKE_utildefines.h"
|
||||||
|
|
||||||
@@ -1313,3 +1315,70 @@ void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], fl
|
|||||||
#endif
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user