forked from bartvdbraak/blender
Moved render simplification function for particle distribution into the
distribution code.
This commit is contained in:
parent
34762de38f
commit
edc9baaae4
@ -305,7 +305,6 @@ void psys_free(struct Object *ob, struct ParticleSystem *psys);
|
||||
|
||||
void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][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);
|
||||
bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
|
||||
|
||||
void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
|
||||
@ -416,6 +415,33 @@ void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa,
|
||||
|
||||
float psys_get_current_display_percentage(struct ParticleSystem *psys);
|
||||
|
||||
typedef struct ParticleRenderElem {
|
||||
int curchild, totchild, reduce;
|
||||
float lambda, t, scalemin, scalemax;
|
||||
} ParticleRenderElem;
|
||||
|
||||
typedef struct ParticleRenderData {
|
||||
ChildParticle *child;
|
||||
ParticleCacheKey **pathcache;
|
||||
ParticleCacheKey **childcache;
|
||||
ListBase pathcachebufs, childcachebufs;
|
||||
int totchild, totcached, totchildcache;
|
||||
struct DerivedMesh *dm;
|
||||
int totdmvert, totdmedge, totdmface;
|
||||
|
||||
float mat[4][4];
|
||||
float viewmat[4][4], winmat[4][4];
|
||||
int winx, winy;
|
||||
|
||||
int do_simplify;
|
||||
int timeoffset;
|
||||
ParticleRenderElem *elems;
|
||||
|
||||
/* ORIGINDEX */
|
||||
const int *index_mf_to_mpoly;
|
||||
const int *index_mp_to_orig;
|
||||
} ParticleRenderData;
|
||||
|
||||
/* psys_reset */
|
||||
#define PSYS_RESET_ALL 1
|
||||
#define PSYS_RESET_DEPSGRAPH 2
|
||||
|
@ -592,89 +592,6 @@ void psys_free(Object *ob, ParticleSystem *psys)
|
||||
* rendering, to make different render settings possible without
|
||||
* removing the previous data. this should be solved properly once */
|
||||
|
||||
typedef struct ParticleRenderElem {
|
||||
int curchild, totchild, reduce;
|
||||
float lambda, t, scalemin, scalemax;
|
||||
} ParticleRenderElem;
|
||||
|
||||
typedef struct ParticleRenderData {
|
||||
ChildParticle *child;
|
||||
ParticleCacheKey **pathcache;
|
||||
ParticleCacheKey **childcache;
|
||||
ListBase pathcachebufs, childcachebufs;
|
||||
int totchild, totcached, totchildcache;
|
||||
DerivedMesh *dm;
|
||||
int totdmvert, totdmedge, totdmface;
|
||||
|
||||
float mat[4][4];
|
||||
float viewmat[4][4], winmat[4][4];
|
||||
int winx, winy;
|
||||
|
||||
int do_simplify;
|
||||
int timeoffset;
|
||||
ParticleRenderElem *elems;
|
||||
|
||||
/* ORIGINDEX */
|
||||
const int *index_mf_to_mpoly;
|
||||
const int *index_mp_to_orig;
|
||||
} ParticleRenderData;
|
||||
|
||||
static float psys_render_viewport_falloff(double rate, float dist, float width)
|
||||
{
|
||||
return pow(rate, dist / width);
|
||||
}
|
||||
|
||||
static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
|
||||
{
|
||||
ParticleRenderData *data = psys->renderdata;
|
||||
float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
|
||||
|
||||
/* transform to view space */
|
||||
copy_v3_v3(co, center);
|
||||
co[3] = 1.0f;
|
||||
mul_m4_v4(data->viewmat, co);
|
||||
|
||||
/* compute two vectors orthogonal to view vector */
|
||||
normalize_v3_v3(view, co);
|
||||
ortho_basis_v3v3_v3(ortho1, ortho2, view);
|
||||
|
||||
/* 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 = sqrtf(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 */
|
||||
mul_m4_v4(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 = sqrtf(area / (float)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][4], float winmat[4][4], int winx, int winy, int timeoffset)
|
||||
{
|
||||
ParticleRenderData *data;
|
||||
@ -789,191 +706,6 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
|
||||
}
|
||||
}
|
||||
|
||||
/* BMESH_TODO, for orig face data, we need to use MPoly */
|
||||
|
||||
int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
|
||||
{
|
||||
DerivedMesh *dm = ctx->dm;
|
||||
Mesh *me = (Mesh *)(ctx->sim.ob->data);
|
||||
MFace *mf, *mface;
|
||||
MVert *mvert;
|
||||
ParticleRenderData *data;
|
||||
ParticleRenderElem *elems, *elem;
|
||||
ParticleSettings *part = ctx->sim.psys->part;
|
||||
float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
|
||||
float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
|
||||
double vprate;
|
||||
int *facetotvert;
|
||||
int a, b, totorigface, totface, newtot, skipped;
|
||||
|
||||
/* double lookup */
|
||||
const int *index_mf_to_mpoly;
|
||||
const int *index_mp_to_orig;
|
||||
|
||||
if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
|
||||
return tot;
|
||||
if (!ctx->sim.psys->renderdata)
|
||||
return tot;
|
||||
|
||||
data = ctx->sim.psys->renderdata;
|
||||
if (data->timeoffset)
|
||||
return 0;
|
||||
if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
|
||||
return tot;
|
||||
|
||||
mvert = dm->getVertArray(dm);
|
||||
mface = dm->getTessFaceArray(dm);
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
totorigface = me->totpoly;
|
||||
|
||||
if (totface == 0 || totorigface == 0)
|
||||
return tot;
|
||||
|
||||
index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
|
||||
index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
||||
if (index_mf_to_mpoly == NULL) {
|
||||
index_mp_to_orig = NULL;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
if (data->elems)
|
||||
MEM_freeN(data->elems);
|
||||
|
||||
data->do_simplify = true;
|
||||
data->elems = elems;
|
||||
data->index_mf_to_mpoly = index_mf_to_mpoly;
|
||||
data->index_mp_to_orig = index_mp_to_orig;
|
||||
|
||||
/* compute number of children per original face */
|
||||
for (a = 0; a < tot; a++) {
|
||||
b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
|
||||
if (b != ORIGINDEX_NONE) {
|
||||
elems[b].totchild++;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute areas and centers of original faces */
|
||||
for (mf = mface, a = 0; a < totface; a++, mf++) {
|
||||
b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
|
||||
|
||||
if (b != ORIGINDEX_NONE) {
|
||||
copy_v3_v3(co1, mvert[mf->v1].co);
|
||||
copy_v3_v3(co2, mvert[mf->v2].co);
|
||||
copy_v3_v3(co3, mvert[mf->v3].co);
|
||||
|
||||
add_v3_v3(facecenter[b], co1);
|
||||
add_v3_v3(facecenter[b], co2);
|
||||
add_v3_v3(facecenter[b], co3);
|
||||
|
||||
if (mf->v4) {
|
||||
copy_v3_v3(co4, mvert[mf->v4].co);
|
||||
add_v3_v3(facecenter[b], co4);
|
||||
facearea[b] += area_quad_v3(co1, co2, co3, co4);
|
||||
facetotvert[b] += 4;
|
||||
}
|
||||
else {
|
||||
facearea[b] += area_tri_v3(co1, co2, co3);
|
||||
facetotvert[b] += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (a = 0; a < totorigface; a++)
|
||||
if (facetotvert[a] > 0)
|
||||
mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
|
||||
|
||||
/* for conversion from BU area / pixel area to reference screen size */
|
||||
BKE_mesh_texspace_get(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.0f - 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->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
|
||||
arearatio = fac * area / facearea[a];
|
||||
|
||||
if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
|
||||
/* lambda is percentage of elements to keep */
|
||||
lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
|
||||
lambda *= viewport;
|
||||
|
||||
lambda = MAX2(lambda, 1.0f / elem->totchild);
|
||||
|
||||
/* compute transition region */
|
||||
t = part->simplify_transition;
|
||||
elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
|
||||
elem->reduce = 1;
|
||||
|
||||
/* 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);
|
||||
|
||||
elem->scalemin = sqrtf(elem->scalemin);
|
||||
elem->scalemax = sqrtf(elem->scalemax);
|
||||
|
||||
/* clamp scaling */
|
||||
scaleclamp = (float)min_ii(elem->totchild, 10);
|
||||
elem->scalemin = MIN2(scaleclamp, elem->scalemin);
|
||||
elem->scalemax = MIN2(scaleclamp, elem->scalemax);
|
||||
|
||||
/* 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->reduce = 0;
|
||||
}
|
||||
|
||||
elem->lambda = lambda;
|
||||
elem->scalemin = sqrtf(elem->scalemin);
|
||||
elem->scalemax = sqrtf(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 = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
|
||||
|
||||
if (b != ORIGINDEX_NONE) {
|
||||
if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
|
||||
ctx->index[newtot] = ctx->index[a];
|
||||
ctx->skip[newtot] = skipped;
|
||||
skipped = 0;
|
||||
newtot++;
|
||||
}
|
||||
else skipped++;
|
||||
}
|
||||
else skipped++;
|
||||
}
|
||||
|
||||
for (a = 0, elem = elems; a < totorigface; a++, elem++)
|
||||
elem->curchild = 0;
|
||||
|
||||
return newtot;
|
||||
}
|
||||
|
||||
bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
|
||||
{
|
||||
ParticleRenderData *data;
|
||||
|
@ -56,6 +56,8 @@
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
|
||||
static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot);
|
||||
|
||||
static void alloc_child_particles(ParticleSystem *psys, int tot)
|
||||
{
|
||||
if (psys->child) {
|
||||
@ -1168,3 +1170,245 @@ void distribute_particles(ParticleSimulationData *sim, int from)
|
||||
fprintf(stderr,"Particle distribution error!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ======== Simplify ======== */
|
||||
|
||||
static float psys_render_viewport_falloff(double rate, float dist, float width)
|
||||
{
|
||||
return pow(rate, dist / width);
|
||||
}
|
||||
|
||||
static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
|
||||
{
|
||||
ParticleRenderData *data = psys->renderdata;
|
||||
float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
|
||||
|
||||
/* transform to view space */
|
||||
copy_v3_v3(co, center);
|
||||
co[3] = 1.0f;
|
||||
mul_m4_v4(data->viewmat, co);
|
||||
|
||||
/* compute two vectors orthogonal to view vector */
|
||||
normalize_v3_v3(view, co);
|
||||
ortho_basis_v3v3_v3(ortho1, ortho2, view);
|
||||
|
||||
/* 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 = sqrtf(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 */
|
||||
mul_m4_v4(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 = sqrtf(area / (float)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;
|
||||
}
|
||||
|
||||
/* BMESH_TODO, for orig face data, we need to use MPoly */
|
||||
static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
|
||||
{
|
||||
DerivedMesh *dm = ctx->dm;
|
||||
Mesh *me = (Mesh *)(ctx->sim.ob->data);
|
||||
MFace *mf, *mface;
|
||||
MVert *mvert;
|
||||
ParticleRenderData *data;
|
||||
ParticleRenderElem *elems, *elem;
|
||||
ParticleSettings *part = ctx->sim.psys->part;
|
||||
float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
|
||||
float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
|
||||
double vprate;
|
||||
int *facetotvert;
|
||||
int a, b, totorigface, totface, newtot, skipped;
|
||||
|
||||
/* double lookup */
|
||||
const int *index_mf_to_mpoly;
|
||||
const int *index_mp_to_orig;
|
||||
|
||||
if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
|
||||
return tot;
|
||||
if (!ctx->sim.psys->renderdata)
|
||||
return tot;
|
||||
|
||||
data = ctx->sim.psys->renderdata;
|
||||
if (data->timeoffset)
|
||||
return 0;
|
||||
if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
|
||||
return tot;
|
||||
|
||||
mvert = dm->getVertArray(dm);
|
||||
mface = dm->getTessFaceArray(dm);
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
totorigface = me->totpoly;
|
||||
|
||||
if (totface == 0 || totorigface == 0)
|
||||
return tot;
|
||||
|
||||
index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
|
||||
index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
||||
if (index_mf_to_mpoly == NULL) {
|
||||
index_mp_to_orig = NULL;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
if (data->elems)
|
||||
MEM_freeN(data->elems);
|
||||
|
||||
data->do_simplify = true;
|
||||
data->elems = elems;
|
||||
data->index_mf_to_mpoly = index_mf_to_mpoly;
|
||||
data->index_mp_to_orig = index_mp_to_orig;
|
||||
|
||||
/* compute number of children per original face */
|
||||
for (a = 0; a < tot; a++) {
|
||||
b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
|
||||
if (b != ORIGINDEX_NONE) {
|
||||
elems[b].totchild++;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute areas and centers of original faces */
|
||||
for (mf = mface, a = 0; a < totface; a++, mf++) {
|
||||
b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
|
||||
|
||||
if (b != ORIGINDEX_NONE) {
|
||||
copy_v3_v3(co1, mvert[mf->v1].co);
|
||||
copy_v3_v3(co2, mvert[mf->v2].co);
|
||||
copy_v3_v3(co3, mvert[mf->v3].co);
|
||||
|
||||
add_v3_v3(facecenter[b], co1);
|
||||
add_v3_v3(facecenter[b], co2);
|
||||
add_v3_v3(facecenter[b], co3);
|
||||
|
||||
if (mf->v4) {
|
||||
copy_v3_v3(co4, mvert[mf->v4].co);
|
||||
add_v3_v3(facecenter[b], co4);
|
||||
facearea[b] += area_quad_v3(co1, co2, co3, co4);
|
||||
facetotvert[b] += 4;
|
||||
}
|
||||
else {
|
||||
facearea[b] += area_tri_v3(co1, co2, co3);
|
||||
facetotvert[b] += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (a = 0; a < totorigface; a++)
|
||||
if (facetotvert[a] > 0)
|
||||
mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
|
||||
|
||||
/* for conversion from BU area / pixel area to reference screen size */
|
||||
BKE_mesh_texspace_get(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.0f - 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->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
|
||||
arearatio = fac * area / facearea[a];
|
||||
|
||||
if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
|
||||
/* lambda is percentage of elements to keep */
|
||||
lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
|
||||
lambda *= viewport;
|
||||
|
||||
lambda = MAX2(lambda, 1.0f / elem->totchild);
|
||||
|
||||
/* compute transition region */
|
||||
t = part->simplify_transition;
|
||||
elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
|
||||
elem->reduce = 1;
|
||||
|
||||
/* 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);
|
||||
|
||||
elem->scalemin = sqrtf(elem->scalemin);
|
||||
elem->scalemax = sqrtf(elem->scalemax);
|
||||
|
||||
/* clamp scaling */
|
||||
scaleclamp = (float)min_ii(elem->totchild, 10);
|
||||
elem->scalemin = MIN2(scaleclamp, elem->scalemin);
|
||||
elem->scalemax = MIN2(scaleclamp, elem->scalemax);
|
||||
|
||||
/* 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->reduce = 0;
|
||||
}
|
||||
|
||||
elem->lambda = lambda;
|
||||
elem->scalemin = sqrtf(elem->scalemin);
|
||||
elem->scalemax = sqrtf(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 = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
|
||||
|
||||
if (b != ORIGINDEX_NONE) {
|
||||
if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
|
||||
ctx->index[newtot] = ctx->index[a];
|
||||
ctx->skip[newtot] = skipped;
|
||||
skipped = 0;
|
||||
newtot++;
|
||||
}
|
||||
else skipped++;
|
||||
}
|
||||
else skipped++;
|
||||
}
|
||||
|
||||
for (a = 0, elem = elems; a < totorigface; a++, elem++)
|
||||
elem->curchild = 0;
|
||||
|
||||
return newtot;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user