[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12959] trunk/blender/source/blender:

Brecht Van Lommel brechtvanlommel at pandora.be
Thu Dec 20 17:35:27 CET 2007


Revision: 12959
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12959
Author:   blendix
Date:     2007-12-20 17:35:27 +0100 (Thu, 20 Dec 2007)

Log Message:
-----------

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.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_particle.h
    trunk/blender/source/blender/blenkernel/intern/particle.c
    trunk/blender/source/blender/blenkernel/intern/particle_system.c
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/makesdna/DNA_material_types.h
    trunk/blender/source/blender/makesdna/DNA_particle_types.h
    trunk/blender/source/blender/render/intern/include/render_types.h
    trunk/blender/source/blender/render/intern/include/renderdatabase.h
    trunk/blender/source/blender/render/intern/include/strand.h
    trunk/blender/source/blender/render/intern/source/convertblender.c
    trunk/blender/source/blender/render/intern/source/renderdatabase.c
    trunk/blender/source/blender/render/intern/source/strand.c
    trunk/blender/source/blender/src/buttons_object.c
    trunk/blender/source/blender/src/buttons_shading.c

Modified: trunk/blender/source/blender/blenkernel/BKE_particle.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_particle.h	2007-12-20 16:33:45 UTC (rev 12958)
+++ trunk/blender/source/blender/blenkernel/BKE_particle.h	2007-12-20 16:35:27 UTC (rev 12959)
@@ -112,8 +112,8 @@
 typedef struct ParticleCacheKey{
 	float co[3];
 	float vel[3];
+	float col[3];
 	float rot[4];
-	float col[3];
 	int steps;
 } ParticleCacheKey;
 
@@ -165,7 +165,7 @@
 
 	float *jit, *jitoff, *weight;
 	float maxweight;
-	int *index, jitlevel;
+	int *index, *skip, jitlevel;
 
 	int from, cfrom, distr;
 
@@ -214,8 +214,10 @@
 void free_keyed_keys(struct ParticleSystem *psys);
 void psys_free(struct Object * ob, struct ParticleSystem * psys);
 
-void psys_particles_to_render_backup(struct Object *ob, struct ParticleSystem *psys);
-void psys_render_backup_to_particles(struct Object *ob, 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_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);
 
 void clear_particles_from_cache(struct Object *ob, struct ParticleSystem *psys, int cfra);
 //void psys_remove_from_particle_list(struct Object *ob, short nbr, struct ParticleSystem *psys);

Modified: trunk/blender/source/blender/blenkernel/intern/particle.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle.c	2007-12-20 16:33:45 UTC (rev 12958)
+++ trunk/blender/source/blender/blenkernel/intern/particle.c	2007-12-20 16:35:27 UTC (rev 12959)
@@ -295,7 +295,6 @@
 }
 void free_child_path_cache(ParticleSystem *psys)
 {
-
 	if(psys->childcache){
 		if(psys->childcache[0])
 			MEM_freeN(psys->childcache[0]);
@@ -363,28 +362,98 @@
 	}
 }
 
-/* these two functions move away particle data and bring it back after
+/* these functions move away particle data and bring it back after
  * rendering, to make different render settings possible without
  * removing the previous data. this should be solved properly once */
 
