Point density: Add utility function to sample density outside of render pipeline

Not currently used, it's a preparation for the further work.

Should not be functional changes.
This commit is contained in:
Sergey Sharybin
2015-07-18 21:42:39 +02:00
parent 92a37993a5
commit 2f15a1f66e
3 changed files with 138 additions and 3 deletions

View File

@@ -59,6 +59,12 @@ void RE_free_sample_material(struct Material *mat);
void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob);
/* pointdensity.c */
struct PointDensity;
void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values);
void RE_init_texture_rng(void);
void RE_exit_texture_rng(void);
#endif /* __RE_RENDER_EXT_H__ */

View File

@@ -45,6 +45,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -58,12 +59,15 @@
#include "texture.h"
#include "pointdensity.h"
#include "RE_render_ext.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
/* only to be used here in this file, it's for speed */
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER;
static int point_data_used(PointDensity *pd)
{
@@ -456,14 +460,16 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *
}
int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
static int pointdensity(PointDensity *pd,
const float texvec[3],
TexResult *texres,
float *r_age,
float r_vec[3])
{
int retval = TEX_INT;
PointDensity *pd = tex->pd;
PointDensityRangeData pdr;
float density = 0.0f, age = 0.0f, time = 0.0f;
float vec[3] = {0.0f, 0.0f, 0.0f}, co[3];
float col[4];
float turb, noise_fac;
int num = 0;
@@ -524,7 +530,26 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
mul_v3_fl(vec, 1.0f / num);
}
if (r_age != NULL) {
*r_age = age;
}
if (r_vec != NULL) {
copy_v3_v3(r_vec, vec);
}
texres->tin = density;
return retval;
}
int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
{
PointDensity *pd = tex->pd;
float age = 0.0f;
float vec[3] = {0.0f, 0.0f, 0.0f};
int retval = pointdensity(pd, texvec, texres, &age, vec);
float col[4];
BRICONT;
if (pd->color_source == TEX_PD_COLOR_CONSTANT)
@@ -578,3 +603,106 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
}
#endif
}
static void sample_dummy_point_density(int resolution, float *values)
{
memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
static void particle_system_minmax(Object *object,
ParticleSystem *psys,
float radius,
float min[3], float max[3])
{
ParticleSettings *part = psys->part;
float imat[4][4];
float size[3] = {radius, radius, radius};
PARTICLE_P;
INIT_MINMAX(min, max);
if (part->type == PART_HAIR) {
/* TOOD(sergey): Not supported currently. */
return;
}
invert_m4_m4(imat, object->obmat);
LOOP_PARTICLES {
float co_object[3], co_min[3], co_max[3];
mul_v3_m4v3(co_object, imat, pa->state.co);
sub_v3_v3v3(co_min, co_object, size);
add_v3_v3v3(co_max, co_object, size);
minmax_v3v3_v3(min, max, co_min);
minmax_v3v3_v3(min, max, co_max);
}
}
void RE_sample_point_density(Scene *scene, PointDensity *pd,
int resolution, float *values)
{
const size_t resolution2 = resolution * resolution;
Object *object = pd->object;
size_t x, y, z;
float min[3], max[3], dim[3], mat[4][4];
if (object == NULL) {
sample_dummy_point_density(resolution, values);
return;
}
if (pd->source == TEX_PD_PSYS) {
ParticleSystem *psys;
if (pd->psys == 0) {
sample_dummy_point_density(resolution, values);
return;
}
psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
if (psys == NULL) {
sample_dummy_point_density(resolution, values);
return;
}
particle_system_minmax(object, psys, pd->radius, min, max);
}
else {
float radius[3] = {pd->radius, pd->radius, pd->radius};
float *loc, *size;
BKE_object_obdata_texspace_get(pd->object, NULL, &loc, &size, NULL);
sub_v3_v3v3(min, loc, size);
add_v3_v3v3(max, loc, size);
/* Adjust texture space to include density points on the boundaries. */
sub_v3_v3(min, radius);
add_v3_v3(max, radius);
}
sub_v3_v3v3(dim, max, min);
if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
sample_dummy_point_density(resolution, values);
return;
}
/* Same matricies/resolution as dupli_render_particle_set(). */
unit_m4(mat);
BLI_mutex_lock(&sample_mutex);
cache_pointdensity_ex(scene, pd, mat, mat, 1, 1);
BLI_mutex_unlock(&sample_mutex);
for (z = 0; z < resolution; ++z) {
for (y = 0; y < resolution; ++y) {
for (x = 0; x < resolution; ++x) {
size_t index = z * resolution2 + y * resolution + x;
float texvec[3];
float age, vec[3];
TexResult texres;
copy_v3_v3(texvec, min);
texvec[0] += dim[0] * (float)x / (float)resolution;
texvec[1] += dim[1] * (float)y / (float)resolution;
texvec[2] += dim[2] * (float)z / (float)resolution;
pointdensity(pd, texvec, &texres, &age, vec);
copy_v3_v3(&values[index*4 + 0], &texres.tr);
values[index*4 + 3] = texres.tin;
}
}
}
free_pointdensity(pd);
}

View File

@@ -628,6 +628,7 @@ void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used,
struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE
void RE_FreePersistentData(void) RET_NONE
void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values) RET_NONE;
void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
/* python */