Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py40
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h20
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c1627
-rw-r--r--source/blender/editors/physics/CMakeLists.txt1
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c268
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c68
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c8
-rw-r--r--source/blender/render/intern/include/texture.h2
-rw-r--r--source/blender/render/intern/source/render_texture.c6
-rw-r--r--source/blender/render/intern/source/volumetric.c10
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c2
12 files changed, 1120 insertions, 948 deletions
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 7d02765297d..88cfc2afbda 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -117,8 +117,11 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, bpy.types.Panel):
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")
+ split = layout.split(percentage=0.5)
+ col = split.column()
+ col.prop(brush, "wave_factor")
+ col = split.column()
+ col.prop(brush, "wave_clamp")
elif (brush.brush_settings_context == "VELOCITY"):
col = layout.row().column()
col.label(text="Velocity Settings:")
@@ -199,6 +202,39 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel):
layout.label(text="Brush Group:")
layout.prop(surface, "brush_group", text="")
+class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, bpy.types.Panel):
+ bl_label = "Dynamic Paint: Initial Color"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ md = context.dynamic_paint
+ if (not (md and (md.ui_type == "CANVAS") and (md.canvas_settings))):
+ return 0
+ surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
+ return (surface and surface.surface_type=="PAINT")
+
+ def draw(self, context):
+ layout = self.layout
+
+ canvas = context.dynamic_paint.canvas_settings
+ surface = canvas.canvas_surfaces.active
+ ob = context.object
+
+ layout.prop(surface, "init_color_type", expand=False)
+ layout.separator()
+
+ # dissolve
+ if (surface.init_color_type == "COLOR"):
+ layout.prop(surface, "init_color")
+
+ if (surface.init_color_type == "TEXTURE"):
+ layout.prop(surface, "init_texture")
+ layout.prop_search(surface, "init_layername", ob.data, "uv_textures", text="UV Layer:")
+
+ if (surface.init_color_type == "VERTEXCOLOR"):
+ layout.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer: ")
+
class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel):
bl_label = "Dynamic Paint: Output"
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index 24cb8c39844..26ad3c294eb 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -18,6 +18,8 @@
struct PaintEffectData;
struct PaintBakeData;
+struct bContext;
+struct wmOperator;
/* Actual surface point */
typedef struct PaintSurfaceData {
@@ -61,12 +63,22 @@ struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pm
void dynamicPaint_Modifier_free (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_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene);
+struct DynamicPaintSurface *dynamicPaint_createNewSurface(struct DynamicPaintCanvasSettings *canvas, struct Scene *scene);
+void dynamicPaint_clearSurface(struct DynamicPaintSurface *surface);
int dynamicPaint_resetSurface(struct DynamicPaintSurface *surface);
-int dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface);
+void dynamicPaint_freeSurface(struct DynamicPaintSurface *surface);
+void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd);
+void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd);
+
+void dynamicPaint_cacheUpdateFrames(struct DynamicPaintSurface *surface);
+int dynamicPaint_surfaceHasColorPreview(struct DynamicPaintSurface *surface);
int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, struct Object *ob, int index);
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface);
-void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, char *basename);
+void dynamicPaintSurface_setUniqueName(struct DynamicPaintSurface *surface, char *basename);
+void dynamicPaint_resetPreview(struct DynamicPaintCanvasSettings *canvas);
+struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings *canvas);
+
+int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op);
#endif /* BKE_DYNAMIC_PAINT_H_ */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 8ecd409a65c..10731faf3ad 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -58,15 +58,11 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h" /* to get temp file path */
-#include "ED_mesh.h"
-#include "ED_screen.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
-/* for bake operator */
-#include "WM_types.h"
+#include "ED_screen.h"
#include "WM_api.h"
/* for image output */
@@ -86,6 +82,7 @@
#include "../render/intern/include/pointdensity.h"
#include "../render/intern/include/render_types.h"
#include "../render/intern/include/voxeldata.h"
+#include "../render/intern/include/texture.h"
#include "DNA_material_types.h"
#include "RE_render_ext.h"
@@ -125,6 +122,7 @@ typedef struct Bounds2D {
} Bounds2D;
typedef struct Bounds3D {
+ int valid;
float min[3], max[3];
} Bounds3D;
@@ -259,7 +257,7 @@ int dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface)
}
/* get currently active surface (in user interface) */
-static DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas)
+struct DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas)
{
DynamicPaintSurface *surface = canvas->surfaces.first;
int i;
@@ -273,7 +271,7 @@ static DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas
}
/* set preview to first previewable surface */
-static void dynamicPaint_resetPreview(DynamicPaintCanvasSettings *canvas)
+void dynamicPaint_resetPreview(DynamicPaintCanvasSettings *canvas)
{
DynamicPaintSurface *surface = canvas->surfaces.first;
int done=0;
@@ -536,36 +534,50 @@ static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene, Obj
return flags;
}
+/* check whether two bounds intersect */
static int boundsIntersect(Bounds3D *b1, Bounds3D *b2)
{
int i=2;
+ if (!b1->valid || !b2->valid) return 0;
for (; i>=0; i-=1)
if (!(b1->min[i] <= b2->max[i] && b1->max[i] >= b2->min[i])) return 0;
return 1;
}
+/* check whether two bounds intersect inside defined proximity */
static int boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, float dist)
{
int i=2;
+ if (!b1->valid || !b2->valid) return 0;
for (; i>=0; i-=1)
if (!(b1->min[i] <= (b2->max[i]+dist) && b1->max[i] >= (b2->min[i]-dist))) return 0;
return 1;
}
+/* check whether bounds intersects a point with given radius */
static int boundIntersectPoint(Bounds3D *b, float point[3], float radius)
{
int i=2;
+ if (!b->valid) return 0;
for (; i>=0; i-=1)
if (!(b->min[i] <= (point[i]+radius) && b->max[i] >= (point[i]-radius))) return 0;
return 1;
}
+/* expand bounds by a new point */
static void boundInsert(Bounds3D *b, float point[3])
{
int i=2;
- for (; i>=0; i-=1) {
- if (point[i] < b->min[i]) b->min[i]=point[i];
- if (point[i] > b->max[i]) b->max[i]=point[i];
+ if (!b->valid) {
+ VECCOPY(b->min, point);
+ VECCOPY(b->max, point);
+ b->valid = 1;
+ }
+ else {
+ for (; i>=0; i-=1) {
+ if (point[i] < b->min[i]) b->min[i]=point[i];
+ if (point[i] > b->max[i]) b->max[i]=point[i];
+ }
}
}
@@ -614,17 +626,11 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
float tx,ty,tz;
float min_dim;
- /* initial values for each thread */
- for (index = 0; index<num_of_threads; index++) {
- VECCOPY(grid_bounds[index].min, bData->realCoord[bData->s_pos[0]].v);
- VECCOPY(grid_bounds[index].max, bData->realCoord[bData->s_pos[0]].v);
- }
- VECCOPY(grid->grid_bounds.min, bData->realCoord[bData->s_pos[0]].v);
- VECCOPY(grid->grid_bounds.max, bData->realCoord[bData->s_pos[0]].v);
-
/* calculate canvas dimensions */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
- for (index = 1; index < sData->total_points; index++) {
+ #endif
+ for (index = 0; index < sData->total_points; index++) {
#ifdef _OPENMP
int id = omp_get_thread_num();
boundInsert(&grid_bounds[id], (bData->realCoord[bData->s_pos[index]].v));
@@ -688,7 +694,9 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
if (!error) {
/* calculate number of points withing each cell */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++) {
int x,y,z;
x = floor((bData->realCoord[bData->s_pos[index]].v[0] - grid->grid_bounds.min[0])/dim[0]*grid->x);
@@ -731,7 +739,9 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
/* calculate cell bounds */
{
int x;
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (x=0; x<grid->x; x++) {
int y;
for (y=0; y<grid->y; y++) {
@@ -747,6 +757,8 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
grid->bounds[b_index].max[0] = grid->grid_bounds.min[0] + dim[0]/grid->x*(x+1);
grid->bounds[b_index].max[1] = grid->grid_bounds.min[1] + dim[1]/grid->y*(y+1);
grid->bounds[b_index].max[2] = grid->grid_bounds.min[2] + dim[2]/grid->z*(z+1);
+
+ grid->bounds[b_index].valid = 1;
}
}
}
@@ -769,7 +781,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
/***************************** Freeing data ******************************/
/* Free brush data */
-static void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
+void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
{
if(pmd->brush) {
if(pmd->brush->dm)
@@ -855,7 +867,7 @@ static void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface)
surface->data = NULL;
}
-static void dynamicPaint_freeSurface(DynamicPaintSurface *surface)
+void dynamicPaint_freeSurface(DynamicPaintSurface *surface)
{
if (!surface) return;
@@ -873,7 +885,7 @@ static void dynamicPaint_freeSurface(DynamicPaintSurface *surface)
}
/* Free canvas data */
-static void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
+void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
{
if(pmd->canvas) {
/* Free surface data */
@@ -912,7 +924,7 @@ void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd)
* Creates a new surface and adds it to the list
* A pointer to this surface is returned
*/
-static DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas, Scene *scene)
+struct DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas, Scene *scene)
{
DynamicPaintSurface *surface= MEM_callocN(sizeof(DynamicPaintSurface), "DynamicPaintSurface");
if (!surface) return NULL;
@@ -938,6 +950,11 @@ static DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSett
surface->disp_type = MOD_DPAINT_DISP_DISPLACE;
surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG;
+ surface->init_color[0] = 1.0f;
+ surface->init_color[1] = 1.0f;
+ surface->init_color[2] = 1.0f;
+ surface->init_color[3] = 1.0f;
+
surface->image_resolution = 256;
surface->substeps = 0;
@@ -1025,6 +1042,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
pmd->brush->particle_smooth = 0.05f;
pmd->brush->wave_factor = 1.0f;
+ pmd->brush->wave_clamp = 0.0f;
pmd->brush->smudge_strength = 0.3f;
pmd->brush->max_velocity = 1.0f;
@@ -1077,16 +1095,17 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn
/* Copy data */
if (tpmd->canvas) {
- pmd->canvas->pmd = tpmd;
+ tpmd->canvas->pmd = tpmd;
tpmd->canvas->ui_info[0] = '\0';
} else if (tpmd->brush) {
- pmd->brush->pmd = tpmd;
+ tpmd->brush->pmd = tpmd;
tpmd->brush->flags = pmd->brush->flags;
tpmd->brush->collision = pmd->brush->collision;
+ tpmd->brush->mat = pmd->brush->mat;
tpmd->brush->r = pmd->brush->r;
tpmd->brush->g = pmd->brush->g;
tpmd->brush->b = pmd->brush->b;
@@ -1098,9 +1117,20 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn
tpmd->brush->paint_distance = pmd->brush->paint_distance;
tpmd->brush->psys = pmd->brush->psys;
- tpmd->brush->paint_ramp = pmd->brush->paint_ramp;
+ if (pmd->brush->paint_ramp)
+ memcpy(tpmd->brush->paint_ramp, pmd->brush->paint_ramp, sizeof(ColorBand));
+ if (pmd->brush->vel_ramp)
+ memcpy(tpmd->brush->vel_ramp, pmd->brush->vel_ramp, sizeof(ColorBand));
tpmd->brush->proximity_falloff = pmd->brush->proximity_falloff;
+ tpmd->brush->brush_settings_context = pmd->brush->brush_settings_context;
+ tpmd->brush->wave_type = pmd->brush->wave_type;
+ tpmd->brush->ray_dir = pmd->brush->ray_dir;
+
+ tpmd->brush->wave_factor = pmd->brush->wave_factor;
+ tpmd->brush->wave_clamp = pmd->brush->wave_clamp;
+ tpmd->brush->max_velocity = pmd->brush->max_velocity;
+ tpmd->brush->smudge_strength = pmd->brush->smudge_strength;
}
}
@@ -1248,6 +1278,163 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for
MEM_freeN(temp_data);
}
+void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
+{
+ PaintSurfaceData *sData = surface->data;
+ PaintPoint* pPoint = (PaintPoint*)sData->type_data;
+ DerivedMesh *dm = surface->canvas->dm;
+ int i;
+
+ if (surface->type != MOD_DPAINT_SURFACE_T_PAINT)
+ return;
+
+ if (surface->init_color_type == MOD_DPAINT_INITIAL_NONE)
+ return;
+ /* Single color */
+ else if (surface->init_color_type == MOD_DPAINT_INITIAL_COLOR) {
+ /* apply color to every surface point */
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(static)
+ #endif
+ for (i=0; i<sData->total_points; i++) {
+ VECCOPY(pPoint[i].color, surface->init_color);
+ pPoint[i].alpha = surface->init_color[3];
+ }
+ }
+ /* UV mapped texture */
+ else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
+ Tex *tex = surface->init_texture;
+ MTFace *tface;
+ MFace *mface = dm->getFaceArray(dm);
+ int numOfFaces = dm->getNumFaces(dm);
+ char uvname[40];
+
+ if (!tex) return;
+
+ /* get uv layer */
+ validate_layer_name(&dm->faceData, CD_MTFACE, surface->init_layername, uvname);
+ tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
+ if (!tface) return;
+
+ /* for vertex surface loop through tfaces and find uv color
+ * that provides highest alpha */
+ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(static)
+ #endif
+ for (i=0; i<numOfFaces; i++) {
+ int numOfVert = (mface[i].v4) ? 4 : 3;
+ float uv[3] = {0.0f};
+ int j;
+ for (j=0; j<numOfVert; j++) {
+ TexResult texres = {0};
+ unsigned int *vert = (&mface[i].v1)+j;
+
+ /* remap to -1.0 to 1.0 */
+ uv[0] = tface[i].uv[j][0]*2.0f - 1.0f;
+ uv[1] = tface[i].uv[j][1]*2.0f - 1.0f;
+
+ multitex_ext_safe(tex, uv, &texres);
+
+ if (texres.tin > pPoint[*vert].alpha) {
+ VECCOPY(pPoint[*vert].color, &texres.tr);
+ pPoint[*vert].alpha = texres.tin;
+ }
+ }
+ }
+ }
+ else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
+ ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
+ int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
+
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(static)
+ #endif
+ for (i=0; i<sData->total_points; i++) {
+ float uv[9] = {0.0f};
+ float uv_final[3] = {0.0f};
+ int j;
+ TexResult texres = {0};
+
+ /* collect all uvs */
+ for (j=0; j<3; j++) {
+ int v=(f_data->uv_p[i].quad && j>0) ? j+1 : j;
+ VECCOPY2D(&uv[j*3], tface[f_data->uv_p[i].face_index].uv[v]);
+ }
+
+ /* interpolate final uv pos */
+ interp_v3_v3v3v3( uv_final, &uv[0], &uv[3], &uv[6],
+ f_data->barycentricWeights[i*samples].v);
+ /* remap to -1.0 to 1.0 */
+ uv_final[0] = uv_final[0]*2.0f - 1.0f;
+ uv_final[1] = uv_final[1]*2.0f - 1.0f;
+
+ multitex_ext_safe(tex, uv_final, &texres);
+
+ /* apply color */
+ VECCOPY(pPoint[i].color, &texres.tr);
+ pPoint[i].alpha = texres.tin;
+ }
+ }
+ }
+ /* vertex color layer */
+ else if (surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) {
+ MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername);
+ if (!col) return;
+
+ /* for vertex surface, just copy colors from mcol */
+ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ MFace *mface = dm->getFaceArray(dm);
+ int numOfFaces = dm->getNumFaces(dm);
+
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(static)
+ #endif
+ for (i=0; i<numOfFaces; i++) {
+ int numOfVert = (mface[i].v4) ? 4 : 3;
+ int j;
+ for (j=0; j<numOfVert; j++) {
+ unsigned int *vert = ((&mface[i].v1)+j);
+
+ pPoint[*vert].color[0] = 1.0f/255.f*(float)col[i*4+j].b;
+ pPoint[*vert].color[1] = 1.0f/255.f*(float)col[i*4+j].g;
+ pPoint[*vert].color[2] = 1.0f/255.f*(float)col[i*4+j].r;
+ pPoint[*vert].alpha = 1.0f/255.f*(float)col[i*4+j].a;
+ }
+ }
+ }
+ else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
+ ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
+ int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
+
+ #ifdef _OPENMP
+ #pragma omp parallel for schedule(static)
+ #endif
+ for (i=0; i<sData->total_points; i++) {
+ int face_ind = f_data->uv_p[i].face_index;
+ float colors[3][4] = {{0.0f,0.0f,0.0f,0.0f}};
+ float final_color[4];
+ int j;
+ /* collect color values */
+ for (j=0; j<3; j++) {
+ int v=(f_data->uv_p[i].quad && j>0) ? j+1 : j;
+ colors[j][0] = 1.0f/255.f*(float)col[face_ind*4+v].b;
+ colors[j][1] = 1.0f/255.f*(float)col[face_ind*4+v].g;
+ colors[j][2] = 1.0f/255.f*(float)col[face_ind*4+v].r;
+ colors[j][3] = 1.0f/255.f*(float)col[face_ind*4+v].a;
+ }
+
+ /* interpolate final color */
+ interp_v4_v4v4v4( final_color, colors[0], colors[1], colors[2],
+ f_data->barycentricWeights[i*samples].v);
+
+ VECCOPY(pPoint[i].color, final_color);
+ pPoint[i].alpha = final_color[3];
+ }
+ }
+ }
+}
+
/* clears surface data back to zero */
void dynamicPaint_clearSurface(DynamicPaintSurface *surface)
{
@@ -1264,6 +1451,10 @@ void dynamicPaint_clearSurface(DynamicPaintSurface *surface)
memset(sData->type_data, 0, data_size * sData->total_points);
+ /* set initial color */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
+ dynamicPaint_setInitialColor(surface);
+
if (sData->bData)
sData->bData->clear = 1;
}
@@ -1288,6 +1479,10 @@ int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
dynamicPaint_allocateSurfaceType(surface);
dynamicPaint_initAdjacencyData(surface, 0);
+ /* set initial color */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
+ dynamicPaint_setInitialColor(surface);
+
return 1;
}
@@ -1316,7 +1511,9 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Deri
int i;
float* value = (float*)sData->type_data;
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<sData->total_points; i++) {
float normal[3];
normal_short_to_float_v3(normal, mvert[i].no);
@@ -1367,7 +1564,9 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
/* paint is stored on dry and wet layers, so mix final color first */
float *fcolor = MEM_callocN(sizeof(float)*sData->total_points*4, "Temp paint color");
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<sData->total_points; i++) {
int j=i*4;
@@ -1389,7 +1588,9 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
if (col) {
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<numOfFaces; i++) {
int j=0;
float invAlpha;
@@ -1421,10 +1622,11 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
col[i*4+j].b = (char)(((float)col[i*4+j].b)*invAlpha + (fcolor[index]*255*fcolor[index+3]));
}
else {
+ float wetness = (pPoint[index].wetness<1.0f) ? pPoint[index].wetness : 1.0f;
col[i*4+j].a = 255;
- col[i*4+j].r = (char)(pPoint[index].wetness*255);
- col[i*4+j].g = (char)(pPoint[index].wetness*255);
- col[i*4+j].b = (char)(pPoint[index].wetness*255);
+ col[i*4+j].r = (char)(wetness*255);
+ col[i*4+j].g = (char)(wetness*255);
+ col[i*4+j].b = (char)(wetness*255);
}
}
}
@@ -1438,7 +1640,9 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
/* paint layer */
col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name);
if (col) {
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<numOfFaces; i++) {
int j=0;
for (; j<((mface[i].v4)?4:3); j++) {
@@ -1458,17 +1662,20 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
/* wet layer */
col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name2);
if (col) {
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<numOfFaces; i++) {
int j=0;
for (; j<((mface[i].v4)?4:3); j++) {
int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
+ float wetness = (pPoint[index].wetness<1.0f) ? pPoint[index].wetness : 1.0f;
col[i*4+j].a = 255;
- col[i*4+j].r = (char)(pPoint[index].wetness*255);
- col[i*4+j].g = (char)(pPoint[index].wetness*255);
- col[i*4+j].b = (char)(pPoint[index].wetness*255);
+ col[i*4+j].r = (char)(wetness*255);
+ col[i*4+j].g = (char)(wetness*255);
+ col[i*4+j].b = (char)(wetness*255);
}
}
}
@@ -1489,7 +1696,9 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
if (col) {
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<numOfFaces; i++) {
float temp_color[3];
int j=0;
@@ -1556,7 +1765,9 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
int i;
PaintWavePoint* wPoint = (PaintWavePoint*)sData->type_data;
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<sData->total_points; i++) {
float normal[3];
normal_short_to_float_v3(normal, mvert[i].no);
@@ -1686,7 +1897,7 @@ struct DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scen
}
-/***************************** Image Sequence / UV Image Canvas Calls ******************************/
+/***************************** Image Sequence / UV Image Surface Calls ******************************/
/*
* Tries to find the neighbouring pixel in given (uv space) direction.
@@ -1884,7 +2095,7 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
}
/*
-* Create a surface for image sequence format
+* Create a surface for uv image sequence format
*/
static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
{
@@ -1984,7 +2195,9 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
* if pixel is uv-mapped on a canvas face.
*/
if (!error) {
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (ty = 0; ty < h; ty++)
{
int tx;
@@ -2129,7 +2342,9 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
* If so use that polygon as pixel surface.
* (To avoid seams on uv island edges)
*/
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (ty = 0; ty < h; ty++)
{
int tx;
@@ -2323,7 +2538,9 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
/* -----------------------------------------------------------------
* For debug, output pixel statuses to the color map
* -----------------------------------------------------------------*/
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
@@ -2340,6 +2557,7 @@ static int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
}
#endif
+ dynamicPaint_setInitialColor(surface);
}
return (error == 0);
@@ -2375,11 +2593,12 @@ void dynamicPaint_outputImage(DynamicPaintSurface *surface, char* filename, shor
mhImgB = IMB_allocImBuf(surface->image_resolution, surface->image_resolution, 32, IB_rectfloat);
if (mhImgB == NULL) {printError(surface->canvas, "Image save failed: Not enough free memory.");return;}
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
int pos=f_data->uv_p[index].pixel_index*4; /* image buffer position */
-
/* Set values of preferred type */
if (type == DPOUTPUT_WET) {
@@ -2461,91 +2680,13 @@ void dynamicPaint_outputImage(DynamicPaintSurface *surface, char* filename, shor
/***************************** Material / Texture Sampling ******************************/
-/*
-* Update animated textures and calculate inverse matrices
-* for material related objects in case texture is mapped to an object.
-* (obj->imat isn't auto-updated)
-*/
-static void dynamicPaint_updateMaterial(Material *mat, Scene *scene)
-{
- MTex *mtex = NULL;
- Tex *tex = NULL;
- int tex_nr;
- if (mat == NULL) return;
-
- /* update material anims */
- BKE_animsys_evaluate_animdata(&mat->id, mat->adt, BKE_curframe(scene), ADT_RECALC_ANIM);
-
- /*
- * Loop through every material texture and check
- * if they are mapped by other object
- */
- for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
- /* separate tex switching */
- if(mat->septex & (1<<tex_nr)) continue;
-
- if(mat->mtex[tex_nr]) {
- mtex= mat->mtex[tex_nr];
- tex= mtex->tex;
-
- if(tex==0) continue;
-
- /* which coords */
- if(mtex->texco==TEXCO_OBJECT) {
- Object *ob= mtex->object;
- if(ob) {
- invert_m4_m4(ob->imat, ob->obmat);
- }
- }
-
- /* update texture anims */
- BKE_animsys_evaluate_animdata(&tex->id, tex->adt, BKE_curframe(scene), ADT_RECALC_ANIM);
-
- /* update cache if voxel data */
- if(tex->id.us && tex->type==TEX_VOXELDATA) {
- cache_voxeldata(tex, (int)scene->r.cfra);
- }
- if(tex->id.us && tex->type==TEX_POINTDENSITY) {
- /* set dummy values for render used */
- Render dummy_re = {0};
- dummy_re.scene = scene;
- unit_m4(dummy_re.viewinv);
- unit_m4(dummy_re.viewmat);
- unit_m4(dummy_re.winmat);
- dummy_re.winx = 128;
- dummy_re.winy = 128;
- cache_pointdensity(&dummy_re, tex);
- }
-
- /* update image sequences and movies */
- if(tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
- if(tex->iuser.flag & IMA_ANIM_ALWAYS)
- BKE_image_user_calc_frame(&tex->iuser, (int)scene->r.cfra, 0);
- }
- }
- }
-}
-
-/* Initialize materials for object:
-* Calculates inverce matrices for linked objects, updates
-* volume caches etc. */
-static void dynamicPaint_updateObjectMaterials(Object *brushOb, Material *ui_mat, Scene *scene)
-{
- /* Calculate inverse transformation matrix
- * for this object */
- invert_m4_m4(brushOb->imat, brushOb->obmat);
-
- /* Now process every material linked to this brush object */
- if ((ui_mat == NULL) && brushOb->mat && brushOb->totcol) {
- int i, tot=(*give_totcolp(brushOb))+1;
- for (i=1; i<tot; i++) {
- dynamicPaint_updateMaterial(give_current_material(brushOb,i), scene);
- }
- }
- else {
- dynamicPaint_updateMaterial(ui_mat, scene);
- }
-}
+/* stores a copy of required materials to allow doing adjustments
+* without interfering the render/preview */
+typedef struct BrushMaterials {
+ Material *mat;
+ Material **ob_mats;
+ int tot;
+} BrushMaterials;
/* A modified part of shadeinput.c -> shade_input_set_uv()
* Used for sampling UV mapped texture color */
@@ -2599,376 +2740,315 @@ static void textured_face_get_uv(float *uv_co, float *normal, float *uv, int fac
}
/*
-* Edited version of do_material_tex()
-*
-* Samples color and alpha from a "Surface" type material
-* on a given point, without need for ShadeInput.
-*
-* Keep up-to-date with new mapping settings
-*
-* also see shade_input_set_shade_texco() for ORCO settings
-* and shade_input_set_uv() for face uv calculation
+* Generate an updated copy of material to use for brush sampling.
+* Updates animated textures and calculates inverse matrices
+* for material related objects in case texture is mapped to an object.
+* (obj->imat isn't auto-updated)
*/
-void dynamicPaint_sampleSolidMaterial(float color[3], float *alpha, Material *mat, Object *brushOb, float xyz[3], int faceIndex, short isQuad, DerivedMesh *orcoDm)
+static void dynamicPaint_copyUpdatedMaterial(Material *orig_mat, Scene *scene, Material **mat_target)
{
MTex *mtex = NULL;
+ MTex *orig_mtex = NULL;
Tex *tex = NULL;
- TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
- float co[3], xyz_local[3];
- float fact, stencilTin=1.0;
- float texvec[3];
- int tex_nr, rgbnor= 0;
- float uv[3], normal[3];
- MFace *mface;
- int v1, v2, v3;
- MVert *mvert;
+ Material *mat;
+ int tex_nr;
- /* Assign material base values */
- color[0] = mat->r;
- color[1] = mat->g;
- color[2] = mat->b;
- *alpha = mat->alpha;
+ if (orig_mat == NULL) return;
- /* Get face data */
- mvert = orcoDm->getVertArray(orcoDm);
- mface = orcoDm->getFaceArray(orcoDm);
-
- if (!mvert || !mface) return;
- v1=mface[faceIndex].v1, v2=mface[faceIndex].v2, v3=mface[faceIndex].v3;
- if (isQuad) {v2=mface[faceIndex].v3; v3=mface[faceIndex].v4;}
- normal_tri_v3( normal, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ /* update material anims */
+ BKE_animsys_evaluate_animdata(&orig_mat->id, orig_mat->adt, BKE_curframe(scene), ADT_RECALC_ANIM);
- VECCOPY(xyz_local, xyz);
- mul_m4_v3(brushOb->imat, xyz_local);
+ /* copy material */
+ mat = MEM_callocN(sizeof(Material), "Temp Brush Material");
+ memcpy(mat, orig_mat, sizeof(Material));
for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
-
- /* separate tex switching */
if(mat->septex & (1<<tex_nr)) continue;
-
+
if(mat->mtex[tex_nr]) {
- mtex= mat->mtex[tex_nr];
- tex= mtex->tex;
-
- tex= mtex->tex;
- if(tex==0) continue;
-
- /* which coords */
- if(mtex->texco==TEXCO_ORCO) {
- float l;
- /* Get generated UV */
- textured_face_generate_uv(uv, normal, xyz_local, mvert[v1].co, mvert[v2].co, mvert[v3].co);
- l= 1.0f+uv[0]+uv[1];
-
- /* calculate generated coordinate
- * ** Keep up-to-date with shadeinput.c -> shade_input_set_shade_texco() **/
- co[0]= l*mvert[v3].co[0]-uv[0]*mvert[v1].co[0]-uv[1]*mvert[v2].co[0];
- co[1]= l*mvert[v3].co[1]-uv[0]*mvert[v1].co[1]-uv[1]*mvert[v2].co[1];
- co[2]= l*mvert[v3].co[2]-uv[0]*mvert[v1].co[2]-uv[1]*mvert[v2].co[2];
- }
- else if(mtex->texco==TEXCO_OBJECT) {
- Object *ob= mtex->object;
-
- VECCOPY(co, xyz);
- /* convert from world space to paint space */
- mul_m4_v3(brushOb->imat, co);
- if(ob) {
- mul_m4_v3(ob->imat, co);
- }
- }
- else if(mtex->texco==TEXCO_GLOB) {
- VECCOPY(co, xyz);
- }
- else if(mtex->texco==TEXCO_UV) {
- MTFace *tface;
-
- /* Get UV layer */
- if(mtex->uvname[0] != 0)
- tface = CustomData_get_layer_named(&orcoDm->faceData, CD_MTFACE, mtex->uvname);
- else
- tface = DM_get_face_data_layer(orcoDm, CD_MTFACE);
- /* Get generated coordinates to calculate UV from */
- textured_face_generate_uv(uv, normal, xyz_local, mvert[v1].co, mvert[v2].co, mvert[v3].co);
- /* Get UV mapping coordinate */
- textured_face_get_uv(co, normal, uv, faceIndex, isQuad, tface);
- }
- else continue; /* non-supported types get just skipped:
- TEXCO_REFL, TEXCO_NORM, TEXCO_TANGENT
- TEXCO_WINDOW, TEXCO_STRAND, TEXCO_STRESS etc.
- */
-
- /* get texture mapping */
- texco_mapping_ext(normal, tex, mtex, co, 0, 0, texvec);
+ orig_mtex = mat->mtex[tex_nr];
- if(tex->use_nodes && tex->nodetree) {
- /* No support for nodes (yet). */
- continue;
- }
- else {
- /* cant use multitex_ext because it redoes mapping for image textures */
- rgbnor = multitex(mtex->tex, texvec, 0, 0, 0, &texres, 0, 0);
- }
+ mtex = MEM_callocN(sizeof(MTex), "Temp MTex Copy");
+ memcpy(mtex, orig_mtex, sizeof(MTex));
+ mat->mtex[tex_nr] = mtex;
+ tex= mtex->tex;
- /* texture output */
- if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
- rgbnor-= TEX_RGB;
- }
+ /* Strip non-compatible texflags */
+ mtex->texflag = (orig_mtex->texflag & MTEX_RGBTOINT) | (orig_mtex->texflag & MTEX_STENCIL) |
+ (orig_mtex->texflag & MTEX_NEGATIVE) | (orig_mtex->texflag & MTEX_ALPHAMIX);
- /* Negate and stencil masks */
- if(mtex->texflag & MTEX_NEGATIVE) {
- if(rgbnor & TEX_RGB) {
- texres.tr= 1.0-texres.tr;
- texres.tg= 1.0-texres.tg;
- texres.tb= 1.0-texres.tb;
+ /* depending of material type, strip non-compatible mapping modes */
+ if (mat->material_type == MA_TYPE_SURFACE) {
+ if (mtex->texco!=TEXCO_ORCO && mtex->texco!=TEXCO_OBJECT &&
+ mtex->texco!=TEXCO_GLOB && mtex->texco!=TEXCO_UV) {
+ /* ignore this texture */
+ mtex->texco = 0;
+ continue;
}
- texres.tin= 1.0-texres.tin;
+ /* strip all mapto flags except color and alpha */
+ mtex->mapto = (orig_mtex->mapto & MAP_COL) | (orig_mtex->mapto & MAP_ALPHA);
}
- if(mtex->texflag & MTEX_STENCIL) {
- if(rgbnor & TEX_RGB) {
- fact= texres.ta;
- texres.ta*= stencilTin;
- stencilTin*= fact;
+ else if (mat->material_type == MA_TYPE_VOLUME) {
+ if (mtex->texco!=TEXCO_OBJECT && mtex->texco!=TEXCO_ORCO &&
+ mtex->texco!=TEXCO_GLOB) {
+ /* ignore */
+ mtex->texco = 0;
+ continue;
}
- else {
- fact= texres.tin;
- texres.tin*= stencilTin;
- stencilTin*= fact;
+ /* strip all mapto flags except color and alpha */
+ mtex->mapto = (orig_mtex->mapto & MAP_TRANSMISSION_COL) | (orig_mtex->mapto & MAP_REFLECTION_COL) |
+ (orig_mtex->mapto & MAP_DENSITY);
+ }
+
+ /* if mapped to an object, calculate inverse matrices */
+ if(mtex->texco==TEXCO_OBJECT) {
+ Object *ob= mtex->object;
+ if(ob) {
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_m4_m4(ob->imat_ren, ob->imat);
}
}
- /* mapping */
- if(mtex->mapto & (MAP_COL)) {
- float tcol[3];
- /* stencil maps on the texture control slider, not texture intensity value */
- tcol[0]=texres.tr; tcol[1]=texres.tg; tcol[2]=texres.tb;
- if((rgbnor & TEX_RGB)==0) {
- tcol[0]= mtex->r;
- tcol[1]= mtex->g;
- tcol[2]= mtex->b;
- }
- else if(mtex->mapto & MAP_ALPHA) {
- texres.tin= stencilTin;
+ /* update texture anims */
+ BKE_animsys_evaluate_animdata(&tex->id, tex->adt, BKE_curframe(scene), ADT_RECALC_ANIM);
+
+ /* if texture type requires caching, create a copy of texture/data too
+ * to be able to re-cache safely.
+ * **Remember to also add new types to dynamicPaint_freeMaterialCopy()!** */
+ if (tex->id.us && (tex->type==TEX_VOXELDATA || tex->type==TEX_POINTDENSITY)) {
+ mtex->tex = MEM_callocN(sizeof(Tex), "Temp Tex Copy");
+ memcpy(mtex->tex, tex, sizeof(Tex));
+ tex= mtex->tex;
+
+ /* update cache if voxel data */
+ if(tex->type==TEX_VOXELDATA) {
+ VoxelData *vd = MEM_callocN(sizeof(VoxelData), "Temp VoxelData Copy");
+ memcpy(vd, tex->vd, sizeof(VoxelData));
+ tex->vd = vd;
+ vd->dataset = NULL;
+
+ cache_voxeldata(tex, (int)scene->r.cfra);
}
- else texres.tin= texres.ta;
- if(mtex->mapto & MAP_COL) {
- float colfac= mtex->colfac*stencilTin;
- texture_rgb_blend(color, tcol, color, texres.tin, colfac, mtex->blendtype);
+ if(tex->type==TEX_POINTDENSITY) {
+ Render dummy_re = {0};
+ PointDensity *pd = MEM_callocN(sizeof(PointDensity), "Temp PointDensity Copy");
+ memcpy(pd, tex->pd, sizeof(PointDensity));
+ tex->pd = pd;
+ pd->point_data = pd->point_tree = NULL;
+
+ /* set dummy values for render and do cache */
+ dummy_re.scene = scene;
+ unit_m4(dummy_re.viewinv);
+ unit_m4(dummy_re.viewmat);
+ unit_m4(dummy_re.winmat);
+ dummy_re.winx = dummy_re.winy = 128;
+ cache_pointdensity(&dummy_re, tex);
}
}
- if(mtex->mapto & MAP_VARS) {
- /* stencil maps on the texture control slider, not texture intensity value */
- if(rgbnor & TEX_RGB) {
- if(texres.talpha) texres.tin= texres.ta;
- else texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
- }
-
- if(mtex->mapto & MAP_ALPHA) {
- float alphafac= mtex->alphafac*stencilTin;
- *alpha= texture_value_blend(mtex->def_var, *alpha, texres.tin, alphafac, mtex->blendtype);
- if(*alpha<0.0) *alpha= 0.0;
- else if(*alpha>1.0) *alpha= 1.0;
- }
+ /* update image sequences and movies */
+ if(tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ if(tex->iuser.flag & IMA_ANIM_ALWAYS)
+ BKE_image_user_calc_frame(&tex->iuser, (int)scene->r.cfra, 0);
}
}
}
+ *mat_target = mat;
}
-
-/*
-* Edited version of texture.c -> do_volume_tex()
-*
-* Samples color and density from a volume type texture
-* without need for ShadeInput.
-*
-* Keep up-to-date with new mapping settings
-*/
-void dynamicPaint_sampleVolumeMaterial(float color[3], float *alpha, Material *mat, Object *brushOb, float xyz[3])
+/* free all duplicate data allocated by dynamicPaint_copyUpdatedMaterial() */
+static void dynamicPaint_freeMaterialCopy(Material *mat)
{
- int mapto_flag = MAP_DENSITY | MAP_REFLECTION_COL | MAP_TRANSMISSION_COL;
- float *col = color;
+ int tex_nr;
+ if (!mat)
+ return;
- MTex *mtex = NULL;
- Tex *tex = NULL;
- TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
- int tex_nr, rgbnor= 0;
- float co[3], texvec[3];
- float fact, stencilTin=1.0;
-
- /* set base color */
- color[0] = mat->vol.reflection_col[0];
- color[1] = mat->vol.reflection_col[1];
- color[2] = mat->vol.reflection_col[2];
- *alpha = mat->vol.density;
-
+ /* free mtexes */
for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
-
- /* separate tex switching */
if(mat->septex & (1<<tex_nr)) continue;
if(mat->mtex[tex_nr]) {
- mtex= mat->mtex[tex_nr];
- tex= mtex->tex;
- if(tex==0) continue;
-
- /* only process if this texture is mapped
- * to one that we're interested in */
- if (!(mtex->mapto & mapto_flag)) continue;
- texres.nor= NULL;
-
- /* which coords */
- if(mtex->texco==TEXCO_OBJECT) {
- Object *ob= mtex->object;
- ob= mtex->object;
- if(ob) {
- VECCOPY(co, xyz);
- mul_m4_v3(ob->imat, co);
+ MTex *mtex= mat->mtex[tex_nr];
+ Tex *tex= mtex->tex;
+ /* free tex copies */
+ if (tex->id.us && (tex->type==TEX_VOXELDATA || tex->type==TEX_POINTDENSITY)) {
+ if(tex->type==TEX_VOXELDATA && tex->vd) {
+ if (tex->vd->dataset) MEM_freeN(tex->vd->dataset);
+ MEM_freeN(tex->vd);
}
- }
- else if(mtex->texco==TEXCO_ORCO) {
- {
- Object *ob= brushOb;
- VECCOPY(co, xyz);
- mul_m4_v3(ob->imat, co);
+ if(tex->type==TEX_POINTDENSITY && tex->pd) {
+ if (tex->pd->point_tree) BLI_bvhtree_free(tex->pd->point_tree);
+ if (tex->pd->point_data) MEM_freeN(tex->pd->point_data);
+ MEM_freeN(tex->pd);
}
+ MEM_freeN(tex);
}
- else if(mtex->texco==TEXCO_GLOB) {
- VECCOPY(co, xyz);
- }
- else continue; /* Skip unsupported types */
+ MEM_freeN(mtex);
+ }
+ }
- if(tex->type==TEX_IMAGE) {
- continue; /* not supported yet */
- }
- else {
- /* placement */
- if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
- else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
+ MEM_freeN(mat);
+}
- if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
- else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
+/* Initialize materials for brush object:
+* Calculates inverse matrices for linked objects, updates
+* volume caches etc. */
+static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
+{
+ /* Calculate inverse transformation matrix
+ * for this object */
+ invert_m4_m4(brushOb->imat, brushOb->obmat);
+ copy_m4_m4(brushOb->imat_ren, brushOb->imat);
- if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
- else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
- }
- rgbnor= multitex_ext(tex, texvec, NULL, NULL, 0, &texres);
-
- /* texture output */
- if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
- rgbnor-= TEX_RGB;
- }
- /* Negate and stencil */
- if(mtex->texflag & MTEX_NEGATIVE) {
- if(rgbnor & TEX_RGB) {
- texres.tr= 1.0-texres.tr;
- texres.tg= 1.0-texres.tg;
- texres.tb= 1.0-texres.tb;
- }
- texres.tin= 1.0-texres.tin;
- }
- if(mtex->texflag & MTEX_STENCIL) {
- if(rgbnor & TEX_RGB) {
- fact= texres.ta;
- texres.ta*= stencilTin;
- stencilTin*= fact;
- }
- else {
- fact= texres.tin;
- texres.tin*= stencilTin;
- stencilTin*= fact;
- }
- }
-
- /* Map values */
- if((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) {
- float tcol[3];
- /* stencil maps on the texture control slider, not texture intensity value */
- if((rgbnor & TEX_RGB)==0) {
- tcol[0]= mtex->r;
- tcol[1]= mtex->g;
- tcol[2]= mtex->b;
- } else {
- tcol[0]=texres.tr;
- tcol[1]=texres.tg;
- tcol[2]=texres.tb;
- if(texres.talpha)
- texres.tin= texres.ta;
- }
-
- /* used for emit */
- if((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) {
- float colemitfac= mtex->colemitfac*stencilTin;
- texture_rgb_blend(col, tcol, col, texres.tin, colemitfac, mtex->blendtype);
- }
- if((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) {
- float colreflfac= mtex->colreflfac*stencilTin;
- texture_rgb_blend(col, tcol, col, texres.tin, colreflfac, mtex->blendtype);
- }
- if((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) {
- float coltransfac= mtex->coltransfac*stencilTin;
- texture_rgb_blend(col, tcol, col, texres.tin, coltransfac, mtex->blendtype);
- }
- }
-
- if((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) {
- /* stencil maps on the texture control slider, not texture intensity value */
-
- /* convert RGB to intensity if intensity info isn't provided */
- if (!(rgbnor & TEX_INT)) {
- if (rgbnor & TEX_RGB) {
- if(texres.talpha) texres.tin= texres.ta;
- else texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb);
- }
- }
- if((mapto_flag & MAP_DENSITY) && (mtex->mapto & MAP_DENSITY)) {
- float densfac= mtex->densfac*stencilTin;
+ /* Now process every material linked to this brush object */
+ if ((ui_mat == NULL) && brushOb->mat && brushOb->totcol) {
+ int i, tot=(*give_totcolp(brushOb));
- *alpha = texture_value_blend(mtex->def_var, *alpha, texres.tin, densfac, mtex->blendtype);
- CLAMP(*alpha, 0.0, 1.0);
- }
- }
+ /* allocate material pointer array */
+ bMats->ob_mats = MEM_callocN(sizeof(Material*)*(tot), "BrushMaterials");
+ for (i=0; i<tot; i++) {
+ dynamicPaint_copyUpdatedMaterial(give_current_material(brushOb,(i+1)), scene, &bMats->ob_mats[i]);
+ }
+ bMats->tot = tot;
+ }
+ else {
+ dynamicPaint_copyUpdatedMaterial(ui_mat, scene, &bMats->mat);
+ }
+}
+
+/* free all data allocated by dynamicPaint_updateBrushMaterials() */
+static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats)
+{
+ /* Now process every material linked to this brush object */
+ if (bMats->ob_mats) {
+ int i;
+ for (i=0; i<bMats->tot; i++) {
+ dynamicPaint_freeMaterialCopy(bMats->ob_mats[i]);
}
+ MEM_freeN(bMats->ob_mats);
+ }
+ else {
+ dynamicPaint_freeMaterialCopy(bMats->mat);
}
}
/*
* Get material diffuse color and alpha (including linked textures) in given coordinates
*
-* color,paint : input/output color values
-* pixelCoord : canvas pixel coordinates in global space. used if material is volumetric
-* paintHit : ray hit point on paint object surface in global space. used by "surface" type materials
+* color,alpha : input/output color values
+* surfaceCoord : canvas surface point coordinates in global space. used if material is volumetric
+* paintHit : ray hit point on brush object surface in global space. used by "surface" type materials
* faceIndex : ray hit face index
* orcoDm : orco state derived mesh of paint object
-* ui_mat : force material. if NULL, material linked to mesh face is used.
-*
-* *"brush object" = object to sample material color from
*/
-void dynamicPaint_getMaterialColor(float *color, float *alpha, Object *brushOb, float pixelCoord[3], float paintHit[3], int faceIndex, short isQuad, DerivedMesh *orcoDm, Material *ui_mat)
+void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, float surfaceCoord[3], float xyz[3], int faceIndex, short isQuad, DerivedMesh *orcoDm)
{
- Material *material = ui_mat;
- /* Get face material */
- if (material == NULL) {
- MFace *mface = NULL;
- mface = orcoDm->getFaceArray(orcoDm);
- material = give_current_material(brushOb, mface[faceIndex].mat_nr+1);
+ MFace *mface;
+ int v1, v2, v3;
+ MVert *mvert;
+ float uv[3], normal[3];
- if (material == NULL) return; /* No material assigned */
- }
+ ShadeInput shi = {0};
+ Material *mat = bMats->mat;
- /* Sample textured material color in given position depending on material type */
- if (material->material_type == MA_TYPE_SURFACE) {
- /* Solid material */
- dynamicPaint_sampleSolidMaterial(color, alpha, material, brushOb, paintHit, faceIndex, isQuad, orcoDm);
+ /* Get face data */
+ mvert = orcoDm->getVertArray(orcoDm);
+ mface = orcoDm->getFaceArray(orcoDm);
+
+ /* If no material defined, use the one assigned to the mesh face */
+ if (mat == NULL) {
+ if (bMats->ob_mats) {
+ int mat_nr = mface[faceIndex].mat_nr;
+ if (mat_nr >= (*give_totcolp(brushOb))) return;
+ mat = bMats->ob_mats[mat_nr];
+ if (mat == NULL) return; /* No material assigned */
+ }
+ else return;
}
- else if (material->material_type == MA_TYPE_VOLUME) {
- /* Volumetric material */
- dynamicPaint_sampleVolumeMaterial(color, alpha, material, brushOb, pixelCoord);
+
+ if (!mvert || !mface || !mat) return;
+ v1=mface[faceIndex].v1, v2=mface[faceIndex].v2, v3=mface[faceIndex].v3;
+ if (isQuad) {v2=mface[faceIndex].v3; v3=mface[faceIndex].v4;}
+ normal_tri_v3( normal, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+
+ /* prepare shadeinput with data required */
+ shi.mat = mat;
+
+ /* Fill shadeinput data depending on texture type */
+ if (mat->material_type == MA_TYPE_SURFACE) {
+ /* global coordinates */
+ VECCOPY(shi.gl, xyz);
+ /* object space coordinates */
+ VECCOPY(shi.co, xyz);
+ mul_m4_v3(brushOb->imat, shi.co);
+ /* orco coordinates */
+ {
+ float l;
+ /* Get generated UV */
+ textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ l= 1.0f+uv[0]+uv[1];
+
+ /* calculate generated coordinate
+ * ** Keep up-to-date with shadeinput.c -> shade_input_set_shade_texco() **/
+ shi.lo[0]= l*mvert[v3].co[0]-uv[0]*mvert[v1].co[0]-uv[1]*mvert[v2].co[0];
+ shi.lo[1]= l*mvert[v3].co[1]-uv[0]*mvert[v1].co[1]-uv[1]*mvert[v2].co[1];
+ shi.lo[2]= l*mvert[v3].co[2]-uv[0]*mvert[v1].co[2]-uv[1]*mvert[v2].co[2];
+ }
+ /* uv coordinates */
+ {
+ int i, layers = CustomData_number_of_layers(&orcoDm->faceData, CD_MTFACE);
+ int layer_index = CustomData_get_layer_index(&orcoDm->faceData, CD_MTFACE);
+
+ /* for every uv layer set coords and name */
+ for (i=0; i<layers; i++) {
+ if(layer_index >= 0) {
+ CustomData *data = &orcoDm->faceData;
+ MTFace *tface = (MTFace*) data->layers[layer_index+i].data;
+ float uv[3];
+ /* point layer name from actual layer data */
+ shi.uv[i].name = data->layers[i].name;
+ /* Get generated coordinates to calculate UV from */
+ textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ /* Get UV mapping coordinate */
+ textured_face_get_uv(shi.uv[i].uv, normal, uv, faceIndex, isQuad, tface);
+ }
+ }
+ /* active uv layer */
+ shi.actuv = CustomData_get_active_layer_index(&orcoDm->faceData,CD_MTFACE) - layer_index;
+ shi.totuv = layers;
+ }
+
+ /* apply initial values from material */
+ shi.r = mat->r;
+ shi.g = mat->g;
+ shi.b = mat->b;
+ shi.alpha = mat->alpha;
+
+ /* do texture */
+ do_material_tex(&shi);
+
+ /* apply result */
+ color[0] = shi.r;
+ color[1] = shi.g;
+ color[2] = shi.b;
+ *alpha = shi.alpha;
}
- else if (material->material_type == MA_TYPE_HALO) {
- /* Halo type not supported */
+ else if (mat->material_type == MA_TYPE_VOLUME) {
+ ObjectInstanceRen obi = {0};
+ Render re = {0};
+ obi.ob = brushOb;
+ shi.obi = &obi;
+ unit_m4(re.viewinv);
+
+ color[0] = mat->vol.reflection_col[0];
+ color[1] = mat->vol.reflection_col[1];
+ color[2] = mat->vol.reflection_col[2];
+ *alpha = mat->vol.density;
+
+ /* do texture */
+ do_volume_tex(&shi, surfaceCoord, (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY),
+ color, alpha, &re);
}
}
@@ -3056,7 +3136,7 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float *
}
-/***************************** Painting Calls ******************************/
+/***************************** Brush Painting Calls ******************************/
/*
* Mix color values to canvas point.
@@ -3125,6 +3205,7 @@ static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index,
}
}
+/* applies given brush intersection value for wave surface */
static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint, DynamicPaintBrushSettings *brush, float isect_height)
{
int hit = 0;
@@ -3150,13 +3231,12 @@ static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint, DynamicPaintBrush
}
/*
-* add paint results to the surface data depending on surface type
+* add brush results to the surface data depending on surface type
*/
static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned int index, DynamicPaintBrushSettings *brush,
- float paint[4], float influence, float depth, float vel_factor, float timescale)
+ float paint[3], float influence, float depth, float vel_factor, float timescale)
{
PaintSurfaceData *sData = surface->data;
-
float strength = influence * brush->alpha;
/* Sample velocity colorband if required */
@@ -3195,8 +3275,9 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned
if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL)
depth = value[index] + depth;
- if (surface->disp_clamp && depth > surface->disp_clamp)
- depth = surface->disp_clamp;
+ if (surface->disp_clamp) {
+ CLAMP(depth, 0.0f-surface->disp_clamp, surface->disp_clamp);
+ }
if (brush->flags & MOD_DPAINT_ERASE) {
value[index] *= (1.0f - strength);
@@ -3220,6 +3301,10 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned
}
/* wave surface */
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
+ if (brush->wave_clamp) {
+ CLAMP(depth, 0.0f-brush->wave_clamp, brush->wave_clamp);
+ }
+
dynamicPaint_mixWaveHeight(&((PaintWavePoint*)sData->type_data)[index],
brush, 0.0f-depth);
}
@@ -3230,6 +3315,7 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned
}
}
+/* checks whether surface and brush bounds intersect depending on brush type */
static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush)
{
if (brush->flags & MOD_DPAINT_ACCEPT_NONCLOSED)
@@ -3252,7 +3338,6 @@ static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, Dy
float cur_sfra = scene->r.subframe;
int cur_fra = scene->r.cfra;
-
float prev_sfra = cur_sfra - timescale;
int prev_fra = cur_fra;
@@ -3289,7 +3374,9 @@ static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, Dy
mvert_p = mvert_c;
/* calculate speed */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<numOfVerts_c; i++) {
float p1[3], p2[3];
@@ -3350,7 +3437,7 @@ static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob,
/*
* Paint a brush object mesh to the surface
*/
-static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *canvasOb, Object *brushOb, Scene *scene, float timescale)
+static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *canvasOb, Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -3365,32 +3452,22 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
if (!brush->dm) return 0;
{
BVHTreeFromMesh treeData = {0};
-
int numOfVerts;
int ii;
+ Bounds3D mesh_bb = {0};
+ VolumeGrid *grid = bData->grid;
- Bounds3D mesh_bb;
- VolumeGrid *grid = bData->grid;
-
- /*
- * Transform collider vertices to world space
- * (Faster than transforming per pixel
- * coordinates and normals to object space)
- */
dm = CDDM_copy(brush->dm);
mvert = dm->getVertArray(dm);
mface = dm->getFaceArray(dm);
numOfVerts = dm->getNumVerts(dm);
+ /* Transform collider vertices to global space
+ * (Faster than transforming per surface point
+ * coordinates and normals to object space) */
for (ii=0; ii<numOfVerts; ii++) {
mul_m4_v3(brushOb->obmat, mvert[ii].co);
-
- if (!ii) {
- VECCOPY(mesh_bb.min, mvert[ii].co);
- VECCOPY(mesh_bb.max, mvert[ii].co);
- }
- else
- boundInsert(&mesh_bb, mvert[ii].co);
+ boundInsert(&mesh_bb, mvert[ii].co);
}
/* check bounding box collision */
@@ -3405,20 +3482,21 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
for (c_index=0; c_index<total_cells; c_index++) {
int id;
- /* check cell bounding box */
- if (!grid->s_num[c_index] ||
- !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush))
+ /* check grid cell bounding box */
+ if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush))
continue;
- /* loop through cell points */
+ /* loop through cell points and process brush */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (id = 0; id < grid->s_num[c_index]; id++)
{
int index = grid->t_index[grid->s_pos[c_index] + id];
int ss, samples = bData->s_num[index];
float total_sample = (float)samples;
float brushStrength = 0.0f; /* brush influence factor */
- float depth = 0.0f; /* displace depth */
+ float depth = 0.0f; /* brush intersection depth */
float velocity_val = 0.0f;
float paintColor[3] = {0.0f};
@@ -3441,9 +3519,9 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
short hit_found = 0;
/* hit data */
- float hitCoord[3]; /* mid-sample hit coordinate */
- int hitFace = -1; /* mid-sample hit face */
- short hitQuad; /* mid-sample hit quad status */
+ float hitCoord[3];
+ int hitFace = -1;
+ short hitQuad;
/* Supersampling factor */
if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
@@ -3459,13 +3537,13 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
else /* MOD_DPAINT_RAY_ZPLUS */
ray_dir[2] = 1.0f;
- /* a simple hack to minimize change of ray leaks at identical ray - edge locations */
+ /* a simple hack to minimize chance of ray leaks at identical ray <-> edge locations */
VECADDVAL(ray_start, 0.001f);
hit.index = -1;
hit.dist = 9999;
nearest.index = -1;
- nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest search uses squared distance */
+ nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest uses squared distance */
/* Check volume collision */
if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
@@ -3473,21 +3551,16 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
{
/* We hit a triangle, now check if collision point normal is facing the point */
-
/* For optimization sake, hit point normal isn't calculated in ray cast loop */
int v1=mface[hit.index].v1, v2=mface[hit.index].v2, v3=mface[hit.index].v3, quad=(hit.no[0] == 1.0f);
float dot;
if (quad) {v2=mface[hit.index].v3; v3=mface[hit.index].v4;}
-
- /* Get hit normal */
normal_tri_v3( hit.no, mvert[v1].co, mvert[v2].co, mvert[v3].co);
dot = ray_dir[0]*hit.no[0] + ray_dir[1]*hit.no[1] + ray_dir[2]*hit.no[2];
- /*
- * If ray and hit normal are facing same direction
- * hit point is inside a closed mesh.
- */
+ /* If ray and hit face normal are facing same direction
+ * hit point is inside a closed mesh. */
if (dot>=0)
{
float dist = hit.dist;
@@ -3508,16 +3581,14 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
sampleStrength += sample_factor;
hit_found = HIT_VOLUME;
- /*
- * Mark hit info
- */
+ /* Mark hit info */
VECADDFAC(hitCoord, ray_start, ray_dir, hit.dist); /* Calculate final hit coordinates */
depth += dist*sample_factor;
hitFace = f_index;
hitQuad = quad;
}
}
- } // end of raycast
+ }
/* Check proximity collision */
if ((brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) &&
@@ -3531,18 +3602,16 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
/* if inverse prox and no hit found, skip this sample */
if (brush->flags & MOD_DPAINT_INVERSE_PROX && !hit_found) continue;
- /*
- * If pure distance proximity, find the nearest point on the mesh
- */
+ /* If pure distance proximity, find the nearest point on the mesh */
if (!(brush->flags & MOD_DPAINT_PROX_FACEALIGNED)) {
if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
- proxDist = sqrt(nearest.dist); /* find_nearest returns a squared distance, so gotta change it back to real distance */
+ proxDist = sqrt(nearest.dist);
copy_v3_v3(hitCo, nearest.co);
hQuad = (nearest.no[0] == 1.0f);
face = nearest.index;
}
}
- else { /* else cast a ray in surface normal direction */
+ else { /* else cast a ray in surface normal direction */
negate_v3(ray_dir);
hit.index = -1;
hit.dist = brush->paint_distance;
@@ -3568,10 +3637,9 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
dist_rate = 1.0f - dist_rate;
}
- /* if using color ramp*/
+ /* if using proximity color ramp use it's alpha */
if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && do_colorband(brush->paint_ramp, dist_rate, colorband))
prox_influence = colorband[3];
- /* if using smooth falloff, multiply gaussian factor */
else if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH) {
prox_influence = (1.0f - dist_rate) * sample_factor;
}
@@ -3614,7 +3682,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
/* simple check based on brush surface velocity,
* todo: perhaps implement something that handles volume movement as well */
- /* and now interpolate vertex speed vectors to get hit point velocity */
+ /* interpolate vertex speed vectors to get hit point velocity */
interp_v3_v3v3v3( brushPointVelocity,
brushVelocity[v1].v,
brushVelocity[v2].v,
@@ -3629,7 +3697,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
}
velocity_val = len_v3(velocity);
- /* */
+ /* if brush has smudge enabled store brush velocity */
if (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
VECCOPY(&bData->brush_velocity[index*4], velocity);
mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
@@ -3650,7 +3718,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
sampleColor[2] = brush->b;
/* Get material+textures color on hit point if required */
- if (brush->flags & MOD_DPAINT_USE_MATERIAL) dynamicPaint_getMaterialColor(sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]+ss].v, hitCoord, hitFace, hitQuad, brush->dm, brush->mat);
+ if (brush->flags & MOD_DPAINT_USE_MATERIAL)
+ dynamicPaint_doMaterialTex(bMats, sampleColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]+ss].v, hitCoord, hitFace, hitQuad, brush->dm);
/* Sample proximity colorband if required */
if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) {
@@ -3688,7 +3757,6 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
paintColor[0] /= numOfHits;
paintColor[1] /= numOfHits;
paintColor[2] /= numOfHits;
- paintColor[3] /= total_sample;
}
/* get final object space depth */
else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
@@ -3701,7 +3769,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, DynamicPaintBrus
}
}
}
- /* free bhv tree */
+ /* free bvh tree */
free_bvhtree_from_mesh(&treeData);
dm->release(dm);
@@ -3763,12 +3831,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
BLI_kdtree_insert(tree, p, pa->state.co, NULL);
/* calc particle system bounds */
- if (particlesAdded == 0) {
- VECCOPY(part_bb.min, pa->state.co);
- VECCOPY(part_bb.max, pa->state.co);
- }
- else
- boundInsert(&part_bb, pa->state.co);
+ boundInsert(&part_bb, pa->state.co);
particlesAdded++;
}
@@ -3817,7 +3880,9 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
continue;
/* loop through cell points */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (id = 0; id < grid->s_num[c_index]; id++)
{
int index = grid->t_index[grid->s_pos[c_index] + id];
@@ -3837,6 +3902,9 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
/* Find nearest particle and get distance to it */
BLI_kdtree_find_nearest(tree, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest);
+ /* if outside maximum range, no other particle can influence either */
+ if (nearest.dist > range) continue;
+
if (brush->flags & MOD_DPAINT_PART_RAD) {
/* use particles individual size */
ParticleData *pa = psys->particles + nearest.index;
@@ -3887,7 +3955,6 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
/* update hit data */
s_range = nearest[n].dist - pa->size;
-
/* skip if higher influence is already found */
if (smooth_range < s_range)
continue;
@@ -3901,13 +3968,12 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
if (s_range < 0.0f)
if (surface->type != MOD_DPAINT_SURFACE_T_DISPLACE &&
surface->type != MOD_DPAINT_SURFACE_T_WAVE)
- continue;
+ break;
}
/* now calculate influence for this particle */
{
float rad = radius + smooth, str;
-
if ((rad-dist) > disp_intersect) {
disp_intersect = radius - dist;
radius = rad;
@@ -3920,7 +3986,6 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
/* if influence is greater, use this one */
if (str > strength) strength = str;
}
-
}
if (strength > 0.001f)
@@ -3929,8 +3994,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
float depth = 0.0f;
/* apply velocity */
- if (brush->flags & MOD_DPAINT_USES_VELOCITY)
- {
+ if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
float velocity[3];
ParticleData *pa = psys->particles + part_index;
mul_v3_v3fl(velocity, pa->state.vel, particle_timestep);
@@ -3941,6 +4005,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
}
velocity_val = len_v3(velocity);
+ /* store brush velocity for smudge */
if (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
VECCOPY(&bData->brush_velocity[index*4], velocity);
mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
@@ -3978,8 +4043,9 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys
return 1;
}
+/* paint a single point of defined proximity radius to the surface */
static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
- Object *canvasOb, Object *brushOb, Scene *scene, float timescale)
+ Object *canvasOb, Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
{
int index;
PaintSurfaceData *sData = surface->data;
@@ -3992,7 +4058,9 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
/*
* Loop through every surface point
*/
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
float distance = len_v3v3(pointCoord, bData->realCoord[bData->s_pos[index]].v);
@@ -4020,10 +4088,11 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
float alpha_factor = 1.0f;
float hit_coord[3];
MVert *mvert = brush->dm->getVertArray(brush->dm);
- /* use dummy coord on first vertex */
+ /* use dummy coord of first vertex */
VECCOPY(hit_coord, mvert[0].co);
+ mul_m4_v3(brushOb->obmat, hit_coord);
- dynamicPaint_getMaterialColor(paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, 0, brush->dm, brush->mat);
+ dynamicPaint_doMaterialTex(bMats, paintColor, &alpha_factor, brushOb, bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, 0, brush->dm);
}
/* color ramp */
@@ -4042,6 +4111,7 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
}
velocity_val = len_v3(velocity);
+ /* store brush velocity for smudge */
if (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity) {
VECCOPY(&bData->brush_velocity[index*4], velocity);
mul_v3_fl(&bData->brush_velocity[index*4], 1.0f/velocity_val);
@@ -4050,7 +4120,6 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
}
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
-
if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP &&
!(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
paintColor[0] = colorband[0];
@@ -4074,7 +4143,6 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
}
dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
}
-
}
return 1;
@@ -4102,7 +4170,9 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int
bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeNeighPoint),"PaintEffectBake");
if (!bNeighs) return;
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
int i;
@@ -4135,6 +4205,74 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int
bData->average_dist /= adj_data->total_targets;
}
+/* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force */
+void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2])
+{
+ BakeNeighPoint *bNeighs = sData->bData->bNeighs;
+ int numOfNeighs = sData->adj_data->n_num[index];
+ int i;
+
+ closest_id[0]=closest_id[1]= -1;
+ closest_d[0]=closest_d[1]= -1.0f;
+
+ /* find closest 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);
+
+ if (dir_dot>closest_d[0] && dir_dot>0.0f) {closest_d[0]=dir_dot; closest_id[0]=n_index;}
+ }
+
+ if (closest_d[0] < 0.0f) return;
+
+ /* find second closest 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);
+ float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir);
+
+ 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;}
+ }
+
+ /* if two valid neighs found, calculate how force effect is divided
+ * evenly between them (so that d[0]+d[1] = 1.0)*/
+ if (closest_id[1] != -1) {
+ float force_proj[3];
+ float tangent[3];
+ float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
+ float force_intersect;
+ float temp;
+
+ /* project force vector on the plane determined by these two neightbour points
+ * and calculate relative force angle from it*/
+ cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
+ normalize_v3(tangent);
+ force_intersect = dot_v3v3(force, tangent);
+ madd_v3_v3v3fl(force_proj, force, tangent, (-1.0f)*force_intersect);
+ normalize_v3(force_proj);
+
+ /* get drip factor based on force dir in relation to angle between those neighbours */
+ temp = dot_v3v3(bNeighs[closest_id[0]].dir, force_proj);
+ CLAMP(temp, -1.0f, 1.0f); /* float precision might cause values > 1.0f that return infinite */
+ closest_d[1] = acos(temp)/neigh_diff;
+ closest_d[0] = 1.0f - closest_d[1];
+
+ /* and multiply depending on how deeply force intersects surface */
+ temp = fabs(force_intersect);
+ CLAMP(temp, 0.0f, 1.0f);
+ closest_d[0] *= acos(temp)/1.57079633f;
+ closest_d[1] *= acos(temp)/1.57079633f;
+ }
+ else {
+ /* if only single neighbour, still linearize force intersection effect */
+ closest_d[0] = 1.0f - acos(closest_d[0])/1.57079633f;
+ }
+}
+
static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, float timescale)
{
PaintSurfaceData *sData = surface->data;
@@ -4159,65 +4297,17 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
for (index = 0; index < sData->total_points; index++) {
int i;
- int numOfNeighs = sData->adj_data->n_num[index];
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
- float smudge_dir[3];
float smudge_str = bData->brush_velocity[index*4+3];
- /* 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};
+ /* force targets */
+ int closest_id[2];
+ float closest_d[2];
if (!smudge_str) continue;
-
- VECCOPY(smudge_dir, &bData->brush_velocity[index*4]);
- /* 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, smudge_dir);
-
- 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, smudge_dir);
- float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir);
-
- 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;}
- }
-
- /* if two valid neighs found, change closest_d
- * values to match final paint factors */
- if (closest_id[1] != -1) {
- float force_proj[3];
- float tangent[3];
- float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
- float force_intersect;
-
- /* project force vector on the plane determined by these two neightbour points
- * and calculate relative force angle from it*/
- cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
- normalize_v3(tangent);
- force_intersect = dot_v3v3(smudge_dir, tangent);
- madd_v3_v3v3fl(force_proj, smudge_dir, tangent, (-1.0f)*force_intersect);
- normalize_v3(force_proj);
-
- /* get drip factor based on force dir in relation to angle between those neighbours */
- closest_d[1] = acos(dot_v3v3(bNeighs[closest_id[0]].dir, force_proj))/neigh_diff;
- closest_d[0] = 1.0f - closest_d[1];
-
- /* and multiply depending on how deeply force intersects surface */
- closest_d[0] *= acos(fabs(force_intersect))/1.57079633f;
- closest_d[1] *= acos(fabs(force_intersect))/1.57079633f;
- }
-
+
+ /* get force affect points */
+ surface_determineForceTargetPoints(sData, index, &bData->brush_velocity[index*4], closest_d, closest_id);
/* Apply movement towards those two points */
for (i=0; i<2; i++) {
@@ -4277,7 +4367,9 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
*force = MEM_mallocN(sData->total_points*4*sizeof(float), "PaintEffectForces");
if (*force) {
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
float forc[3] = {0};
@@ -4342,8 +4434,6 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/bData->average_dist*timescale);
CLAMP(steps, 1, 14);
- //printf("Average distance is %f, avg force %f, num of steps %i\n", average_dist, average_force, steps);
-
return steps;
}
@@ -4369,7 +4459,9 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* Copy current surface to the previous points array to read unmodified values */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
int i;
@@ -4377,10 +4469,8 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
float totalAlpha = 0.0f;
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
- /*
- * Only reads values from the surface copy (prevPoint[]),
- * so this one is thread safe
- */
+ /* Only reads values from the surface copy (prevPoint[]),
+ * so this one is thread safe */
/* Loop through neighbouring points */
for (i=0; i<numOfNeighs; i++) {
@@ -4431,7 +4521,9 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* Copy current surface to the previous points array to read unmodified values */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
int i;
@@ -4463,10 +4555,8 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
pPoint->alpha -= a_factor;
if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f;
-
pPoint->e_alpha -= ea_factor;
if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f;
-
pPoint->wetness -= w_factor;
if (pPoint->wetness < 0.0f) pPoint->wetness = 0.0f;
}
@@ -4484,64 +4574,18 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
for (index = 0; index < sData->total_points; index++) {
int i;
- int numOfNeighs = sData->adj_data->n_num[index];
PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
PaintPoint *pPoint_prev = &prevPoint[index];
- /* to make dripping happen with as little spread as possible, */
- int closest_id[2] = {-1, -1};
- float closest_d[2] = {-1.0f, -1.0f};
+ int closest_id[2];
+ float closest_d[2];
/* adjust drip speed depending on wetness */
float w_factor = pPoint_prev->wetness*0.5 - 0.025f;
if (w_factor <= 0) continue;
- /* 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]);
-
- 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);
-
- 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;}
- }
-
- /* if two valid neighs found, change closest_d
- * values to match final paint factors */
- if (closest_id[1] != -1) {
- float force_proj[3];
- float tangent[3];
- float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
- float force_intersect;
-
- /* project force vector on the plane determined by these two neightbour points
- * and calculate relative force angle from it*/
- cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
- normalize_v3(tangent);
- force_intersect = dot_v3v3(&force[index*4], tangent);
- madd_v3_v3v3fl(force_proj, &force[index*4], tangent, (-1.0f)*force_intersect);
- normalize_v3(force_proj);
-
- /* get drip factor based on force dir in relation to angle between those neighbours */
- closest_d[1] = acos(dot_v3v3(bNeighs[closest_id[0]].dir, force_proj))/neigh_diff;
- closest_d[0] = 1.0f - closest_d[1];
-
- /* and multiply depending on how deeply force intersects surface */
- closest_d[0] *= acos(fabs(force_intersect))/1.57079633f;
- closest_d[1] *= acos(fabs(force_intersect))/1.57079633f;
- }
-
+ /* get force affect points */
+ surface_determineForceTargetPoints(sData, index, &force[index*4], closest_d, closest_id);
/* Apply movement towards those two points */
for (i=0; i<2; i++) {
@@ -4571,7 +4615,9 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
}
/* Keep values within acceptable range */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++)
{
PaintPoint *cPoint = &((PaintPoint*)sData->type_data)[index];
@@ -4628,7 +4674,9 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
/* copy previous frame data */
memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(PaintWavePoint));
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++) {
PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
int numOfNeighs = sData->adj_data->n_num[index];
@@ -4661,13 +4709,11 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
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 do wave eq */
else {
/* add force towards zero height based on average dist */
if (avg_dist)
@@ -4683,8 +4729,10 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
}
}
- /* reset d_obs and state */
+ /* reset state */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index = 0; index < sData->total_points; index++) {
PaintWavePoint *wPoint = &((PaintWavePoint*)sData->type_data)[index];
wPoint->state = 0;
@@ -4701,7 +4749,9 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time
PaintSurfaceData *sData = surface->data;
int index;
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index=0; index<sData->total_points; index++)
{
/* Do drying dissolve effects */
@@ -4761,7 +4811,7 @@ static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob
if (!bData->prev_verts) return 1;
- /* matrix */
+ /* matrix comparison */
for (i=0; i<4; i++) {
int j;
for (j=0; j<4; j++)
@@ -4769,7 +4819,9 @@ static int dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob
}
/* vertices */
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (i=0; i<numOfVerts; i++) {
int j;
for (j=0; j<3; j++)
@@ -4848,9 +4900,9 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
bData->s_pos = MEM_mallocN(sData->total_points*sizeof(unsigned int), "Dynamic Paint bData s_pos");
bData->s_num = MEM_mallocN(sData->total_points*sizeof(unsigned int), "Dynamic Paint bData s_num");
bData->realCoord = (struct Vec3f *) MEM_mallocN(surface_totalSamples(surface)*sizeof(Vec3f), "Dynamic Paint point coords");
-
bData->prev_verts = MEM_mallocN(canvasNumOfVerts*sizeof(MVert), "Dynamic Paint bData prev_verts");
+ /* if any allocation failed, free everything */
if (!bData->bNormal || !bData->s_pos || !bData->s_num || !bData->realCoord || !canvas_verts) {
if (bData->bNormal) MEM_freeN(bData->bNormal);
if (bData->s_pos) MEM_freeN(bData->s_pos);
@@ -4877,9 +4929,10 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
/*
* Make a transformed copy of canvas derived mesh vertices to avoid recalculation.
*/
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index=0; index<canvasNumOfVerts; index++) {
- /* Multiply coordinates by canvas transformation matrix */
VECCOPY(canvas_verts[index].v, mvert[index].co);
mul_m4_v3(ob->obmat, canvas_verts[index].v);
}
@@ -4887,7 +4940,9 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
/*
* Prepare each surface point for a new step
*/
+ #ifdef _OPENMP
#pragma omp parallel for schedule(static)
+ #endif
for (index=0; index<sData->total_points; index++)
{
float prev_point[3];
@@ -4895,7 +4950,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
VECCOPY(prev_point, bData->realCoord[bData->s_pos[index]].v);
}
/*
- * Calculate current 3D-position of each surface pixel
+ * Calculate current 3D-position and normal of each surface point
*/
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
float n1[3], n2[3], n3[3];
@@ -4926,9 +4981,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
negate_v3(bData->bNormal[index].invNorm);
}
else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
- /* In case of verted data */
int ss;
-
if (surface->flags & MOD_DPAINT_ANTIALIAS && adj_data) {
bData->s_num[index] = adj_data->n_num[index]+1;
bData->s_pos[index] = adj_data->n_index[index]+index;
@@ -4938,7 +4991,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
bData->s_pos[index] = index;
}
- /* per sample coordinates */
+ /* calculate position for each sample */
for (ss=0; ss<bData->s_num[index]; ss++) {
/* first sample is always point center */
VECCOPY(bData->realCoord[bData->s_pos[index]+ss].v, canvas_verts[index].v);
@@ -4957,7 +5010,8 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
negate_v3(bData->bNormal[index].invNorm);
}
- /* Prepare special data for surface types */
+ /* Prepare surface normal directional scale to easily convert
+ * brush intersection amount between global and local space */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
float temp_nor[3];
@@ -4991,11 +5045,10 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
/* generate surface space partitioning grid */
surfaceGenerateGrid(surface);
-
/* calculate current frame neighbouring point distances and global dirs */
dynamicPaint_prepareNeighbourData(surface, 0);
- /* Copy current frame position to check against in next frame */
+ /* Copy current frame vertices to check against in next frame */
copy_m4_m4(bData->prev_obmat, ob->obmat);
memcpy(bData->prev_verts, mvert, canvasNumOfVerts*sizeof(MVert));
@@ -5005,7 +5058,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
}
/*
-* Do Dynamic Paint Step. Paints scene brush objects of current state/frame to canvas.
+* Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface.
*/
static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe)
{
@@ -5013,7 +5066,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
PaintBakeData *bData = sData->bData;
DynamicPaintCanvasSettings *canvas = surface->canvas;
int ret = 1;
-
if (!sData || sData->total_points < 1) return 0;
dynamicPaint_surfacePreStep(surface, timescale);
@@ -5023,7 +5075,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
{
Base *base = NULL;
GroupObject *go = NULL;
-
Object *brushObj = NULL;
ModifierData *md = NULL;
@@ -5040,7 +5091,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
while (base || go)
{
brushObj = NULL;
-
/* select object */
if(surface->brush_group) {
if(go->ob) brushObj = go->ob;
@@ -5048,8 +5098,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
else
brushObj = base->object;
- if(!brushObj)
- {
+ if(!brushObj) {
/* skip item */
if(surface->brush_group) go = go->next;
else base= base->next;
@@ -5062,17 +5111,16 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
else
base= base->next;
- md = modifiers_findByType(brushObj, eModifierType_DynamicPaint);
-
/* check if target has an active dp modifier */
+ md = modifiers_findByType(brushObj, eModifierType_DynamicPaint);
if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
{
DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
-
- /* Make sure we're dealing with a brush */
+ /* make sure we're dealing with a brush */
if (pmd2->brush)
{
DynamicPaintBrushSettings *brush = pmd2->brush;
+ BrushMaterials bMats = {0};
/* calculate brush speed vectors if required */
if (brush->flags & MOD_DPAINT_DO_SMUDGE) {
@@ -5084,45 +5132,43 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
dynamicPaint_prepareNeighbourData(surface, 1);
}
- /* update object position on this subframe */
+ /* update object data on this subframe */
if (subframe) {
scene_setSubframe(scene, subframe);
subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_curframe(scene));
}
-
- /* If using material color, update anim data to current (sub)frame */
+ /* Prepare materials if required */
if (brush->flags & MOD_DPAINT_USE_MATERIAL)
- dynamicPaint_updateObjectMaterials(brushObj, brush->mat, scene);
+ dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
- /*
- * Paint brush on surface depending on it's collision type
- */
- /* Particle brush */
- if (brush->collision == MOD_DPAINT_COL_PSYS)
- {
- if (brush && brush->psys && brush->psys->part && brush->psys->part->type==PART_EMITTER)
- if (psys_check_enabled(brushObj, brush->psys)) {
+ /* Apply brush on the surface depending on it's collision type */
+ /* Particle brush: */
+ if (brush->collision == MOD_DPAINT_COL_PSYS) {
+ if (brush && brush->psys && brush->psys->part && brush->psys->part->type==PART_EMITTER &&
+ psys_check_enabled(brushObj, brush->psys)) {
/* Paint a particle system */
BKE_animsys_evaluate_animdata(&brush->psys->part->id, brush->psys->part->adt, BKE_curframe(scene), ADT_RECALC_ANIM);
dynamicPaint_paintParticles(surface, brush->psys, brush, ob, timescale);
}
}
- /* Object center distance */
+ /* Object center distance: */
else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
- dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, ob, brushObj, scene, timescale);
+ dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, ob, brushObj, &bMats, scene, timescale);
}
- /* Mesh volume/proximity */
- else if (brushObj != ob){
- dynamicPaint_paintMesh(surface, brush, ob, brushObj, scene, timescale);
+ /* Mesh volume/proximity: */
+ else if (brushObj != ob) {
+ dynamicPaint_paintMesh(surface, brush, ob, brushObj, &bMats, scene, timescale);
}
+ /* free temp material data */
+ if (brush->flags & MOD_DPAINT_USE_MATERIAL)
+ dynamicPaint_freeBrushMaterials(&bMats);
/* reset object to it's original state */
if (subframe) {
scene->r.cfra = scene_frame;
scene->r.subframe = scene_subframe;
subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_curframe(scene));
- dynamicPaint_updateObjectMaterials(brushObj, brush->mat, scene);
}
/* process special brush effects, like smudge */
@@ -5132,7 +5178,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
MEM_freeN(bData->brush_velocity);
bData->brush_velocity = NULL;
}
- } /* end of collision check (Is valid paint modifier) */
+ }
}
}
}
@@ -5145,7 +5191,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
dynamicPaint_doWaveStep(surface, timescale);
}
- /* paint movement effects */
+ /* paint surface effects */
if (surface->effect && surface->type == MOD_DPAINT_SURFACE_T_PAINT)
{
int steps = 1, s;
@@ -5159,12 +5205,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* Prepare effects and get number of required steps */
steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale);
-
- /*
- * Do Effects steps
- */
- for (s = 0; s < steps; s++)
- {
+ for (s = 0; s < steps; s++) {
dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps);
}
@@ -5178,7 +5219,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
}
/*
-* Calculate a single frame for canvas point cache
+* Calculate a single frame and included subframes for surface
*/
static int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame)
{
@@ -5196,10 +5237,8 @@ static int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scen
int st;
timescale = 1.0f / (surface->substeps+1);
- for (st = 1; st <= surface->substeps; st++)
- {
+ for (st = 1; st <= surface->substeps; st++) {
float subframe = ((float) st) / (surface->substeps+1);
-
if (!dynamicPaint_doStep(scene, cObject, surface, timescale, subframe)) return 0;
}
}
@@ -5261,7 +5300,7 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf
char filename[250];
char pad[4];
char dir_slash[2];
- /* OpenEXR or PNG */
+ /* OpenEXR or PNG */
short format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? DPOUTPUT_OPENEXR : DPOUTPUT_PNG;
/* Add frame number padding */
@@ -5308,12 +5347,12 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf
/*
-* An operator call to start baking dynamic paint image sequences for active object
+* Bake Dynamic Paint image sequence surface
*/
-static int dynamicPaint_initBake(bContext *C, wmOperator *op)
+int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op)
{
DynamicPaintModifierData *pmd = NULL;
- Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ Object *ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
int status = 0;
double timer = PIL_check_seconds_timer();
DynamicPaintSurface *surface;
@@ -5321,7 +5360,7 @@ static int dynamicPaint_initBake(bContext *C, wmOperator *op)
/*
* Get modifier data
*/
- pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
+ pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
if (!pmd) {
BKE_report(op->reports, RPT_ERROR, "Bake Failed: No Dynamic Paint modifier found.");
return 0;
@@ -5340,7 +5379,7 @@ static int dynamicPaint_initBake(bContext *C, wmOperator *op)
G.afbreek= 0; /* reset blender_test_break*/
/* Bake Dynamic Paint */
- status = dynamicPaint_bakeImageSequence(C, surface, cObject);
+ status = dynamicPaint_bakeImageSequence(C, surface, ob);
/* Clear bake */
pmd->canvas->flags &= ~MOD_DPAINT_BAKING;
WM_cursor_restore(CTX_wm_window(C));
@@ -5392,235 +5431,3 @@ static int dynamicPaint_initBake(bContext *C, wmOperator *op)
return status;
}
-
-
-/***************************** Operators ******************************/
-
-static int dynamicpaint_bake_exec(bContext *C, wmOperator *op)
-{
-
- /* Bake dynamic paint */
- if(!dynamicPaint_initBake(C, op)) {
- return OPERATOR_CANCELLED;}
-
- return OPERATOR_FINISHED;
-}
-
-void DPAINT_OT_bake(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Dynamic Paint Bake";
- ot->description= "Bake dynamic paint";
- ot->idname= "DPAINT_OT_bake";
-
- /* api callbacks */
- ot->exec= dynamicpaint_bake_exec;
- ot->poll= ED_operator_object_active_editable;
-}
-
-static int surface_slot_add_exec(bContext *C, wmOperator *op)
-{
- DynamicPaintModifierData *pmd = NULL;
- Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
- DynamicPaintSurface *surface;
-
- /* Make sure we're dealing with a canvas */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
- if (!pmd) return OPERATOR_CANCELLED;
- if (!pmd->canvas) return OPERATOR_CANCELLED;
-
- surface = dynamicPaint_createNewSurface(pmd->canvas, CTX_data_scene(C));
-
- if (!surface) return OPERATOR_CANCELLED;
-
- /* set preview for this surface only and set active */
- pmd->canvas->active_sur = 0;
- for(surface=surface->prev; surface; surface=surface->prev) {
- surface->flags &= ~MOD_DPAINT_PREVIEW;
- pmd->canvas->active_sur++;
- }
-
- return OPERATOR_FINISHED;
-}
-
-/* add surface slot */
-void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Add Surface Slot";
- ot->idname= "DPAINT_OT_surface_slot_add";
- ot->description="Add a new Dynamic Paint surface slot";
-
- /* api callbacks */
- ot->exec= surface_slot_add_exec;
- ot->poll= ED_operator_object_active_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int surface_slot_remove_exec(bContext *C, wmOperator *op)
-{
- DynamicPaintModifierData *pmd = NULL;
- Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
- DynamicPaintSurface *surface;
- int id=0;
-
- /* Make sure we're dealing with a canvas */
- pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
- if (!pmd) return OPERATOR_CANCELLED;
- if (!pmd->canvas) return OPERATOR_CANCELLED;
-
- surface = pmd->canvas->surfaces.first;
-
- /* find active surface and remove it */
- for(; surface; surface=surface->next) {
- if(id == pmd->canvas->active_sur) {
- pmd->canvas->active_sur -= 1;
- dynamicPaint_freeSurface(surface);
- break;
- }
- id++;
- }
-
- dynamicPaint_resetPreview(pmd->canvas);
- DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject);
-
- return OPERATOR_FINISHED;
-}
-
-/* remove surface slot */
-void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Remove Surface Slot";
- ot->idname= "DPAINT_OT_surface_slot_remove";
- ot->description="Remove the selected surface slot";
-
- /* api callbacks */
- ot->exec= surface_slot_remove_exec;
- ot->poll= ED_operator_object_active_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int type_toggle_exec(bContext *C, wmOperator *op)
-{
-
- Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
- Scene *scene = CTX_data_scene(C);
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
- int type= RNA_enum_get(op->ptr, "type");
-
- if (!pmd) return OPERATOR_CANCELLED;
-
- /* if type is already enabled, toggle it off */
- if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
- dynamicPaint_freeCanvas(pmd);
- }
- else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
- dynamicPaint_freeBrush(pmd);
- }
- /* else create a new type */
- else {
- if (!dynamicPaint_createType(pmd, type, scene))
- return OPERATOR_CANCELLED;
- }
-
- /* update dependancy */
- DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject);
- DAG_scene_sort(CTX_data_main(C), scene);
-
- return OPERATOR_FINISHED;
-}
-
-void DPAINT_OT_type_toggle(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Toggle Type Active";
- ot->idname= "DPAINT_OT_type_toggle";
- ot->description = "Toggles whether given type is active or not";
-
- /* api callbacks */
- ot->exec= type_toggle_exec;
- ot->poll= ED_operator_object_active_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "type", prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", "");
- ot->prop= prop;
-}
-
-static int output_toggle_exec(bContext *C, wmOperator *op)
-{
-
- Object *ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
- Scene *scene = CTX_data_scene(C);
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
- int index= RNA_int_get(op->ptr, "index");
-
- if (!pmd) return OPERATOR_CANCELLED;
-
-
- /* if type is already enabled, toggle it off */
- if (pmd->canvas) {
- DynamicPaintSurface *surface = get_activeSurface(pmd->canvas);
-
- if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
- int exists = dynamicPaint_outputLayerExists(surface, ob, index);
- char *name;
-
- if (index == 0)
- name = surface->output_name;
- else if (index == 1)
- name = surface->output_name2;
-
- /* Vertex Color Layer */
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- if (!exists)
- ED_mesh_color_add(C, scene, ob, ob->data, name, 1);
- else
- ED_mesh_color_remove_named(C, ob, ob->data, name);
- }
- /* Vertex Weight Layer */
- else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
- if (!exists)
- ED_vgroup_add_name(ob, name);
- else {
- bDeformGroup *defgroup = defgroup_find_name(ob, name);
- if (defgroup) ED_vgroup_delete(ob, defgroup);
- }
- }
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void DPAINT_OT_output_toggle(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Toggle Output Layer";
- ot->idname= "DPAINT_OT_output_toggle";
- ot->description = "Adds or removes Dynamic Paint output data layer.";
-
- /* api callbacks */
- ot->exec= output_toggle_exec;
- ot->poll= ED_operator_object_active_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_int(ot->srna, "index", 0, 0, 1, "Index", "", 0, 1);
- ot->prop= prop;
-} \ No newline at end of file
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index f32b23cd3ee..0455e80ea33 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC_SYS
)
set(SRC
+ dynamicpaint_ops.c
particle_boids.c
particle_edit.c
particle_object.c
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
new file mode 100644
index 00000000000..8a4007745de
--- /dev/null
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -0,0 +1,268 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "DNA_dynamicpaint_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_dynamicpaint.h"
+#include "BKE_modifier.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+static int dynamicpaint_bake_exec(bContext *C, wmOperator *op)
+{
+ /* Bake dynamic paint */
+ if(!dynamicPaint_initBake(C, op)) {
+ return OPERATOR_CANCELLED;}
+
+ return OPERATOR_FINISHED;
+}
+
+void DPAINT_OT_bake(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Dynamic Paint Bake";
+ ot->description= "Bake dynamic paint image sequence surface";
+ ot->idname= "DPAINT_OT_bake";
+
+ /* api callbacks */
+ ot->exec= dynamicpaint_bake_exec;
+ ot->poll= ED_operator_object_active_editable;
+}
+
+static int surface_slot_add_exec(bContext *C, wmOperator *op)
+{
+ DynamicPaintModifierData *pmd = 0;
+ Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ DynamicPaintSurface *surface;
+
+ /* Make sure we're dealing with a canvas */
+ pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
+ if (!pmd) return OPERATOR_CANCELLED;
+ if (!pmd->canvas) return OPERATOR_CANCELLED;
+
+ surface = dynamicPaint_createNewSurface(pmd->canvas, CTX_data_scene(C));
+
+ if (!surface) return OPERATOR_CANCELLED;
+
+ /* set preview for this surface only and set active */
+ pmd->canvas->active_sur = 0;
+ for(surface=surface->prev; surface; surface=surface->prev) {
+ surface->flags &= ~MOD_DPAINT_PREVIEW;
+ pmd->canvas->active_sur++;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+/* add surface slot */
+void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Slot";
+ ot->idname= "DPAINT_OT_surface_slot_add";
+ ot->description="Add a new Dynamic Paint surface slot";
+
+ /* api callbacks */
+ ot->exec= surface_slot_add_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int surface_slot_remove_exec(bContext *C, wmOperator *op)
+{
+ DynamicPaintModifierData *pmd = 0;
+ Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ DynamicPaintSurface *surface;
+ int id=0;
+
+ /* Make sure we're dealing with a canvas */
+ pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
+ if (!pmd) return OPERATOR_CANCELLED;
+ if (!pmd->canvas) return OPERATOR_CANCELLED;
+
+ surface = pmd->canvas->surfaces.first;
+
+ /* find active surface and remove it */
+ for(; surface; surface=surface->next) {
+ if(id == pmd->canvas->active_sur) {
+ pmd->canvas->active_sur -= 1;
+ dynamicPaint_freeSurface(surface);
+ break;
+ }
+ id++;
+ }
+
+ dynamicPaint_resetPreview(pmd->canvas);
+ DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject);
+
+ return OPERATOR_FINISHED;
+}
+
+/* remove surface slot */
+void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Surface Slot";
+ ot->idname= "DPAINT_OT_surface_slot_remove";
+ ot->description="Remove the selected surface slot";
+
+ /* api callbacks */
+ ot->exec= surface_slot_remove_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int type_toggle_exec(bContext *C, wmOperator *op)
+{
+
+ Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ Scene *scene = CTX_data_scene(C);
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if (!pmd) return OPERATOR_CANCELLED;
+
+ /* if type is already enabled, toggle it off */
+ if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
+ dynamicPaint_freeCanvas(pmd);
+ }
+ else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
+ dynamicPaint_freeBrush(pmd);
+ }
+ /* else create a new type */
+ else {
+ if (!dynamicPaint_createType(pmd, type, scene))
+ return OPERATOR_CANCELLED;
+ }
+
+ /* update dependancy */
+ DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject);
+ DAG_scene_sort(CTX_data_main(C), scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void DPAINT_OT_type_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Toggle Type Active";
+ ot->idname= "DPAINT_OT_type_toggle";
+ ot->description = "Toggles whether given type is active or not";
+
+ /* api callbacks */
+ ot->exec= type_toggle_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= RNA_def_enum(ot->srna, "type", prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", "");
+ ot->prop= prop;
+}
+
+static int output_toggle_exec(bContext *C, wmOperator *op)
+{
+
+ Object *ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ Scene *scene = CTX_data_scene(C);
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
+ int index= RNA_int_get(op->ptr, "index");
+
+ if (!pmd) return OPERATOR_CANCELLED;
+
+
+ /* if type is already enabled, toggle it off */
+ if (pmd->canvas) {
+ DynamicPaintSurface *surface = get_activeSurface(pmd->canvas);
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
+ int exists = dynamicPaint_outputLayerExists(surface, ob, index);
+ char *name;
+
+ if (index == 0)
+ name = surface->output_name;
+ else if (index == 1)
+ name = surface->output_name2;
+
+ /* Vertex Color Layer */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ if (!exists)
+ ED_mesh_color_add(C, scene, ob, ob->data, name, 1);
+ else
+ ED_mesh_color_remove_named(C, ob, ob->data, name);
+ }
+ /* Vertex Weight Layer */
+ else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
+ if (!exists)
+ ED_vgroup_add_name(ob, name);
+ else {
+ bDeformGroup *defgroup = defgroup_find_name(ob, name);
+ if (defgroup) ED_vgroup_delete(ob, defgroup);
+ }
+ }
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void DPAINT_OT_output_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Toggle Output Layer";
+ ot->idname= "DPAINT_OT_output_toggle";
+ ot->description = "Adds or removes Dynamic Paint output data layer.";
+
+ /* api callbacks */
+ ot->exec= output_toggle_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= RNA_def_int(ot->srna, "index", 0, 0, 1, "Index", "", 0, 1);
+ ot->prop= prop;
+}
diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h
index 4841cf00007..2dbd1a50001 100644
--- a/source/blender/makesdna/DNA_dynamicpaint_types.h
+++ b/source/blender/makesdna/DNA_dynamicpaint_types.h
@@ -61,6 +61,12 @@ struct PaintSurfaceData;
#define MOD_DPAINT_SURFACE_PREV_PAINT 0
#define MOD_DPAINT_SURFACE_PREV_WETMAP 1
+/* init_color_type */
+#define MOD_DPAINT_INITIAL_NONE 0
+#define MOD_DPAINT_INITIAL_COLOR 1
+#define MOD_DPAINT_INITIAL_TEXTURE 2
+#define MOD_DPAINT_INITIAL_VERTEXCOLOR 3
+
typedef struct DynamicPaintSurface {
struct DynamicPaintSurface *next, *prev;
@@ -81,6 +87,7 @@ typedef struct DynamicPaintSurface {
short disp_type, image_fileformat;
short effect_ui; /* just ui selection box */
short preview_id; /* surface output id to preview */
+ short init_color_type, pad_s;
int flags, effect;
int image_resolution, substeps;
@@ -89,6 +96,12 @@ typedef struct DynamicPaintSurface {
int dry_speed, diss_speed;
float disp_clamp;
+ /* initial color */
+ float init_color[4];
+ struct Tex *init_texture;
+ char init_layername[40];
+ int pad;
+
float spread_speed, color_spread_speed, shrink_speed;
float drip_vel, drip_acc;
@@ -188,9 +201,8 @@ typedef struct DynamicPaintBrushSettings {
short wave_type;
short ray_dir;
- float wave_factor;
+ float wave_factor, wave_clamp;
float max_velocity, smudge_strength;
- float pad;
} DynamicPaintBrushSettings;
#endif
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 54beae97688..bd9915f92be 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -87,6 +87,15 @@ static void rna_DynamicPaintSurface_reset(Main *bmain, Scene *scene, PointerRNA
rna_DynamicPaint_redoModifier(bmain, scene, ptr);
}
+static void rna_DynamicPaintSurface_initialcolortype(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ DynamicPaintSurface *surface = (DynamicPaintSurface*)ptr->data;
+
+ surface->init_layername[0] = '\0';
+ dynamicPaint_clearSurface(surface);
+ rna_DynamicPaint_redoModifier(bmain, scene, ptr);
+}
+
static void rna_DynamicPaintSurface_changePreview(Main *bmain, Scene *scene, PointerRNA *ptr)
{
DynamicPaintSurface *act_surface = (DynamicPaintSurface*)ptr->data;
@@ -302,6 +311,14 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
{MOD_DPAINT_SURFACE_PREV_WETMAP, "WETMAP", 0, "Wetmap", ""},
{0, NULL, 0, NULL, NULL}};
+ /* Initial color setting */
+ static EnumPropertyItem prop_dynamicpaint_init_color_type[] = {
+ {MOD_DPAINT_INITIAL_NONE, "NONE", 0, "None", ""},
+ {MOD_DPAINT_INITIAL_COLOR, "COLOR", 0, "Color", ""},
+ {MOD_DPAINT_INITIAL_TEXTURE, "TEXTURE", 0, "UV Texture", ""},
+ {MOD_DPAINT_INITIAL_VERTEXCOLOR, "VERTEXCOLOR", 0, "Vertex Color", ""},
+ {0, NULL, 0, NULL, NULL}};
+
/* Effect type
* Only used by ui to view per effect settings */
static EnumPropertyItem prop_dynamicpaint_effecttype[] = {
@@ -358,13 +375,11 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_DynamicPaintSurface_changePreview");
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Name", "Surface name");
RNA_def_property_update(prop, NC_OBJECT, "rna_DynamicPaintSurface_uniqueName");
RNA_def_struct_name_property(srna, prop);
prop= RNA_def_property(srna, "brush_group", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "brush_group");
RNA_def_property_struct_type(prop, "Group");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Brush Group", "Only use brush objects from this group");
@@ -386,7 +401,6 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed");
prop= RNA_def_property(srna, "dry_speed", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "dry_speed");
RNA_def_property_range(prop, 1.0, 10000.0);
RNA_def_property_ui_range(prop, 1.0, 10000.0, 5, 0);
RNA_def_property_ui_text(prop, "Dry Speed", "Dry Speed");
@@ -396,7 +410,6 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
*/
prop= RNA_def_property(srna, "image_resolution", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_int_sdna(prop, NULL, "image_resolution");
RNA_def_property_range(prop, 16.0, 4096.0);
RNA_def_property_ui_range(prop, 16.0, 4096.0, 1, 0);
RNA_def_property_ui_text(prop, "Resolution", "Output image resolution");
@@ -408,7 +421,6 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_int_sdna(prop, NULL, "start_frame");
RNA_def_property_range(prop, 1.0, 9999.0);
RNA_def_property_ui_range(prop, 1.0, 9999, 1, 0);
RNA_def_property_ui_text(prop, "Start Frame", "Simulation start frame");
@@ -416,14 +428,12 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_int_sdna(prop, NULL, "end_frame");
RNA_def_property_range(prop, 1.0, 9999.0);
RNA_def_property_ui_range(prop, 1.0, 9999.0, 1, 0);
RNA_def_property_ui_text(prop, "End Frame", "Simulation end frame");
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_DynamicPaintSurfaces_updateFrames");
prop= RNA_def_property(srna, "substeps", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "substeps");
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_range(prop, 0.0, 10, 1, 0);
RNA_def_property_ui_text(prop, "Sub-Steps", "Do extra frames between scene frames to ensure smooth motion.");
@@ -435,11 +445,34 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_DynamicPaintSurface_reset");
/*
+ * Initial Color
+ */
+
+ prop= RNA_def_property(srna, "init_color_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_enum_items(prop, prop_dynamicpaint_init_color_type);
+ RNA_def_property_ui_text(prop, "Initial Color", "");
+ RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW|ND_MODIFIER, "rna_DynamicPaintSurface_initialcolortype");
+
+ prop= RNA_def_property(srna, "init_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Color", "Initial color of the surface.");
+ RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW|ND_MODIFIER, "rna_DynamicPaintSurface_reset");
+
+ prop= RNA_def_property(srna, "init_texture", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Texture", "");
+ RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW|ND_MODIFIER, "rna_DynamicPaintSurface_reset");
+
+ prop= RNA_def_property(srna, "init_layername", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Data Layer", "");
+ RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW|ND_MODIFIER, "rna_DynamicPaintSurface_reset");
+
+ /*
* Effect Settings
*/
prop= RNA_def_property(srna, "effect_ui", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_sdna(prop, NULL, "effect_ui");
RNA_def_property_enum_items(prop, prop_dynamicpaint_effecttype);
RNA_def_property_ui_text(prop, "Effect Type", "");
@@ -554,20 +587,17 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
prop= RNA_def_property(srna, "disp_clamp", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_float_sdna(prop, NULL, "disp_clamp");
RNA_def_property_range(prop, 0.00, 50.0);
RNA_def_property_ui_range(prop, 0.00, 5.0, 1, 2);
- RNA_def_property_ui_text(prop, "Clamp Displace", "Maximum level of displace intersection. Use 0.0 to disable.");
+ RNA_def_property_ui_text(prop, "Clamp Displace", "Maximum level of displace intersection in mesh space. Use 0.0 to disable.");
prop= RNA_def_property(srna, "image_fileformat", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_sdna(prop, NULL, "image_fileformat");
RNA_def_property_enum_items(prop, prop_dynamicpaint_image_fileformat);
RNA_def_property_ui_text(prop, "File Format", "");
prop= RNA_def_property(srna, "disp_type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_sdna(prop, NULL, "disp_type");
RNA_def_property_enum_items(prop, prop_dynamicpaint_disp_type);
RNA_def_property_ui_text(prop, "Data Type", "");
@@ -579,25 +609,21 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
/* 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 propogation 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.001, 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.");
@@ -640,7 +666,6 @@ static void rna_def_dynamic_paint_canvas_settings(BlenderRNA *brna)
rna_def_canvas_surfaces(brna, prop);
prop= RNA_def_property(srna, "ui_info", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "ui_info");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Bake Info", "Info on bake status");
}
@@ -732,28 +757,29 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
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, 5, 2);
RNA_def_property_ui_text(prop, "Factor", "Multiplier for wave influence of this brush.");
+ prop= RNA_def_property(srna, "wave_clamp", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.00, 50.0);
+ RNA_def_property_ui_range(prop, 0.00, 5.0, 1, 2);
+ RNA_def_property_ui_text(prop, "Clamp Waves", "Maximum level of surface intersection used to influence waves. Use 0.0 to disable.");
+
prop= RNA_def_property(srna, "do_smudge", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_DO_SMUDGE);
RNA_def_property_ui_text(prop, "Do Smudge", "Makes this brush to smudge existing paint as it moves.");
prop= RNA_def_property(srna, "smudge_strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "smudge_strength");
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_range(prop, 0.0, 1.0, 5, 2);
RNA_def_property_ui_text(prop, "Smudge Strength", "Smudge effect strength");
prop= RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "max_velocity");
RNA_def_property_range(prop, 0.0001, 10.0);
RNA_def_property_ui_range(prop, 0.1, 2.0, 5, 2);
RNA_def_property_ui_text(prop, "Max Velocity", "Velocity considered as maximum influence. (Blender units per frame)");
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 58d7890b0ce..1e011146c82 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -112,6 +112,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
for(; surface; surface=surface->next) {
walk(userData, ob, (ID **)&surface->brush_group);
+ walk(userData, ob, (ID **)&surface->init_texture);
}
}
if (pmd->brush) {
@@ -119,6 +120,12 @@ static void foreachIDLink(ModifierData *md, Object *ob,
}
}
+static void foreachTexLink(ModifierData *md, Object *ob,
+ TexWalkFunc walk, void *userData)
+{
+ walk(userData, ob, md, ""); /* property name isn't used */
+}
+
ModifierTypeInfo modifierType_DynamicPaint = {
/* name */ "Dynamic Paint",
/* structName */ "DynamicPaintModifierData",
@@ -144,4 +151,5 @@ ModifierTypeInfo modifierType_DynamicPaint = {
/* dependsOnNormals */ 0,
/* foreachObjectLink */ 0,
/* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ foreachTexLink,
};
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index a63c4f7f253..1da144a099f 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -68,7 +68,7 @@ void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag, short thread);
void do_material_tex(struct ShadeInput *shi);
void do_lamp_tex(LampRen *la, float *lavec, struct ShadeInput *shi, float *colf, int effect);
-void do_volume_tex(struct ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val);
+void do_volume_tex(struct ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val, struct Render *re);
void init_render_textures(Render *re);
void end_render_textures(Render *re);
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 138eca2dd9b..9a5de4ae937 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -2673,7 +2673,7 @@ void do_material_tex(ShadeInput *shi)
}
-void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val)
+void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val, Render *re)
{
MTex *mtex;
Tex *tex;
@@ -2682,7 +2682,7 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
float co[3], texvec[3];
float fact, stencilTin=1.0;
- if (R.r.scemode & R_NO_TEX) return;
+ if (re->r.scemode & R_NO_TEX) return;
/* here: test flag if there's a tex (todo) */
for(tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
@@ -2724,7 +2724,7 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
}
else if(mtex->texco==TEXCO_GLOB) {
VECCOPY(co, xyz);
- mul_m4_v3(R.viewinv, co);
+ mul_m4_v3(re->viewinv, co);
}
else continue; // can happen when texco defines disappear and it renders old files
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index 19bbb11e143..dcb3c9d5749 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -290,7 +290,7 @@ float vol_get_density(struct ShadeInput *shi, float *co)
float density_scale = shi->mat->vol.density_scale;
if (shi->mat->mapto_textured & MAP_DENSITY)
- do_volume_tex(shi, co, MAP_DENSITY, NULL, &density);
+ do_volume_tex(shi, co, MAP_DENSITY, NULL, &density, &R);
// if meta-object, modulate by metadensity without increasing it
if (shi->obi->obr->ob->type == OB_MBALL) {
@@ -312,11 +312,11 @@ static void vol_get_reflection_color(ShadeInput *shi, float *ref_col, float *co)
VECCOPY(ref_col, shi->mat->vol.reflection_col);
if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_REFLECTION_COL))
- do_volume_tex(shi, co, MAP_SCATTERING+MAP_REFLECTION_COL, ref_col, &scatter);
+ do_volume_tex(shi, co, MAP_SCATTERING+MAP_REFLECTION_COL, ref_col, &scatter, &R);
/* only one single float parameter at a time... :s */
if (shi->mat->mapto_textured & (MAP_REFLECTION))
- do_volume_tex(shi, co, MAP_REFLECTION, NULL, &reflection);
+ do_volume_tex(shi, co, MAP_REFLECTION, NULL, &reflection, &R);
ref_col[0] = reflection * ref_col[0] * scatter;
ref_col[1] = reflection * ref_col[1] * scatter;
@@ -331,7 +331,7 @@ static void vol_get_emission(ShadeInput *shi, float *emission_col, float *co)
VECCOPY(emission_col, shi->mat->vol.emission_col);
if (shi->mat->mapto_textured & (MAP_EMISSION+MAP_EMISSION_COL))
- do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission);
+ do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission, &R);
emission_col[0] = emission_col[0] * emission;
emission_col[1] = emission_col[1] * emission;
@@ -351,7 +351,7 @@ static void vol_get_sigma_t(ShadeInput *shi, float *sigma_t, float *co)
float scattering = shi->mat->vol.scattering;
if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_TRANSMISSION_COL))
- do_volume_tex(shi, co, MAP_SCATTERING+MAP_TRANSMISSION_COL, transmission_col, &scattering);
+ do_volume_tex(shi, co, MAP_SCATTERING+MAP_TRANSMISSION_COL, transmission_col, &scattering, &R);
sigma_t[0] = (1.0f - transmission_col[0]) + scattering;
sigma_t[1] = (1.0f - transmission_col[1]) + scattering;
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 0ac5157e34f..c0879eae773 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -124,6 +124,8 @@ int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osa
int multitex_ext_safe(struct Tex *tex, float *texvec, struct TexResult *texres){return 0;}
int multitex_nodes(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex) {return 0;}
void texco_mapping_ext(float *facenor, struct Tex* tex, struct MTex* mtex, float* co, float* dx, float* dy, float* texvec){}
+void do_material_tex(struct ShadeInput *shi) {}
+void do_volume_tex(struct ShadeInput *shi, float *xyz, int mapto_flag, float *col, float *val, struct Render *re) {}
/* nodes */
struct RenderResult *RE_GetResult(struct Render *re){return (struct RenderResult *) NULL;}