* Added a new surface type "Waves" that simulates simple 2D wave motion.

* Optimized adjacency point searching for vertex surfaces.
* Separated adjacency code from effect system.
* Overall code cleaning and tweaking.
This commit is contained in:
Miika Hamalainen
2011-07-02 18:06:39 +00:00
parent c896fcae79
commit 9ae663154f
6 changed files with 586 additions and 253 deletions

View File

@@ -104,7 +104,12 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, bpy.types.Panel):
col.prop(brush, "paint_color", text="")
col.prop(brush, "paint_alpha", text="Alpha")
if (brush.brush_settings_context != "GENERAL"):
elif (brush.brush_settings_context == "WAVE"):
layout.prop(brush, "wave_type")
if (brush.wave_type != "REFLECT"):
split = layout.split(percentage=0.6)
split.prop(brush, "wave_factor")
else:
layout.label(text="-WIP-")
@@ -131,7 +136,7 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel):
split.prop(surface, "dry_speed", text="Dry Time")
split.prop(surface, "use_dry_log", text="Slow")
if (surface.surface_type != "IWAVE"):
if (surface.surface_type != "WAVE"):
if (surface.surface_type == "DISPLACE"):
layout.prop(surface, "use_dissolve", text="Dissolve:")
elif (surface.surface_type == "WEIGHT"):
@@ -144,6 +149,19 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel):
split.prop(surface, "dissolve_speed", text="Time")
split.prop(surface, "use_dissolve_log", text="Slow")
if (surface.surface_type == "WAVE"):
layout.prop(surface, "wave_open_borders")
split = layout.split()
col = split.column(align=True)
col.prop(surface, "wave_timescale")
col.prop(surface, "wave_speed")
col = split.column(align=True)
col.prop(surface, "wave_damping")
col.prop(surface, "wave_spring")
layout.label(text="Brush Group:")
layout.prop(surface, "brush_group", text="")
@@ -158,7 +176,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel):
if ((not md) or (md.dynamicpaint_type != 'CANVAS')):
return 0
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
return (surface and (not (surface.surface_format=="VERTEX" and surface.surface_type=="DISPLACE") ))
return (surface and not (surface.surface_format=="VERTEX" and (surface.surface_type=="DISPLACE" or surface.surface_type=="WAVE")))
def draw(self, context):
layout = self.layout
@@ -202,9 +220,10 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel):
sub = col.column()
sub.active = surface.do_output2
sub.prop(surface, "output_name2", text="Filename: ")
if (surface.surface_type == "DISPLACE"):
else:
col.prop(surface, "output_name", text="Filename: ")
col.prop(surface, "disp_type", text="Displace Type")
if (surface.surface_type == "DISPLACE"):
col.prop(surface, "disp_type", text="Displace Type")
layout.separator()
layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')

View File

@@ -24,8 +24,8 @@ typedef struct PaintSurfaceData {
void *format_data;
/* surface type data */
void *type_data;
/* paint effects data */
struct PaintEffectData *eff_data;
/* point neighbor data */
struct PaintAdjData *adj_data;
unsigned int total_points;
short samples;
@@ -49,27 +49,28 @@ typedef struct PaintPoint {
float alpha;
} PaintPoint;
/* iWave type surface point */
typedef struct PaintIWavePoint {
float source;
float obstruction;
float height, previousHeight;
/* heigh field waves */
typedef struct PaintWavePoint {
float height;
float velocity;
short state; /* 0 = neutral
* 1 = obstacle
* 2 = reflect only */
float foam;
float verticalDerivative;
} PaintIWavePoint;
} PaintWavePoint;
struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
void dynamicPaint_cacheUpdateFrames(struct DynamicPaintSurface *surface);
int dynamicPaint_resetSurface(struct DynamicPaintSurface *surface);
int dynamicPaint_surfaceHasPreview(DynamicPaintSurface *surface);
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface);
void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, char *basename);
void dynamicPaint_Modifier_free (struct DynamicPaintModifierData *pmd);
void dynamicPaint_Modifier_createType(struct DynamicPaintModifierData *pmd);
void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tsmd);
void dynamicPaint_cacheUpdateFrames(struct DynamicPaintSurface *surface);
void dynamicPaint_clearSurface(DynamicPaintSurface *surface);
int dynamicPaint_resetSurface(struct DynamicPaintSurface *surface);
int dynamicPaint_surfaceHasPreview(DynamicPaintSurface *surface);
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface);
void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, char *basename);
#endif /* BKE_DYNAMIC_PAINT_H_ */

View File