-typedef struct ParticleRenderDataup {
+typedef struct ParticleRenderElem {
+	int curchild, totchild;
+	float lambda, t, scalemin, scalemax;
+} ParticleRenderElem;
+
+typedef struct ParticleRenderData {
 	ChildParticle *child;
 	ParticleCacheKey **pathcache;
 	ParticleCacheKey **childcache;
 	int totchild, totcached, totchildcache;
 	DerivedMesh *dm;
 	int totdmvert, totdmedge, totdmface;
-} ParticleRenderDataup;
 
-void psys_particles_to_render_backup(Object *ob, ParticleSystem *psys)
+	float mat[4][4];
+	float viewmat[4][4], winmat[4][4];
+	int winx, winy;
+
+	int dosimplify;
+	ParticleRenderElem *elems;
+	int *origindex;
+} ParticleRenderData;
+
+static float psys_render_viewport_falloff(double rate, float dist, float width)
 {
-	ParticleRenderDataup *data;
+	return pow(rate, dist/width);
+}
+
+static float psys_render_projected_area(ParticleSystem *psys, float *center, float area, double vprate, float *viewport)
+{
+	ParticleRenderData *data= psys->renderdata;
+	float co[3], view[3], ortho1[3], ortho2[2], w, dx, dy, radius;
+	
+	/* transform to view space */
+	VECCOPY(co, center);
+	co[3]= 1.0f;
+	Mat4MulVec4fl(data->viewmat, co);
+	
+	/* compute two vectors orthogonal to view vector */
+	VECCOPY(view, co);
+	Normalize(view);
+	VecOrthoBasisf(view, ortho1, ortho2);
+
+	/* compute on screen minification */
+	w= co[2]*data->winmat[2][3] + data->winmat[3][3];
+	dx= data->winx*ortho2[0]*data->winmat[0][0];
+	dy= data->winy*ortho2[1]*data->winmat[1][1];
+	w= sqrt(dx*dx + dy*dy)/w;
+
+	/* w squared because we are working with area */
+	area= area*w*w;
+
+	/* viewport of the screen test */
+
+	/* project point on screen */
+	Mat4MulVec4fl(data->winmat, co);
+	if(co[3] != 0.0f) {
+		co[0]= 0.5f*data->winx*(1.0f + co[0]/co[3]);
+		co[1]= 0.5f*data->winy*(1.0f + co[1]/co[3]);
+	}
+
+	/* screen space radius */
+	radius= sqrt(area/M_PI);
+
+	/* make smaller using fallof once over screen edge */
+	*viewport= 1.0f;
+
+	if(co[0]+radius < 0.0f)
+		*viewport *= psys_render_viewport_falloff(vprate, -(co[0]+radius), data->winx);
+	else if(co[0]-radius > data->winx)
+		*viewport *= psys_render_viewport_falloff(vprate, (co[0]-radius) - data->winx, data->winx);
+
+	if(co[1]+radius < 0.0f)
+		*viewport *= psys_render_viewport_falloff(vprate, -(co[1]+radius), data->winy);
+	else if(co[1]-radius > data->winy)
+		*viewport *= psys_render_viewport_falloff(vprate, (co[1]-radius) - data->winy, data->winy);
+	
+	return area;
+}
+
+void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy)
+{
+	ParticleRenderData*data;
 	ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
 
 	if(!G.rendering)
 		return;
 
-	data= MEM_callocN(sizeof(ParticleRenderDataup), "ParticleRenderDataup");
+	data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
 
 	data->child= psys->child;
 	data->totchild= psys->totchild;
@@ -404,17 +473,26 @@
 	psys->childcache= NULL;
 	psys->totchild= psys->totcached= psys->totchildcache= 0;
 
+	Mat4CpyMat4(data->winmat, winmat);
+	Mat4MulMat4(data->viewmat, ob->obmat, viewmat);
+	Mat4MulMat4(data->mat, data->viewmat, winmat);
+	data->winx= winx;
+	data->winy= winy;
+
 	psys->renderdata= data;
 }
 
-void psys_render_backup_to_particles(Object *ob, ParticleSystem *psys)
+void psys_render_restore(Object *ob, ParticleSystem *psys)
 {
-	ParticleRenderDataup *data;
+	ParticleRenderData*data;
 	ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
 
 	data= psys->renderdata;
 	if(!data)
 		return;
+	
+	if(data->elems)
+		MEM_freeN(data->elems);
 
 	if(psmd->dm) {
 		psmd->dm->needsFree= 1;
@@ -428,7 +506,7 @@
 		psys->child= 0;
 		psys->totchild= 0;
 	}
-	
+
 	psys->child= data->child;
 	psys->totchild= data->totchild;
 	psys->pathcache= data->pathcache;
@@ -449,6 +527,211 @@
 	psys->renderdata= NULL;
 }
 
