Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-12-20 19:35:27 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-12-20 19:35:27 +0300
commit0f2b2e3c60173e85e137df71392d867576e65ac1 (patch)
treef06099e4ef4a673b622a9f61902cb7b57692780a /source/blender/render/intern
parent2e48a4af57759e61a1afd89edb19a4dc92ced728 (diff)
Strand Render Simplification
============================ - Strand render now has options to remove child strands as the object's faces becomes smaller, in the Simplification particle panel. - "Reference Size" is the approximate size of the object on screen, after which simplification starts. - "Rate" is how fast strands are removed. - "Transition" is the percentage of strands being faded out as they are removed. - Another "Viewport" option removes strands on faces that are outside of the viewport. "Rate" again controls how fast these are removed. - Strand render in Blender Units now has an adjustable minimum width. Below this minimum width, strands start fading out instead of getting smaller.
Diffstat (limited to 'source/blender/render/intern')
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/include/renderdatabase.h2
-rw-r--r--source/blender/render/intern/include/strand.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c45
-rw-r--r--source/blender/render/intern/source/renderdatabase.c18
-rw-r--r--source/blender/render/intern/source/strand.c49
6 files changed, 89 insertions, 30 deletions
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 4a731878ffb..7fbbd0f5abc 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -343,7 +343,7 @@ typedef struct StrandBuffer {
unsigned int lay;
int overrideuv;
int flag, maxdepth;
- float adaptcos;
+ float adaptcos, minwidth;
float winmat[4][4];
int winx, winy;
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index 0346f2d6413..c919a54008e 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -69,6 +69,7 @@ typedef struct StrandTableNode {
struct StrandRen *strand;
float *winspeed;
float *surfnor;
+ float *simplify;
struct MCol *mcol;
float *uv;
int totuv, totmcol;
@@ -112,6 +113,7 @@ int RE_vlakren_get_normal(struct Render *re, struct ObjectInstanceRen *obi, stru
float *RE_strandren_get_surfnor(struct ObjectRen *obr, struct StrandRen *strand, int verify);
float *RE_strandren_get_uv(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify);
struct MCol *RE_strandren_get_mcol(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify);
+float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify);
float *RE_strandren_get_winspeed(struct ObjectInstanceRen *obi, struct StrandRen *strand, int verify);
struct VertRen *RE_vertren_copy(struct ObjectRen *obr, struct VertRen *ver);
diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h
index 7f37317d4d5..34a147c1933 100644
--- a/source/blender/render/intern/include/strand.h
+++ b/source/blender/render/intern/include/strand.h
@@ -68,6 +68,9 @@ typedef struct StrandPoint {
/* screen space */
float hoco[4];
float x, y;
+
+ /* simplification */
+ float alpha;
} StrandPoint;
typedef struct StrandSegment {
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index de3bd6079a4..eb5bb3f2f71 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -983,7 +983,7 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
{
static VertRen *v1= NULL, *v2= NULL;
VlakRen *vlr;
- float nor[3], cross[3], w, dx, dy, width;
+ float nor[3], cross[3], crosslen, w, dx, dy, width;
static float anor[3], avec[3];
int flag, i;
static int second=0;
@@ -992,14 +992,11 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
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);
+ dx= re->winx*cross[0]*re->winmat[0][0];
+ dy= re->winy*cross[1]*re->winmat[1][1];
+ w= sqrt(dx*dx + dy*dy)/w;
if(w!=0.0f) {
float fac;
@@ -1013,12 +1010,16 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end);
- /* use actual Blender units for strand width and fall back to min 1px */
+ /* use actual Blender units for strand width and fall back to minimum width */
if(ma->mode & MA_STR_B_UNITS){
- if(width < 1.0f/w)
- width= 1.0f/w;
+ crosslen= VecLength(cross);
+ w= 2.0f*crosslen*ma->strand_min/w;
+
+ if(width < w)
+ width= w;
+
/*cross is the radius of the strand so we want it to be half of full width */
- VecMulf(cross,0.5);
+ VecMulf(cross,0.5/crosslen);
}
else
width/=w;
@@ -1496,7 +1497,8 @@ 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 loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random;
- int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1;
+ float simplify[2];
+ int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 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};
char **uv_name=0;
@@ -1639,9 +1641,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
Mat4CpyMat4(strandbuf->winmat, re->winmat);
strandbuf->winx= re->winx;
strandbuf->winy= re->winy;
- strandbuf->maxdepth= 2; /* TODO */
+ strandbuf->maxdepth= 2;
strandbuf->adaptcos= cos((float)part->adapt_angle*(float)(M_PI/180.0));
strandbuf->overrideuv= override_uv;
+ strandbuf->minwidth= ma->strand_min;
if(part->flag & PART_HAIR_BSPLINE)
strandbuf->flag |= R_STRAND_BSPLINE;
@@ -1720,7 +1723,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
}
- else{
+ else {
ChildParticle *cpa= psys->child+a-totpart;
pa_time=psys_get_child_time(psys, cpa, cfra);
@@ -1778,6 +1781,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
}
}
+ dosimplify= psys_render_simplify_params(psys, cpa, simplify);
+
if(path_nbr) {
cache = psys->childcache[a-totpart];
max_k = (int)cache->steps;
@@ -1805,6 +1810,12 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
strand->vert= svert;
VECCOPY(strand->orco, orco);
+ if(dosimplify) {
+ float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
+ ssimplify[0]= simplify[0];
+ ssimplify[1]= simplify[1];
+ }
+
if(surfnor) {
float *snor= RE_strandren_get_surfnor(obr, strand, 1);
VECCOPY(snor, surfnor);
@@ -3886,7 +3897,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_particles_to_render_backup(ob, psys);
+ psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy);
}
/* if no psys has "show emitter" selected don't render emitter */
@@ -3910,7 +3921,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in
for(psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
obr= RE_addRenderObject(re, ob, par, index, psysindex);
init_render_object_data(re, obr, only_verts);
- psys_render_backup_to_particles(ob, psys);
+ psys_render_restore(ob, psys);
/* only add instance for objects that have not been used for dupli */
if(!(ob->transflag & OB_RENDER_DUPLI))
@@ -4666,7 +4677,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
} else {
/* check if both have same amounts of vertices */
if(obi->totvector!=oldobi->totvector) {
- printf("Warning: object %s has different amount of vertices on other frame\n", obi->ob->id.name+2);
+ printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name+2);
continue;
}
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 3906b1fc001..79c87252fc2 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -104,6 +104,7 @@
#define RE_MCOL_ELEMS 4
#define RE_UV_ELEMS 2
#define RE_SURFNOR_ELEMS 3
+#define RE_SIMPLIFY_ELEMS 2
float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
{
@@ -590,6 +591,21 @@ MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **nam
return node->mcol + index*RE_MCOL_ELEMS;
}
+float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
+{
+ float *simplify;
+ int nr= strand->index>>8;
+
+ simplify= obr->strandnodes[nr].simplify;
+ if(simplify==NULL) {
+ if(verify)
+ simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify table");
+ else
+ return NULL;
+ }
+ return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
+}
+
/* winspeed is exception, it is stored per instance */
float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
{
@@ -743,6 +759,8 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes)
MEM_freeN(strandnodes[a].winspeed);
if(strandnodes[a].surfnor)
MEM_freeN(strandnodes[a].surfnor);
+ if(strandnodes[a].simplify)
+ MEM_freeN(strandnodes[a].simplify);
}
MEM_freeN(strandnodes);
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 42c6d559f65..4f0e9764a43 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -321,7 +321,8 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
{
Material *ma;
StrandBuffer *strandbuf;
- float p[4][3], data[4], cross[3], w, dx, dy, t;
+ float *simplify;
+ float p[4][3], data[4], cross[3], crosslen, w, dx, dy, t;
int type;
strandbuf= sseg->buffer;
@@ -378,25 +379,34 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
Normalize(spoint->nor);
spoint->width= strand_eval_width(ma, spoint->strandco);
+
+ /* simplification */
+ simplify= RE_strandren_get_simplify(strandbuf->obr, sseg->strand, 0);
+ spoint->alpha= (simplify)? simplify[1]: 1.0f;
/* outer points */
Crossf(cross, spoint->co, spoint->tan);
- if(strandbuf->flag & R_STRAND_B_UNITS)
- Normalize(cross);
-
w= spoint->co[2]*strandbuf->winmat[2][3] + strandbuf->winmat[3][3];
- dx= strandbuf->winx*cross[0]*strandbuf->winmat[0][0]/w;
- dy= strandbuf->winy*cross[1]*strandbuf->winmat[1][1]/w;
- w= sqrt(dx*dx + dy*dy);
+ dx= strandbuf->winx*cross[0]*strandbuf->winmat[0][0];
+ dy= strandbuf->winy*cross[1]*strandbuf->winmat[1][1];
+ w= sqrt(dx*dx + dy*dy)/w;
if(w > 0.0f) {
if(strandbuf->flag & R_STRAND_B_UNITS) {
- w= 1.0f/w;
+ crosslen= VecLength(cross);
+ w= 2.0f*crosslen*strandbuf->minwidth/w;
- if(spoint->width < w)
+ if(spoint->width < w) {
+ spoint->alpha= spoint->width/w;
spoint->width= w;
- VecMulf(cross, spoint->width*0.5f);
+ }
+
+ if(simplify)
+ /* squared because we only change width, not length */
+ spoint->width *= simplify[0]*simplify[0];
+
+ VecMulf(cross, spoint->width*0.5f/crosslen);
}
else
VecMulf(cross, spoint->width/w);
@@ -528,7 +538,7 @@ static void strand_project_point(float winmat[][4], float winx, float winy, Stra
}
#include "BLI_rand.h"
-void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint);
+static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint);
static void strand_shade_get(StrandPart *spart, int lookup, ShadeSample *ssamp, StrandPoint *spoint, StrandVert *svert, StrandSegment *sseg)
{
@@ -653,7 +663,7 @@ static int strand_test_clip(float winmat[][4], ZSpan *zspan, float *bounds, floa
return clipflag;
}
-void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint)
+static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint)
{
ShadeInput *shi= ssamp->shi;
ShadeResult *shr= ssamp->shr;
@@ -685,6 +695,21 @@ void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, Str
shade_samples_do_AO(ssamp);
shade_input_do_shade(shi, shr);
+ /* apply simplification */
+ if(spoint->alpha < 1.0f) {
+ shr->combined[0] *= spoint->alpha;
+ shr->combined[1] *= spoint->alpha;
+ shr->combined[2] *= spoint->alpha;
+ shr->combined[3] *= spoint->alpha;
+
+ shr->col[0] *= spoint->alpha;
+ shr->col[1] *= spoint->alpha;
+ shr->col[2] *= spoint->alpha;
+ shr->col[3] *= spoint->alpha;
+
+ shr->alpha *= spoint->alpha;
+ }
+
/* include lamphalos for strand, since halo layer was added already */
if(re->flag & R_LAMPHALO)
if(shi->layflag & SCE_LAY_HALO)