@@ -166,20 +166,23 @@ typedef struct EffVelPoint {
float previous_vel[3];
} EffVelPoint;
typedef struct EffBakeNPoint {
typedef struct BakeNeighPoint {
float dir[3]; /* vector pointing towards this neighbour */
float dist; /* distance to */
} EffBakeNPoint;
} BakeNeighPoint;
typedef struct PaintEffectData {
/* adjacency data flags */
#define ADJ_ON_MESH_EDGE (1<<0)
typedef struct PaintAdjData {
unsigned int *n_index; /* total_points sized index array */
unsigned int *numOf_n; /* num of neighs for each point */
unsigned int *n_target; /* array of neighbouring point indexes
for single sample use n_index+neigh_num */
unsigned int *flags; /* for each point */
unsigned int total_targets; /* size of n_target */
unsigned int most_neighs;
//EffVelPoint *v_point;
} PaintEffectData;
} PaintAdjData;
/***************************** General Utils ******************************/
@@ -286,8 +289,8 @@ void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface) {
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
strcat(surface->output_name,"weight");
}
else if (surface->type == MOD_DPAINT_SURFACE_T_IWAVE) {
strcat(surface->output_name,"iwave");
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
strcat(surface->output_name,"wave");
strcat(surface->output_name2,"foam");
}
@@ -354,11 +357,12 @@ static void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
static void dynamicPaint_freeEffectData(PaintSurfaceData *data)
{
if (data->eff_data) {
if (data->eff_data->n_index) MEM_freeN(data->eff_data->n_index);
if (data->eff_data->numOf_n) MEM_freeN(data->eff_data->numOf_n);
if (data->eff_data->n_target) MEM_freeN(data->eff_data->n_target);
MEM_freeN(data->eff_data);
if (data->adj_data) {
if (data->adj_data->n_index) MEM_freeN(data->adj_data->n_index);
if (data->adj_data->numOf_n) MEM_freeN(data->adj_data->numOf_n);
if (data->adj_data->n_target) MEM_freeN(data->adj_data->n_target);
if (data->adj_data->flags) MEM_freeN(data->adj_data->flags);
MEM_freeN(data->adj_data);
}
}
@@ -474,6 +478,11 @@ static DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSett
surface->spread_speed = 1.0f;
surface->shrink_speed = 1.0f;
surface->wave_damping = 0.05f;
surface->wave_speed = 0.8f;
surface->wave_timescale = 1.0f;
surface->wave_spring = 0.20;
sprintf(surface->image_output_path, "%sdynamicpaint/", "/tmp/");
dynamicPaintSurface_setUniqueName(surface, "Surface");
@@ -534,8 +543,10 @@ void dynamicPaint_Modifier_createType(struct DynamicPaintModifierData *pmd)
pmd->brush->displace_distance = 0.5f;
pmd->brush->prox_displace_strength = 0.5f;
pmd->brush->particle_radius = 0.2;
pmd->brush->particle_smooth = 0.05;
pmd->brush->particle_radius = 0.2f;
pmd->brush->particle_smooth = 0.05f;
pmd->brush->wave_factor = 1.0f;
pmd->brush->dm = NULL;
@@ -636,22 +647,27 @@ static void dynamicPaint_allocateSurfaceType(DynamicPaintSurface *surface)
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
sData->type_data = MEM_callocN(sizeof(float)*sData->total_points, "DynamicPaintSurface WeightData");
}
else if (surface->type == MOD_DPAINT_SURFACE_T_IWAVE) {
sData->type_data = MEM_callocN(sizeof(PaintIWavePoint)*sData->total_points, "DynamicPaintSurface iWaveData");
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
sData->type_data = MEM_callocN(sizeof(PaintWavePoint)*sData->total_points, "DynamicPaintSurface WaveData");
}
else return;
if (sData->type_data == NULL) printError(surface->canvas, "Not enough free memory!");
}
static int surface_usesNeighData(DynamicPaintSurface *surface) {
return (surface->type == MOD_DPAINT_SURFACE_T_PAINT ||
surface->type == MOD_DPAINT_SURFACE_T_WAVE);
}
/* initialize "paint effect" data */
static void dynamicPaint_initEffectData(DynamicPaintSurface *surface) {
/* initialize surface adjacency data */
static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface) {
PaintSurfaceData *sData = surface->data;
PaintEffectData *ed;
PaintAdjData *ed;
int *temp_data;
int neigh_points = 0;
if (!surface->effect) return;
if (!surface->effect && !surface_usesNeighData(surface)) return;
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
/* For vertex format, neighbours are connected by edges */
@@ -663,58 +679,110 @@ static void dynamicPaint_initEffectData(DynamicPaintSurface *surface) {
if (!neigh_points) return;
/* allocate memory */
ed = sData->eff_data = MEM_callocN(sizeof(PaintEffectData), "Surface Effect Data");
ed = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data");
if (!ed) return;
ed->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Effect Index");
ed->numOf_n = MEM_callocN(sizeof(int)*sData->total_points, "Surface Effect Counts");
ed->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Effect Neighs");
ed->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index");
ed->numOf_n = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts");
temp_data = MEM_callocN(sizeof(int)*sData->total_points, "Temp Adj Data");
ed->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets");
ed->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags");
ed->total_targets = neigh_points;
ed->most_neighs = 0;
/* in case of error, free allocated memory */
if (!ed->n_index || !ed->numOf_n || !ed->n_target) {
if (!ed->n_index || !ed->numOf_n || !ed->n_target || !temp_data) {
dynamicPaint_freeEffectData(sData);
MEM_freeN(temp_data);
printError(surface->canvas, "Not enough free memory.");
return;
}
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
int i,j;
int i;
int n_pos;
/* For vertex format, count every vertex that is connected by an edge */
int numOfEdges = surface->canvas->dm->getNumEdges(surface->canvas->dm);
int numOfFaces = surface->canvas->dm->getNumFaces(surface->canvas->dm);
struct MEdge *edge = surface->canvas->dm->getEdgeArray(surface->canvas->dm);
struct MFace *face = surface->canvas->dm->getFaceArray(surface->canvas->dm);
/* add neighbour data */
/* count number of edges per vertex */
for (i=0; i<numOfEdges; i++) {
ed->numOf_n[edge[i].v1]++;
ed->numOf_n[edge[i].v2]++;
temp_data[edge[i].v1]++;
temp_data[edge[i].v2]++;
}
/* to locate points on "mesh edge" */
for (i=0; i<numOfFaces; i++) {
temp_data[face[i].v1]++;
temp_data[face[i].v2]++;
temp_data[face[i].v3]++;
if (face[i].v4)
temp_data[face[i].v4]++;
}
/* now check if total number of edges+faces for
* each vertex is even, if not -> vertex is on mesh edge */
for (i=0; i<sData->total_points; i++) {
if ((temp_data[i]%2) ||
temp_data[i] < 4)
ed->flags[i] |= ADJ_ON_MESH_EDGE;
/* reset temp data */
temp_data[i] = 0;
}
/* order n_index array */
n_pos = 0;
for (i=0; i<sData->total_points; i++) {
ed->n_index[i] = n_pos;
ed->numOf_n[i] = 0;
n_pos += ed->numOf_n[i];
}
for (j=0; j<numOfEdges; j++) {
if (edge[j].v1 == i) {
ed->n_target[n_pos] = edge[j].v2;
ed->numOf_n[i]++;
n_pos++;
}
else if (edge[j].v2 == i) {
ed->n_target[n_pos] = edge[j].v1;
ed->numOf_n[i]++;
n_pos++;
}
}
if (ed->numOf_n[i] > ed->most_neighs)
ed->most_neighs = ed->numOf_n[i];
/* and now add neighbour data using that info */
for (i=0; i<numOfEdges; i++) {
/* first vertex */
int index = edge[i].v1;
n_pos = ed->n_index[index]+temp_data[index];
ed->n_target[n_pos] = edge[i].v2;
temp_data[index]++;
/* second vertex */
index = edge[i].v2;
n_pos = ed->n_index[index]+temp_data[index];
ed->n_target[n_pos] = edge[i].v1;
temp_data[index]++;
}
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
/* for image sequences, only allocate memory.
* bake initialization takes care of rest */
}
MEM_freeN(temp_data);
}
/* (re)initialize surface data (only for point cache types)*/
/* clears surface data back to zero */
void dynamicPaint_clearSurface(DynamicPaintSurface *surface) {
PaintSurfaceData *sData = surface->data;
if (sData && sData->type_data) {
unsigned int data_size;
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
data_size = sizeof(PaintPoint);
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
data_size = sizeof(PaintWavePoint);
else
data_size = sizeof(float);
memset(sData->type_data, 0, data_size * sData->total_points);
}
}
/* completely (re)initializes surface (only for point cache types)*/
int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
{
int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
@@ -732,7 +800,7 @@ int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
surface->data->total_points = numOfPoints;
surface->data->samples = 1;
dynamicPaint_allocateSurfaceType(surface);
dynamicPaint_initEffectData(surface);
dynamicPaint_initAdjacencyData(surface);
return 1;
}
@@ -988,7 +1056,7 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
* able to share same drawing methods */
MFace *mface = result->getFaceArray(result);
int numOfFaces = result->getNumFaces(result);
int i,j;
int i;
MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
@@ -1050,6 +1118,24 @@ struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, S
}
}
}
/* wave simulation */
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
MVert *mvert = result->getVertArray(result);
int i;
float normal[3];
PaintWavePoint* wPoint = (PaintWavePoint*)surface->data->type_data;
for (i=0; i<surface->data->total_points; i++) {
normal_short_to_float_v3(normal, mvert[i].no);
normalize_v3(normal);
mvert[i].co[0] += normal[0]*wPoint[i].height;
mvert[i].co[1] += normal[1]*wPoint[i].height;
mvert[i].co[2] += normal[2]*wPoint[i].height;
}
CDDM_calc_normals(result);
}
}
}
}
@@ -1133,7 +1219,6 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
*/
{
int numOfFaces = dm->getNumFaces(dm);
MVert *mvert = dm->getVertArray(dm);
MFace *mface = dm->getFaceArray(dm);
MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
@@ -1607,7 +1692,7 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
/* If any effect enabled, create surface effect / wet layer
* neighbour lists. Processes possibly moving data. */
if (surface->effect) {
if (surface_usesNeighData(surface)) {
int i, cursor=0;
@@ -1622,10 +1707,10 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
/* allocate memory */
sData->total_points = w*h;
dynamicPaint_initEffectData(surface);
dynamicPaint_initAdjacencyData(surface);
if (sData->eff_data) {
PaintEffectData *ed = sData->eff_data;
if (sData->adj_data) {
PaintAdjData *ed = sData->adj_data;
unsigned int n_pos = 0;
//#pragma omp parallel for schedule(static)
for (yy = 0; yy < h; yy++)
@@ -1634,7 +1719,6 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
for (xx = 0; xx < w; xx++)
{
int i, index = xx+w*yy;
PaintUVPoint *tPoint = (&tempPoints[index]);
if (tempPoints[index].face_index != -1) {
ed->n_index[final_index[index]] = n_pos;
@@ -1652,10 +1736,6 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
n_pos++;
}
}
if (ed->numOf_n[final_index[index]] > ed->most_neighs)
ed->most_neighs = ed->numOf_n[final_index[index]];
}
}
}
@@ -1707,7 +1787,6 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
/* Init surface type data */
if (!error) {
int index;
dynamicPaint_allocateSurfaceType(surface);
#if 0
@@ -1739,7 +1818,7 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
#define DPOUTPUT_PAINT 0
#define DPOUTPUT_WET 1
#define DPOUTPUT_DISPLACE 2
#define DPOUTPUT_IWAVE 3
#define DPOUTPUT_WAVES 3
/*
* Outputs an image file from uv surface data.
@@ -1810,6 +1889,15 @@ void dynamicPaint_outputImage(DynamicPaintSurface *surface, char* filename, shor
if (depth > 1.0f) depth = 1.0f;
}
mhImgB->rect_float[pos]=depth;
mhImgB->rect_float[pos+1]=depth;
mhImgB->rect_float[pos+2]=depth;
mhImgB->rect_float[pos+3]=1.0f;
}
else if (type == DPOUTPUT_WAVES) {
PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
float depth = wPoint->height/2.0f+0.5f;
mhImgB->rect_float[pos]=depth;
mhImgB->rect_float[pos+1]=depth;
mhImgB->rect_float[pos+2]=depth;
@@ -2435,7 +2523,7 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float *
* timescale : value used to adjust time dependand
* operations when using substeps
*/
void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags, float *paintColor, float *paintAlpha, float *paintWetness, float *timescale)
static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags, float *paintColor, float *paintAlpha, float *paintWetness, float *timescale)
{
PaintPoint *pPoint = &((PaintPoint*)surface->data->type_data)[index];
@@ -2491,6 +2579,30 @@ void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int pa
}
}
static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint, DynamicPaintBrushSettings *brush, float isect_height)
{
int hit = 0;
isect_height *= brush->wave_factor;
/* determine hit depending on wave_factor */
if (brush->wave_factor > 0.0f && wPoint->height > isect_height)
hit = 1;
else if (brush->wave_factor < 0.0f && wPoint->height < isect_height)
hit = 1;
if (hit) {
if (brush->wave_type == MOD_DPAINT_WAVEB_DEPTH) {
wPoint->height = isect_height;
wPoint->state = 1;
wPoint->velocity = 0.0f;
}
else if (brush->wave_type == MOD_DPAINT_WAVEB_FORCE)
wPoint->velocity = isect_height;
else if (brush->wave_type == MOD_DPAINT_WAVEB_REFLECT)
wPoint->state = 2;
}
}
/*
* Paint a brush object mesh to the surface
*/
@@ -2757,6 +2869,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, PaintBakeData *b
*/
dynamicPaint_mixPaintColors(surface, index, brush->flags, paintColor, &paintAlpha, &paintWetness, &timescale);
}
/* displace */
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
float *value = (float*)sData->type_data;
@@ -2770,6 +2883,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, PaintBakeData *b
if (value[index] < depth) value[index] = depth;
}
}
/* vertex weight */
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
float *value = (float*)sData->type_data;
@@ -2787,6 +2901,13 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, PaintBakeData *b
}
}
}
/* wave */
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
depth *= -1.0f/bData->bPoint[index].normal_scale;
dynamicPaint_mixWaveHeight(&((PaintWavePoint*)surface->data->type_data)[index],
brush, depth);
}
}
}
}
@@ -2970,6 +3091,18 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, PaintBakeDa
if (value[index] < strength) value[index] = strength;
}
}
/* wave */
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
float sdepth;
/* change falloff type to inverse square to match real displace depth */
disp_intersect = (1.0f - sqrt(disp_intersect / radius)) * radius;
/* get displace depth */
sdepth = -1.0f * (radius - disp_intersect) / bData->bPoint[index].normal_scale;
dynamicPaint_mixWaveHeight(&((PaintWavePoint*)surface->data->type_data)[index],
brush, sdepth);
}
}
BLI_kdtree_free(tree);
@@ -2979,6 +3112,35 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, PaintBakeDa
/***************************** Dynamic Paint Step / Baking ******************************/
/*
* Calculate current frame neighbouring point distances
* and direction vectors
*/
static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, BakeNeighPoint *bNeighs, float *realCoords)
{
PaintSurfaceData *sData = surface->data;
int index;
#pragma omp parallel for schedule(static)
for (index = 0; index < sData->total_points; index++)
{
int i;
int numOfNeighs = sData->adj_data->numOf_n[index];
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->adj_data->n_index[index]+i;
int t_index = sData->adj_data->n_target[n_index];
/* dir vec */
sub_v3_v3v3(bNeighs[n_index].dir, &realCoords[t_index*3], &realCoords[index*3]);
/* dist */
bNeighs[n_index].dist = len_v3(bNeighs[n_index].dir);
/* normalize dir */
if (bNeighs[n_index].dist) mul_v3_fl(bNeighs[n_index].dir, 1.0f/bNeighs[n_index].dist);
}
}
}
/* paint effect default movement per frame in global units */
#define EFF_MOVEMENT_PER_FRAME 0.05f
@@ -2986,7 +3148,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, PaintBakeDa
* Prepare data required by effects for current frame.
* Returns number of steps required
*/
static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *scene, Object *ob, EffBakeNPoint *eNeighs, float **force, float *realCoords, float timescale)
static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *scene, Object *ob, BakeNeighPoint *bNeighs, float **force, float *realCoords, float timescale)
{
double average_dist = 0.0f;
double average_force = 0.0f;
@@ -2999,7 +3161,6 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
/* Init force data if required */
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
float vel[3] = {0};
float f_t[3];
ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights);
/* allocate memory for force data (dir vector + strength) */
@@ -3036,44 +3197,21 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
pdEndEffectors(&effectors);
}
/*
* Calculate current frame neighbouring pixel distances
* and average distance between those neighbours
*/
#pragma omp parallel for schedule(static)
/* calculate average values (single thread) */
for (index = 0; index < sData->total_points; index++)
{
int i;
int numOfNeighs = sData->eff_data->numOf_n[index];
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->eff_data->n_index[index]+i;
int t_index = sData->eff_data->n_target[n_index];
/* dir vec */
sub_v3_v3v3(eNeighs[n_index].dir, &realCoords[t_index*3], &realCoords[index*3]);
/* dist */
eNeighs[n_index].dist = len_v3(eNeighs[n_index].dir);
/* normalize dir */
if (eNeighs[n_index].dist) mul_v3_fl(eNeighs[n_index].dir, 1.0f/eNeighs[n_index].dist);
}
}
/* calculate average values single thread */
for (index = 0; index < sData->total_points; index++)
{
int i;
int numOfNeighs = sData->eff_data->numOf_n[index];
int numOfNeighs = sData->adj_data->numOf_n[index];
if (*force)
average_force += (*force)[index*4+3];
for (i=0; i<numOfNeighs; i++) {
average_dist += eNeighs[sData->eff_data->n_index[index]+i].dist;
average_dist += bNeighs[sData->adj_data->n_index[index]+i].dist;
}
}
average_force /= sData->total_points;
average_dist /= sData->eff_data->total_targets;
average_dist /= sData->adj_data->total_targets;
/* Get number of required steps using averate point distance
* so that just a few ultra close pixels wont up substeps to max */
@@ -3097,12 +3235,12 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
/*
* Processes active effect step.
*/
static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, EffBakeNPoint *eNeighs, float *force, PaintPoint *prevPoint, float timescale)
static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, BakeNeighPoint *bNeighs, float *force, PaintPoint *prevPoint, float timescale)
{
PaintSurfaceData *sData = surface->data;
int index;
if (!sData->eff_data) return;
if (!sData->adj_data) return;
/*
* Spread Effect
*/
@@ -3116,7 +3254,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, EffBakeNPoin
for (index = 0; index < sData->total_points; index++)
{
int i;
int numOfNeighs = sData->eff_data->numOf_n[index];
int numOfNeighs = sData->adj_data->numOf_n[index];
float totalAlpha = 0.0f;
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
@@ -3127,10 +3265,10 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, EffBakeNPoin
/* Loop through neighbouring points */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->eff_data->n_index[index]+i;
int n_index = sData->adj_data->n_index[index]+i;
float w_factor, alphaAdd = 0.0f;
PaintPoint *ePoint = &prevPoint[sData->eff_data->n_target[n_index]];
float speed_scale = (eNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/eNeighs[n_index].dist;
PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
totalAlpha += ePoint->e_alpha;
@@ -3174,14 +3312,14 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, EffBakeNPoin
for (index = 0; index < sData->total_points; index++)
{
int i;
int numOfNeighs = sData->eff_data->numOf_n[index];
int numOfNeighs = sData->adj_data->numOf_n[index];
float totalAlpha = 0.0f;
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->eff_data->n_index[index]+i;
float speed_scale = (eNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/eNeighs[n_index].dist;
PaintPoint *ePoint = &prevPoint[sData->eff_data->n_target[n_index]];
int n_index = sData->adj_data->n_index[index]+i;
float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
float a_factor, ea_factor, w_factor;
totalAlpha += ePoint->e_alpha;
@@ -3222,99 +3360,89 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, EffBakeNPoin
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force)
{
float eff_scale = EFF_MOVEMENT_PER_FRAME*timescale/10.0f;
float *str = MEM_callocN(sData->eff_data->most_neighs*sizeof(float), "PaintEffectForces");
for (index = 0; index < sData->total_points; index++) {
int i;
int numOfNeighs = sData->adj_data->numOf_n[index];
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
/* Copy current surface to the previous points array to read unmodified values */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
/* to make dripping happen with as little spread as possible,
* only use two closest point dirs "around" the force dir */
int closest_id[2] = {-1, -1};
float closest_d[2] = {-1.0f, -1.0f};
if (str)
{
for (index = 0; index < sData->total_points; index++) {
int i;
int numOfNeighs = sData->eff_data->numOf_n[index];
float totalStr = 0.0f, str_factor;
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
/* adjust drip speed depending on wetness */
float w_factor = pPoint->wetness*0.4 - 0.05f;
if (w_factor <= 0) continue;
w_factor *= w_factor;
/* to make dripping happen with as little spread as possible,
* find two closest point dirs around the force dir */
int closest_id[2] = {-1, -1};
float closest_d[2] = {-1.0f, -1.0f};
/* find closest neigh dir */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->adj_data->n_index[index]+i;
float dir_dot = dot_v3v3(bNeighs[n_index].dir, &force[index*4]);
/* find closest neigh dir */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->eff_data->n_index[index]+i;
float dir_dot = dot_v3v3(eNeighs[n_index].dir, &force[index*4]);
if (dir_dot>closest_d[0] && dir_dot>0.0f) {closest_d[0]=dir_dot; closest_id[0]=n_index;}
}
if (dir_dot>closest_d[0] && dir_dot>0.0f) {closest_d[0]=dir_dot; closest_id[0]=n_index;}
}
/* find other neigh */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->adj_data->n_index[index]+i;
float dir_dot = dot_v3v3(bNeighs[n_index].dir, &force[index*4]);
float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir);
/* find other neigh */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->eff_data->n_index[index]+i;
float dir_dot = dot_v3v3(eNeighs[n_index].dir, &force[index*4]);
float closest_dot = dot_v3v3(eNeighs[n_index].dir, eNeighs[closest_id[0]].dir);
if (n_index == closest_id[0]) continue;
if (n_index == closest_id[0]) continue;
/* only accept neighbour at "other side" of the first one in relation to force dir
* so make sure angle between this and closest neigh is greater than first angle */
if (dir_dot>closest_d[1] && closest_dot<closest_d[0] && dir_dot>0.0f) {closest_d[1]=dir_dot; closest_id[1]=n_index;}
}
/* only accept neighbour at "other side" of the first one in relation to force dir
* so make sure angle between this and closest neigh is greater than first angle */
if (dir_dot>closest_d[1] && closest_dot<closest_d[0] && dir_dot>0.0f) {closest_d[1]=dir_dot; closest_id[1]=n_index;}
}
/* if two valid neighs found, change closest_d
* values to match final paint factors */
if (closest_id[1] != -1) {
float neigh_diff = dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
/* linearize both values */
neigh_diff *= neigh_diff;
closest_d[0] *= closest_d[0];
/* if two valid neighs found, change closest_d
* values to match final paint factors */
if (closest_id[1] != -1) {
float neigh_diff = dot_v3v3(eNeighs[closest_id[0]].dir, eNeighs[closest_id[1]].dir);
/* linearize both values */
neigh_diff *= neigh_diff;
closest_d[0] *= closest_d[0];
/* get relation to angle between neighs */
closest_d[0] -= neigh_diff;
/* and normalize as relative angle within neigh range */
closest_d[0] /= 1.0f - neigh_diff;
/* get relation to angle between neighs */
closest_d[0] -= neigh_diff;
/* and normalize as relative angle within neigh range */
closest_d[0] /= 1.0f - neigh_diff;
/* simply set other neigh to cover missing half of this factor */
closest_d[1] = 1.0f - closest_d[0];
}
else if (closest_id[0] != -1) {
/* if only one neigh, still linearize to minimize spread */
closest_d[0] *= closest_d[0];
}
/* simply set other neigh to cover missing half of this factor */
closest_d[1] = 1.0f - closest_d[0];
}
else if (closest_id[0] != -1) {
/* if only one neigh, still linearize to minimize spread */
closest_d[0] *= closest_d[0];
}
/* Apply movement towards those two points */
for (i=0; i<2; i++) {
int n_index = closest_id[i];
if (n_index != -1 && closest_d[i]>0.0f) {
float dir_dot = closest_d[i], dir_factor, w_factor;
float speed_scale = eff_scale*force[index*4+3]/eNeighs[n_index].dist;
PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->eff_data->n_target[n_index]];
/* Apply movement towards those two points */
for (i=0; i<2; i++) {
int n_index = closest_id[i];
if (n_index != -1 && closest_d[i]>0.0f) {
float dir_dot = closest_d[i], dir_factor;
float speed_scale = eff_scale*force[index*4+3]/bNeighs[n_index].dist;
PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
/* just skip if angle is too extreme */
if (dir_dot <= 0.0f) continue;
/* just skip if angle is too extreme */
if (dir_dot <= 0.0f) continue;
/* adjust drip speed depending on wetness */
w_factor = pPoint->wetness*0.4 - 0.05f;
if (w_factor <= 0) continue;
w_factor *= w_factor;
dir_factor = dir_dot * speed_scale * w_factor;
if (dir_factor > 1.0f) dir_factor = 1.0f;
dir_factor = dir_dot * speed_scale * w_factor;
if (dir_factor > 1.0f) dir_factor = 1.0f;
/* mix new color */
mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, dir_factor);
/* mix new color */
mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, dir_factor);
ePoint->e_alpha += dir_factor;
ePoint->wetness += dir_factor;
if (ePoint->e_alpha > 1.0f) ePoint->e_alpha = 1.0f;
ePoint->e_alpha += dir_factor;
ePoint->wetness += dir_factor;
if (ePoint->e_alpha > 1.0f) ePoint->e_alpha = 1.0f;
/* and decrease paint wetness on current point */
pPoint->wetness -= dir_factor;
}
/* and decrease paint wetness on current point */
pPoint->wetness -= dir_factor;
}
}
MEM_freeN(str);
}
/* Keep values within acceptable range */
@@ -3332,6 +3460,113 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, EffBakeNPoin
}
}
#define WAVE_TIME_FAC 0.1
void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, BakeNeighPoint *bNeighs, float timescale)
{
PaintSurfaceData *sData = surface->data;
int index;
int steps, ss;
float dt, min_dist, damp_factor;
float wave_speed = surface->wave_speed;
double average_dist = 0.0f;
/* allocate memory */
PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points*sizeof(PaintWavePoint), "Temp previous points for wave simulation");
if (!prevPoint) return;
/* calculate average neigh distance (single thread) */
for (index = 0; index < sData->total_points; index++)
{
int i;
int numOfNeighs = sData->adj_data->numOf_n[index];
for (i=0; i<numOfNeighs; i++) {
average_dist += bNeighs[sData->adj_data->n_index[index]+i].dist;
}
}
average_dist /= sData->adj_data->total_targets;
/* determine number of required steps */
steps = ceil((WAVE_TIME_FAC*timescale*surface->wave_timescale) / (average_dist/wave_speed/3));
CLAMP(steps, 1, 15);
timescale /= steps;
/* apply simulation values for final timescale */
dt = WAVE_TIME_FAC*timescale*surface->wave_timescale;
min_dist = wave_speed*dt*1.5f;
damp_factor = pow((1.0f-surface->wave_damping), 1.0f*timescale);
for (ss=0; ss<steps; ss++) {
/* copy previous frame data */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(PaintWavePoint));
#pragma omp parallel for schedule(static)
for (index = 0; index < sData->total_points; index++) {
PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
int numOfNeighs = sData->adj_data->numOf_n[index];
float force = 0.0f, avg_dist = 0.0f, avg_height = 0.0f;
int numOfN = 0, numOfRN = 0;
int i;
if (wPoint->state) continue;
/* calculate force from surrounding points */
for (i=0; i<numOfNeighs; i++) {
int n_index = sData->adj_data->n_index[index]+i;
float dist = bNeighs[n_index].dist;
PaintWavePoint *tPoint = &prevPoint[sData->adj_data->n_target[n_index]];
if (!dist || tPoint->state) continue;
if (dist<min_dist) dist=min_dist;
avg_dist += dist;
numOfN++;
/* count average height for edge points for open borders */
if (!(sData->adj_data->flags[sData->adj_data->n_target[n_index]] & ADJ_ON_MESH_EDGE)) {
avg_height += tPoint->height;
numOfRN++;
}
force += (tPoint->height - wPoint->height) / (dist*dist);
}
avg_dist = (numOfN) ? avg_dist/numOfN : 0.0f;
if (surface->flags & MOD_DPAINT_WAVE_OPEN_BORDERS &&
sData->adj_data->flags[index] & ADJ_ON_MESH_EDGE) {
/* if open borders, apply a fake height to keep waves going on */
avg_height = (numOfRN) ? avg_height/numOfRN : 0.0f;
wPoint->height = (dt*wave_speed*avg_height + wPoint->height*avg_dist) / (avg_dist + dt*wave_speed);
}
/* else, do wave eq */
else {
/* add force towards zero height based on average dist */
if (avg_dist)
force += (0.0f - wPoint->height) * surface->wave_spring / (avg_dist*avg_dist) / 2.0f;
/* change point velocity */
wPoint->velocity += force*dt * wave_speed*wave_speed;
/* damping */
wPoint->velocity *= damp_factor;
/* and new height */
wPoint->height += wPoint->velocity*dt;
}
}
}
/* reset d_obs and state */
for (index = 0; index < sData->total_points; index++) {
PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
wPoint->state = 0;
}
MEM_freeN(prevPoint);
}
#define VALUE_DISSOLVE(VALUE, SPEED, SCALE, LOG) (VALUE) = (LOG) ? (VALUE) * 1.0f - 1.0f/((SPEED)/(SCALE)) : (VALUE) - 1.0f/(SPEED)*(SCALE)
/* Prepare for surface step by creating PaintBakePoint data */
@@ -3483,7 +3718,8 @@ static int dynamicPaint_prepareSurfaceStep(DynamicPaintSurface *surface, PaintBa
}
/* Prepare special data for surface types */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
float temp_nor[3];
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX)
{normal_short_to_float_v3(temp_nor, mvert[index].no);
@@ -3657,45 +3893,58 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
MEM_freeN(bData.bPoint);
/* paint movement effects */
if (surface->effect && surface->type == MOD_DPAINT_SURFACE_T_PAINT && sData->eff_data)
/* neighbour data and surface opretions that use it */
if (sData->adj_data)
{
int steps = 1, s;
PaintPoint *prevPoint;
EffBakeNPoint *eNeighs;
float *force = NULL;
BakeNeighPoint *bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeNeighPoint), "PaintEffectBake");
/* free antialias sample coords, as theyre not needed anymore */
if (sData->samples>1) bData.realCoord = MEM_reallocN(bData.realCoord, sData->total_points*3*sizeof(float));
/* neighbouring point distances and dirs */
eNeighs = MEM_mallocN(sData->eff_data->total_targets*sizeof(struct EffBakeNPoint), "PaintEffectBake");
/* Allocate memory for surface previous points to read unchanged values from */
prevPoint = MEM_mallocN(sData->total_points*sizeof(struct PaintPoint), "PaintSurfaceDataCopy");
if (bNeighs) {
/* calculate current frame distances and global dirs */
dynamicPaint_prepareNeighbourData(surface, bNeighs, bData.realCoord);
/* in case of error, free already allocated blocks */
if (!prevPoint || !eNeighs || !bData.realCoord) {
if (!bData.realCoord) MEM_freeN(bData.realCoord);
if (!eNeighs) MEM_freeN(eNeighs);
if (!prevPoint) MEM_freeN(prevPoint);
/* wave type surface simulation step */
if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
dynamicPaint_doWaveStep(surface, bNeighs, timescale);
}
return printError(canvas, "Not enough free memory.");
/* paint movement effects */
if (surface->effect && surface->type == MOD_DPAINT_SURFACE_T_PAINT)
{
int steps = 1, s;
PaintPoint *prevPoint;
float *force = NULL;
/* free antialias sample coords, as theyre not needed anymore */
if (sData->samples>1) bData.realCoord = MEM_reallocN(bData.realCoord, sData->total_points*3*sizeof(float));
/* Allocate memory for surface previous points to read unchanged values from */
prevPoint = MEM_mallocN(sData->total_points*sizeof(struct PaintPoint), "PaintSurfaceDataCopy");
/* in case of error, free already allocated blocks */
if (!prevPoint || !bData.realCoord) {
if (!bData.realCoord) MEM_freeN(bData.realCoord);
if (!prevPoint) MEM_freeN(prevPoint);
return printError(canvas, "Not enough free memory.");
}
/* Prepare effects and get number of required steps */
steps = dynamicPaint_prepareEffectStep(surface, scene, ob, bNeighs, &force, bData.realCoord, timescale);
/*
* Do Effects steps
*/
for (s = 0; s < steps; s++)
{
dynamicPaint_doEffectStep(surface, bNeighs, force, prevPoint, timescale/(float)steps);
}
/* Free temporary effect data */
if (prevPoint) MEM_freeN(prevPoint);
if (force) MEM_freeN(force);
}
MEM_freeN(bNeighs);
}
/* Prepare effects and get number of required steps */
steps = dynamicPaint_prepareEffectStep(surface, scene, ob, eNeighs, &force, bData.realCoord, timescale);
/*
* Do Effects steps
*/
for (s = 0; s < steps; s++)
{
dynamicPaint_doEffectStep(surface, eNeighs, force, prevPoint, timescale/(float)steps);
}
/* Free temporary effect data */
if (eNeighs) MEM_freeN(eNeighs);
if (prevPoint) MEM_freeN(prevPoint);
if (force) MEM_freeN(force);
}
MEM_freeN(bData.realCoord);
@@ -3830,10 +4079,16 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf
}
/* displacement map */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
sprintf(filename, "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame);
dynamicPaint_outputImage(surface, filename, format, DPOUTPUT_DISPLACE);
}
/* waves */
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
sprintf(filename, "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame);
dynamicPaint_outputImage(surface, filename, format, DPOUTPUT_WAVES);
}
}
}
return 1;