+int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
+{
+	DerivedMesh *dm= ctx->dm;
+	Mesh *me= (Mesh*)(ctx->ob->data);
+	MFace *mf, *mface;
+	MVert *mvert;
+	ParticleRenderData *data;
+	ParticleRenderElem *elems, *elem;
+	ParticleSettings *part= ctx->psys->part;
+	float *facearea, (*facecenter)[3], size[3], fac, powrate;
+	float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
+	double vprate;
+	int *origindex, *facetotvert;
+	int a, b, totorigface, totface, newtot, skipped;
+
+	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))
+		return tot;
+
+	mvert= dm->getVertArray(dm);
+	mface= dm->getFaceArray(dm);
+	origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+	totface= dm->getNumFaces(dm);
+	totorigface= me->totface;
+
+	if(totface == 0 || totorigface == 0 || origindex == NULL)
+		return tot;
+
+	facearea= MEM_callocN(sizeof(float)*totorigface, "SimplifyFaceArea");
+	facecenter= MEM_callocN(sizeof(float[3])*totorigface, "SimplifyFaceCenter");
+	facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea");
+	elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem");
+
+	data= ctx->psys->renderdata;
+	data->dosimplify= 1;
+	data->elems= elems;
+	data->origindex= origindex;
+
+	/* compute number of children per original face */
+	for(a=0; a<tot; a++) {
+		b= origindex[ctx->index[a]];
+		if(b != -1)
+			elems[b].totchild++;
+	}
+
+	/* compute areas and centers of original faces */
+	for(mf=mface, a=0; a<totface; a++, mf++) {
+		b= origindex[a];
+
+		if(b != -1) {
+			VECCOPY(co1, mvert[mf->v1].co);
+			VECCOPY(co2, mvert[mf->v2].co);
+			VECCOPY(co3, mvert[mf->v3].co);
+
+			VECADD(facecenter[b], facecenter[b], co1);
+			VECADD(facecenter[b], facecenter[b], co2);
+			VECADD(facecenter[b], facecenter[b], co3);
+
+			if(mf->v4) {
+				VECCOPY(co4, mvert[mf->v4].co);
+				VECADD(facecenter[b], facecenter[b], co4);
+				facearea[b] += AreaQ3Dfl(co1, co2, co3, co4);
+				facetotvert[b] += 4;
+			}
+			else {
+				facearea[b] += AreaT3Dfl(co1, co2, co3);
+				facetotvert[b] += 3;
+			}
+		}
+	}
+
+	for(a=0; a<totorigface; a++)
+		if(facetotvert[a] > 0)
+			VecMulf(facecenter[a], 1.0f/facetotvert[a]);
+
+	/* for conversion from BU area / pixel area to reference screen size */
+	mesh_get_texspace(me, 0, 0, size);
+	fac= ((size[0] + size[1] + size[2])/3.0f)/part->simplify_refsize;
+	fac= fac*fac;
+
+	powrate= log(0.5f)/log(part->simplify_rate*0.5f);
+	if(part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
+		vprate= pow(1.0 - part->simplify_viewport, 5.0);
+	else
+		vprate= 1.0;
+
+	/* set simplification parameters per original face */
+	for(a=0, elem=elems; a<totorigface; a++, elem++) {
+		area = psys_render_projected_area(ctx->psys, facecenter[a], facearea[a], vprate, &viewport);
+		arearatio= fac*area/facearea[a];
+
+		if(arearatio < 1.0f || viewport < 1.0f) {
+			/* lambda is percentage of elements to keep */
+			lambda= (arearatio < 1.0f)? pow(arearatio, powrate): 1.0f;
+			lambda *= viewport;
+
+			/* compute transition region */
+			t= part->simplify_transition;
+			elem->t= (lambda-t < 0.0f)? lambda: (lambda+t > 1.0f)? 1.0f-lambda: t;
+
+			/* scale at end and beginning of the transition region */
+			elem->scalemax= (lambda+t < 1.0f)? 1.0f/lambda: 1.0f/(1.0f - elem->t*elem->t/t);
+			elem->scalemin= (lambda+t < 1.0f)? 0.0f: elem->scalemax*(1.0f-elem->t/t);
+
+			/* extend lambda to include transition */
+			lambda= lambda + elem->t;
+			if(lambda > 1.0f)
+				lambda= 1.0f;
+		}
+		else {
+			lambda= arearatio;
+
+			elem->scalemax= 1.0f; //sqrt(lambda);
+			elem->scalemin= 1.0f; //sqrt(lambda);
+		}
+
+		elem->lambda= lambda;
+		elem->scalemin= sqrt(elem->scalemin);
+		elem->scalemax= sqrt(elem->scalemax);
+		elem->curchild= 0;
+	}
+
+	MEM_freeN(facearea);
+	MEM_freeN(facecenter);
+	MEM_freeN(facetotvert);
+
+	/* move indices and set random number skipping */
+	ctx->skip= MEM_callocN(sizeof(int)*tot, "SimplificationSkip");
+
+	skipped= 0;
+	for(a=0, newtot=0; a<tot; a++) {
+		b= origindex[ctx->index[a]];
+		if(b != -1) {
+			if(elems[b].curchild++ < ceil(elems[b].lambda*elems[b].totchild)) {
+				ctx->index[newtot]= ctx->index[a];
+				ctx->skip[newtot]= skipped;
+				skipped= 0;
+				newtot++;
+			}

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list