New voxel texture mode "Hair", for displaying the internal hair volume
structure as a texture. This is mostly a debugging feature that may be removed again later.
This commit is contained in:
@@ -771,6 +771,8 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel, Panel):
|
||||
elif vd.file_format == 'SMOKE':
|
||||
layout.prop(vd, "domain_object")
|
||||
layout.prop(vd, "smoke_data_type")
|
||||
elif vd.file_format == 'HAIR':
|
||||
layout.prop(vd, "domain_object")
|
||||
elif vd.file_format == 'IMAGE_SEQUENCE':
|
||||
layout.template_ID(tex, "image", open="image.open")
|
||||
layout.template_image(tex, "image", tex.image_user, compact=True)
|
||||
|
@@ -42,6 +42,7 @@ struct MFace;
|
||||
struct DerivedMesh;
|
||||
struct ClothModifierData;
|
||||
struct CollisionTree;
|
||||
struct VoxelData;
|
||||
|
||||
#define DO_INLINE MALWAYS_INLINE
|
||||
|
||||
@@ -196,6 +197,8 @@ int implicit_free (struct ClothModifierData *clmd );
|
||||
int implicit_solver (struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors );
|
||||
void implicit_set_positions (struct ClothModifierData *clmd );
|
||||
|
||||
bool implicit_hair_volume_get_texture_data(struct Object *UNUSED(ob), struct ClothModifierData *clmd, struct ListBase *UNUSED(effectors), struct VoxelData *vd);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// cloth.c
|
||||
////////////////////////////////////////////////
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_linklist.h"
|
||||
@@ -1293,34 +1294,33 @@ static void hair_velocity_collision(const HairGridVert *collgrid, const float gm
|
||||
}
|
||||
}
|
||||
|
||||
static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
|
||||
static void hair_volume_get_boundbox(lfVector *lX, unsigned int numverts, float gmin[3], float gmax[3])
|
||||
{
|
||||
int size = hair_grid_size(hair_grid_res);
|
||||
HairGridVert *hairgrid;
|
||||
HairGridVert *collgrid;
|
||||
ListBase *colliders;
|
||||
ColliderCache *col = NULL;
|
||||
float gmin[3], gmax[3], density;
|
||||
/* 2.0f is an experimental value that seems to give good results */
|
||||
float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
|
||||
float collfac = 2.0f * clmd->sim_parms->collider_friction;
|
||||
unsigned int v = 0;
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
INIT_MINMAX(gmin, gmax);
|
||||
for (i = 0; i < numverts; i++)
|
||||
DO_MINMAX(lX[i], gmin, gmax);
|
||||
}
|
||||
|
||||
static HairGridVert *hair_volume_create_hair_grid(ClothModifierData *clmd, lfVector *lX, lfVector *lV, unsigned int numverts)
|
||||
{
|
||||
int size = hair_grid_size(hair_grid_res);
|
||||
HairGridVert *hairgrid;
|
||||
float gmin[3], gmax[3], density;
|
||||
/* 2.0f is an experimental value that seems to give good results */
|
||||
float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
|
||||
unsigned int v = 0;
|
||||
int i = 0;
|
||||
|
||||
hair_volume_get_boundbox(lX, numverts, gmin, gmax);
|
||||
|
||||
hairgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair voxel data");
|
||||
collgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair collider voxel data");
|
||||
|
||||
/* initialize grid */
|
||||
for (i = 0; i < size; ++i) {
|
||||
zero_v3(hairgrid[i].velocity);
|
||||
hairgrid[i].density = 0.0f;
|
||||
|
||||
zero_v3(collgrid[i].velocity);
|
||||
collgrid[i].density = 0.0f;
|
||||
}
|
||||
|
||||
/* gather velocities & density */
|
||||
@@ -1335,6 +1335,42 @@ static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *
|
||||
}
|
||||
}
|
||||
|
||||
/* divide velocity with density */
|
||||
for (i = 0; i < size; i++) {
|
||||
density = hairgrid[i].density;
|
||||
if (density > 0.0f) {
|
||||
hairgrid[i].velocity[0] /= density;
|
||||
hairgrid[i].velocity[1] /= density;
|
||||
hairgrid[i].velocity[2] /= density;
|
||||
}
|
||||
}
|
||||
|
||||
return hairgrid;
|
||||
}
|
||||
|
||||
|
||||
static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd, lfVector *lX, unsigned int numverts)
|
||||
{
|
||||
int size = hair_grid_size(hair_grid_res);
|
||||
HairGridVert *collgrid;
|
||||
ListBase *colliders;
|
||||
ColliderCache *col = NULL;
|
||||
float gmin[3], gmax[3], density;
|
||||
/* 2.0f is an experimental value that seems to give good results */
|
||||
float collfac = 2.0f * clmd->sim_parms->collider_friction;
|
||||
unsigned int v = 0;
|
||||
int i = 0;
|
||||
|
||||
hair_volume_get_boundbox(lX, numverts, gmin, gmax);
|
||||
|
||||
collgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair collider voxel data");
|
||||
|
||||
/* initialize grid */
|
||||
for (i = 0; i < size; ++i) {
|
||||
zero_v3(collgrid[i].velocity);
|
||||
collgrid[i].density = 0.0f;
|
||||
}
|
||||
|
||||
/* gather colliders */
|
||||
colliders = get_collider_cache(clmd->scene, NULL, NULL);
|
||||
if (colliders && collfac > 0.0f) {
|
||||
@@ -1359,13 +1395,6 @@ static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *
|
||||
|
||||
/* divide velocity with density */
|
||||
for (i = 0; i < size; i++) {
|
||||
density = hairgrid[i].density;
|
||||
if (density > 0.0f) {
|
||||
hairgrid[i].velocity[0] /= density;
|
||||
hairgrid[i].velocity[1] /= density;
|
||||
hairgrid[i].velocity[2] /= density;
|
||||
}
|
||||
|
||||
density = collgrid[i].density;
|
||||
if (density > 0.0f) {
|
||||
collgrid[i].velocity[0] /= density;
|
||||
@@ -1374,6 +1403,21 @@ static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *
|
||||
}
|
||||
}
|
||||
|
||||
return collgrid;
|
||||
}
|
||||
|
||||
static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
|
||||
{
|
||||
HairGridVert *hairgrid, *collgrid;
|
||||
float gmin[3], gmax[3];
|
||||
/* 2.0f is an experimental value that seems to give good results */
|
||||
float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
|
||||
float collfac = 2.0f * clmd->sim_parms->collider_friction;
|
||||
|
||||
hair_volume_get_boundbox(lX, numverts, gmin, gmax);
|
||||
hairgrid = hair_volume_create_hair_grid(clmd, lX, lV, numverts);
|
||||
collgrid = hair_volume_create_collision_grid(clmd, lX, numverts);
|
||||
|
||||
hair_velocity_smoothing(hairgrid, gmin, gmax, smoothfac, lF, lX, lV, numverts);
|
||||
hair_velocity_collision(collgrid, gmin, gmax, collfac, lF, lX, lV, numverts);
|
||||
|
||||
@@ -1381,6 +1425,47 @@ static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *
|
||||
MEM_freeN(collgrid);
|
||||
}
|
||||
|
||||
bool implicit_hair_volume_get_texture_data(Object *UNUSED(ob), ClothModifierData *clmd, ListBase *UNUSED(effectors), VoxelData *vd)
|
||||
{
|
||||
lfVector *lX, *lV;
|
||||
HairGridVert *hairgrid/*, *collgrid*/;
|
||||
int numverts;
|
||||
int totres, i;
|
||||
|
||||
if (!clmd->clothObject || !clmd->clothObject->implicit)
|
||||
return false;
|
||||
|
||||
lX = clmd->clothObject->implicit->X;
|
||||
lV = clmd->clothObject->implicit->V;
|
||||
numverts = clmd->clothObject->numverts;
|
||||
|
||||
hairgrid = hair_volume_create_hair_grid(clmd, lX, lV, numverts);
|
||||
// collgrid = hair_volume_create_collision_grid(clmd, lX, numverts);
|
||||
|
||||
vd->resol[0] = hair_grid_res;
|
||||
vd->resol[1] = hair_grid_res;
|
||||
vd->resol[2] = hair_grid_res;
|
||||
|
||||
totres = hair_grid_size(hair_grid_res);
|
||||
|
||||
vd->data_type = TEX_VD_INTENSITY;
|
||||
if (totres > 0) {
|
||||
vd->dataset = (float *)MEM_mapallocN(sizeof(float) * (totres), "hair volume texture data");
|
||||
for (i = 0; i < totres; ++i) {
|
||||
vd->dataset[i] = hairgrid[i].density;
|
||||
}
|
||||
}
|
||||
else
|
||||
vd->dataset = NULL;
|
||||
|
||||
MEM_freeN(hairgrid);
|
||||
// MEM_freeN(collgrid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ================================ */
|
||||
|
||||
static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M)
|
||||
{
|
||||
/* Collect forces and derivatives: F, dFdX, dFdV */
|
||||
@@ -1798,4 +1883,3 @@ void implicit_set_positions(ClothModifierData *clmd)
|
||||
if (G.debug_value > 0)
|
||||
printf("implicit_set_positions\n");
|
||||
}
|
||||
|
||||
|
@@ -617,6 +617,7 @@ enum {
|
||||
#define TEX_VD_RAW_16BIT 2
|
||||
#define TEX_VD_IMAGE_SEQUENCE 3
|
||||
#define TEX_VD_SMOKE 4
|
||||
#define TEX_VD_HAIR 5
|
||||
/* for voxels which use VoxelData->source_path */
|
||||
#define TEX_VD_IS_SOURCE_PATH(_format) (ELEM(_format, TEX_VD_BLENDERVOXEL, TEX_VD_RAW_8BIT, TEX_VD_RAW_16BIT))
|
||||
|
||||
|
@@ -1851,6 +1851,7 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
|
||||
{TEX_VD_IMAGE_SEQUENCE, "IMAGE_SEQUENCE", 0, "Image Sequence",
|
||||
"Generate voxels from a sequence of image slices"},
|
||||
{TEX_VD_SMOKE, "SMOKE", 0, "Smoke", "Render voxels from a Blender smoke simulation"},
|
||||
{TEX_VD_HAIR, "HAIR", 0, "Hair", "Render voxels from a Blender hair simulation"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
@@ -61,6 +62,7 @@
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_smoke_types.h"
|
||||
|
||||
@@ -364,6 +366,27 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_frame_hair(VoxelData *vd, int UNUSED(cfra))
|
||||
{
|
||||
Object *ob;
|
||||
ModifierData *md;
|
||||
bool found = false;
|
||||
|
||||
vd->dataset = NULL;
|
||||
if (vd->object == NULL) return;
|
||||
ob = vd->object;
|
||||
|
||||
if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_ParticleSystem))) {
|
||||
ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
|
||||
|
||||
if (pmd->psys && pmd->psys->clmd) {
|
||||
found |= implicit_hair_volume_get_texture_data(ob, pmd->psys->clmd, NULL, vd);
|
||||
}
|
||||
}
|
||||
|
||||
vd->ok = found;
|
||||
}
|
||||
|
||||
void cache_voxeldata(Tex *tex, int scene_frame)
|
||||
{
|
||||
VoxelData *vd = tex->vd;
|
||||
@@ -397,6 +420,9 @@ void cache_voxeldata(Tex *tex, int scene_frame)
|
||||
case TEX_VD_SMOKE:
|
||||
init_frame_smoke(vd, scene_frame);
|
||||
return;
|
||||
case TEX_VD_HAIR:
|
||||
init_frame_hair(vd, scene_frame);
|
||||
return;
|
||||
case TEX_VD_BLENDERVOXEL:
|
||||
BLI_path_abs(path, G.main->name);
|
||||
if (!BLI_exists(path)) return;
|
||||
|
Reference in New Issue
Block a user