View File

@@ -683,17 +683,17 @@ static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
/* cache type */
ptcache_file_write(pf, &surface->type, 1, sizeof(int));
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
in_len = sizeof(PaintPoint)*total_points;
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
}
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
in_len = sizeof(float)*total_points;
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
}
if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
in_len = sizeof(PaintWavePoint)*total_points;
else return 0;
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
ptcache_file_compressed_write(pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
MEM_freeN(out);
@@ -725,6 +725,8 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
data_len = sizeof(float);
if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
data_len = sizeof(PaintWavePoint);
else return 0;
ptcache_file_compressed_read(pf, (unsigned char*)surface->data->type_data, data_len*surface->data->total_points);
@@ -2413,7 +2415,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
smokeModifier_reset_turbulence(pid->calldata);
else if(pid->type == PTCACHE_TYPE_DYNAMICPAINT)
dynamicPaint_resetSurface((DynamicPaintSurface*)pid->calldata);
dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata);
}
if(clear)
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);

View File

@@ -26,7 +26,7 @@ struct PaintSurfaceData;
#define MOD_DPAINT_SURFACE_T_PAINT 0
#define MOD_DPAINT_SURFACE_T_DISPLACE 1
#define MOD_DPAINT_SURFACE_T_WEIGHT 2
#define MOD_DPAINT_SURFACE_T_IWAVE 3
#define MOD_DPAINT_SURFACE_T_WAVE 3
/* surface flags */
#define MOD_DPAINT_ACTIVE (1<<0) /* Is surface enabled */
@@ -36,10 +36,10 @@ struct PaintSurfaceData;
#define MOD_DPAINT_MULALPHA (1<<3) /* Multiply color by alpha when saving image */
#define MOD_DPAINT_DISSOLVE_LOG (1<<4) /* Use 1/x for surface dissolve */
#define MOD_DPAINT_DRY_LOG (1<<5) /* Use 1/x for drying paint */
#define MOD_DPAINT_PREVIEW (1<<6) /* preview this surface on viewport*/
/* image sequence output */
#define MOD_DPAINT_WAVE_OPEN_BORDERS (1<<7) /* passes waves through mesh edges */
#define MOD_DPAINT_OUT1 (1<<10) /* output primary surface */
#define MOD_DPAINT_OUT2 (1<<11) /* output secondary surface */
@@ -88,7 +88,11 @@ typedef struct DynamicPaintSurface {
int dry_speed, diss_speed;
float disp_depth;
float spread_speed, shrink_speed, pad_f;
float spread_speed, shrink_speed;
/* wave settings */
float wave_damping, wave_speed, wave_timescale, wave_spring;
float pad_f;
char uvlayer_name[32];
char image_output_path[240];
@@ -123,7 +127,6 @@ typedef struct DynamicPaintCanvasSettings {
#define MOD_DPAINT_RAMP_ALPHA (1<<4) /* only read falloff ramp alpha */
#define MOD_DPAINT_PROX_FACEALIGNED (1<<5) /* do proximity check only in normal dir */
#define MOD_DPAINT_INVERSE_PROX (1<<6) /* inverse proximity painting */
//#define MOD_DPAINT_EDGE_DISP (1<<6) /* add displacement to intersection edges */
/* collision type */
#define MOD_DPAINT_COL_VOLUME 0 /* paint with mesh volume */
@@ -136,6 +139,11 @@ typedef struct DynamicPaintCanvasSettings {
#define MOD_DPAINT_PRFALL_SMOOTH 1 /* smooth, linear falloff */
#define MOD_DPAINT_PRFALL_RAMP 2 /* use color ramp */
/* wave_brush_type */
#define MOD_DPAINT_WAVEB_DEPTH 0 /* use intersection depth */
#define MOD_DPAINT_WAVEB_FORCE 1 /* act as a force on intersection area */
#define MOD_DPAINT_WAVEB_REFLECT 2 /* obstacle that reflects waves */
/* Painter settings */
typedef struct DynamicPaintBrushSettings {
@@ -159,9 +167,11 @@ typedef struct DynamicPaintBrushSettings {
short proximity_falloff;
short brush_settings_context; /* ui settings display */
int pad2; // replace if need for new value
short wave_type;
short pad_s;
//int pad;
float wave_factor;
float pad_f;
} DynamicPaintBrushSettings;
#endif

View File

@@ -220,14 +220,13 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
RNA_enum_item_add(&item, &totitem, &tmp);
}
/* iWave */
/*if (surface->format == MOD_DPAINT_SURFACE_F_PTEX ||
surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
tmp.value = MOD_DPAINT_SURFACE_T_IWAVE;
tmp.identifier = "IWAVE";
tmp.name = "iWave";
/* Height waves */
{
tmp.value = MOD_DPAINT_SURFACE_T_WAVE;
tmp.identifier = "WAVE";
tmp.name = "Waves";
RNA_enum_item_add(&item, &totitem, &tmp);
}*/
}
RNA_enum_item_end(&item, &totitem);
*free = 1;
@@ -507,6 +506,35 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_dynamicpaint_disp_type);
RNA_def_property_ui_text(prop, "Data Type", "");
/* wave simulator settings */
prop= RNA_def_property(srna, "wave_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "wave_damping");
RNA_def_property_range(prop, 0.001, 1.0);
RNA_def_property_ui_range(prop, 0.01, 1.0, 1, 2);
RNA_def_property_ui_text(prop, "Damping", "Wave damping factor.");
prop= RNA_def_property(srna, "wave_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "wave_speed");
RNA_def_property_range(prop, 0.01, 3.0);
RNA_def_property_ui_range(prop, 0.01, 1.5, 1, 2);
RNA_def_property_ui_text(prop, "Speed", "Wave speed.");
prop= RNA_def_property(srna, "wave_timescale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "wave_timescale");
RNA_def_property_range(prop, 0.01, 3.0);
RNA_def_property_ui_range(prop, 0.01, 1.5, 1, 2);
RNA_def_property_ui_text(prop, "Timescale", "Wave time scaling factor.");
prop= RNA_def_property(srna, "wave_spring", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "wave_spring");
RNA_def_property_range(prop, 0.01, 1.0);
RNA_def_property_ui_range(prop, 0.01, 1.0, 1, 2);
RNA_def_property_ui_text(prop, "Spring", "Spring force that pulls water level back to zero.");
prop= RNA_def_property(srna, "wave_open_borders", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_WAVE_OPEN_BORDERS);
RNA_def_property_ui_text(prop, "Open Borders", "Passes waves through mesh edges.");
/* cache */
prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
@@ -565,10 +593,16 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
{MOD_DPAINT_PRFALL_RAMP, "RAMP", 0, "Color Ramp", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem prop_dynamicpaint_brush_wave_type[] = {
{MOD_DPAINT_WAVEB_DEPTH, "DEPTH", 0, "Obstacle", ""},
{MOD_DPAINT_WAVEB_FORCE, "FORCE", 0, "Force", ""},
{MOD_DPAINT_WAVEB_REFLECT, "REFLECT", 0, "Reflect Only", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem buttons_dynamicpaint_settings_menu[] = {
{0, "GENERAL", ICON_MOD_DYNAMICPAINT, "", "Show general settings"},
{1, "DISPLACE", ICON_MOD_DISPLACE, "", "Show displace related settings"},
{3, "IWAVE", ICON_MOD_WAVE, "", "Show iWave related settings"},
//{1, "DISPLACE", ICON_MOD_DISPLACE, "", "Show displace related settings"},
{2, "WAVE", ICON_MOD_WAVE, "", "Show wave related settings"},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "DynamicPaintBrushSettings", NULL);
@@ -618,6 +652,18 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
prop= RNA_def_property(srna, "paint_erase", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_ERASE);
RNA_def_property_ui_text(prop, "Erase Paint", "Erase / remove paint instead of adding it.");
prop= RNA_def_property(srna, "wave_type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_sdna(prop, NULL, "wave_type");
RNA_def_property_enum_items(prop, prop_dynamicpaint_brush_wave_type);
RNA_def_property_ui_text(prop, "Paint Type", "");
prop= RNA_def_property(srna, "wave_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "wave_factor");
RNA_def_property_range(prop, -2.0, 2.0);
RNA_def_property_ui_range(prop, -1.0, 1.0, 1, 2);
RNA_def_property_ui_text(prop, "Factor", "Multiplier for wave strenght of this brush.");
/*
* Paint Area / Collision