From 30cba27987362054d16b10e73ddf2601af93be68 Mon Sep 17 00:00:00 2001 From: Miika Hamalainen Date: Sat, 22 Oct 2011 16:16:14 +0000 Subject: [PATCH] Dynamic Paint: * Some changes and cleanup pointed on the codereview. --- .../bl_ui/properties_physics_dynamicpaint.py | 133 +++--- source/blender/blenkernel/BKE_dynamicpaint.h | 2 - .../blender/blenkernel/intern/dynamicpaint.c | 394 ++---------------- source/blender/blenlib/BLI_kdtree.h | 1 - source/blender/blenlib/BLI_threads.h | 4 + source/blender/blenlib/intern/BLI_kdtree.c | 87 ---- source/blender/blenlib/intern/threads.c | 14 + source/blender/blenloader/intern/readfile.c | 14 +- .../editors/physics/dynamicpaint_ops.c | 48 +-- .../blender/makesdna/DNA_dynamicpaint_types.h | 2 +- .../makesrna/intern/rna_dynamicpaint.c | 13 +- .../modifiers/intern/MOD_dynamicpaint.c | 32 +- .../render/extern/include/RE_render_ext.h | 7 + .../blender/render/intern/include/texture.h | 2 +- .../render/intern/source/render_texture.c | 258 +++++++++++- .../blender/render/intern/source/shadeinput.c | 26 +- .../render/intern/source/shadeoutput.c | 16 +- .../bad_level_call_stubs/stubs.c | 10 +- 18 files changed, 475 insertions(+), 588 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py index 4c59ed85639..4a116707d0e 100644 --- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py +++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py @@ -92,59 +92,28 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, bpy.types.Panel): layout.operator("dpaint.type_toggle", text="Add Brush").type = 'BRUSH' else: layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH' - - layout.prop(brush, "brush_settings_context", expand=True, icon_only=True) - - if (brush.brush_settings_context == "GENERAL"): - split = layout.split() - col = split.column() - col.prop(brush, "absolute_alpha") - col.prop(brush, "paint_erase") - col.prop(brush, "paint_wetness", text="Wetness") - - col = split.column() - sub = col.column() - sub.active = (brush.paint_source != "PSYS"); - sub.prop(brush, "use_material") - if brush.use_material and brush.paint_source != "PSYS": - col.prop(brush, "material", text="") - col.prop(brush, "paint_alpha", text="Alpha Factor") - else: - col.prop(brush, "paint_color", text="") - col.prop(brush, "paint_alpha", text="Alpha") - - elif (brush.brush_settings_context == "WAVE"): - layout.prop(brush, "wave_type") - if (brush.wave_type != "REFLECT"): - 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:") - split = layout.split() - col = split.column() - col.prop(brush, "velocity_alpha") - col.prop(brush, "velocity_color") - col = split.column() - col.prop(brush, "velocity_depth") - sub = layout.row().column() - sub.active = (brush.velocity_alpha or brush.velocity_color or brush.velocity_depth) - sub.prop(brush, "max_velocity") - sub.template_color_ramp(brush, "velocity_ramp", expand=True) - layout.separator() - layout.label(text="Smudge:") - layout.prop(brush, "do_smudge") - layout.prop(brush, "smudge_strength") + split = layout.split() + + col = split.column() + col.prop(brush, "absolute_alpha") + col.prop(brush, "paint_erase") + col.prop(brush, "paint_wetness", text="Wetness") + + col = split.column() + sub = col.column() + sub.active = (brush.paint_source != "PSYS"); + sub.prop(brush, "use_material") + if brush.use_material and brush.paint_source != "PSYS": + col.prop(brush, "material", text="") + col.prop(brush, "paint_alpha", text="Alpha Factor") else: - layout.label(text="-WIP-") + col.prop(brush, "paint_color", text="") + col.prop(brush, "paint_alpha", text="Alpha") class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel): - bl_label = "Dynamic Paint: Advanced" + bl_label = "Dynamic Paint Advanced" @classmethod def poll(cls, context): @@ -208,7 +177,7 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel): layout.prop(surface, "brush_group", text="") class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel): - bl_label = "Dynamic Paint: Output" + bl_label = "Dynamic Paint Output" bl_options = {'DEFAULT_CLOSED'} @classmethod @@ -299,7 +268,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel): layout.label(text=canvas.ui_info) class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, bpy.types.Panel): - bl_label = "Dynamic Paint: Initial Color" + bl_label = "Dynamic Paint Initial Color" bl_options = {'DEFAULT_CLOSED'} @classmethod @@ -332,7 +301,7 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, bpy.types.Panel): layout.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer: ") class PHYSICS_PT_dp_effects(PhysicButtonsPanel, bpy.types.Panel): - bl_label = "Dynamic Paint: Effects" + bl_label = "Dynamic Paint Effects" bl_options = {'DEFAULT_CLOSED'} @classmethod @@ -383,7 +352,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, bpy.types.Panel): class PHYSICS_PT_dp_cache(PhysicButtonsPanel, bpy.types.Panel): - bl_label = "Dynamic Paint: Cache" + bl_label = "Dynamic Paint Cache" bl_options = {'DEFAULT_CLOSED'} @classmethod @@ -401,9 +370,8 @@ class PHYSICS_PT_dp_cache(PhysicButtonsPanel, bpy.types.Panel): point_cache_ui(self, context, cache, (cache.is_baked is False), 'DYNAMIC_PAINT') -class PHYSICS_PT_dp_advanced_brush(PhysicButtonsPanel, bpy.types.Panel): - bl_label = "Dynamic Paint: Advanced" - bl_options = {'DEFAULT_CLOSED'} +class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Dynamic Paint Source" @classmethod def poll(cls, context): @@ -450,6 +418,61 @@ class PHYSICS_PT_dp_advanced_brush(PhysicButtonsPanel, bpy.types.Panel): col.separator() col.prop(brush, "prox_ramp_alpha", text="Only Use Alpha") col.template_color_ramp(brush, "paint_ramp", expand=True) + +class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Dynamic Paint Velocity" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.dynamic_paint + return md and (md.ui_type == "BRUSH") and (md.brush_settings) + + def draw(self, context): + layout = self.layout + + brush = context.dynamic_paint.brush_settings + ob = context.object + + col = layout.row().column() + col.label(text="Brush Velocity Settings:") + split = layout.split() + col = split.column() + col.prop(brush, "velocity_alpha") + col.prop(brush, "velocity_color") + col = split.column() + col.prop(brush, "velocity_depth") + sub = layout.row().column() + sub.active = (brush.velocity_alpha or brush.velocity_color or brush.velocity_depth) + sub.prop(brush, "max_velocity") + sub.template_color_ramp(brush, "velocity_ramp", expand=True) + layout.separator() + layout.label(text="Smudge:") + layout.prop(brush, "do_smudge") + layout.prop(brush, "smudge_strength") + +class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Dynamic Paint Wave" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.dynamic_paint + return md and (md.ui_type == "BRUSH") and (md.brush_settings) + + def draw(self, context): + layout = self.layout + + brush = context.dynamic_paint.brush_settings + ob = context.object + + layout.prop(brush, "wave_type") + if (brush.wave_type != "REFLECT"): + split = layout.split(percentage=0.5) + col = split.column() + col.prop(brush, "wave_factor") + col = split.column() + col.prop(brush, "wave_clamp") def register(): bpy.utils.register_module(__name__) diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index fe45c6580fe..d9cbed815fc 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -16,8 +16,6 @@ #include "DNA_dynamicpaint_types.h" -struct PaintEffectData; -struct PaintBakeData; struct bContext; struct wmOperator; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index fc2302f0fbe..0aa06e5fda4 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -20,17 +20,19 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_kdtree.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_dynamicpaint_types.h" #include "DNA_group_types.h" /*GroupObject*/ +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "DNA_userdef_types.h" /* to get temp file path */ +#include "DNA_texture_types.h" #include "BKE_animsys.h" #include "BKE_bvhutils.h" /* bvh tree */ @@ -45,6 +47,7 @@ #include "BKE_dynamicpaint.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_modifier.h" @@ -61,19 +64,10 @@ /* for image output */ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "BKE_image.h" -/* uv validate */ -#include "intern/MOD_util.h" - -/* to read object material color */ -#include "DNA_texture_types.h" -#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" +/* to read material/texture color */ #include "RE_render_ext.h" +#include "RE_shader_ext.h" #ifdef _OPENMP #include @@ -216,10 +210,8 @@ typedef struct PaintAdjData { */ static int printError(DynamicPaintCanvasSettings *canvas, char *string) { - if (strlen(string)>64) string[63] = '\0'; - /* Add error to canvas ui info label */ - sprintf(canvas->error, string); + BLI_snprintf(canvas->error, sizeof(canvas->error), string); /* Print console output */ printf("DynamicPaint bake failed: %s\n", canvas->error); @@ -924,7 +916,7 @@ void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd) /* * Creates a new surface and adds it to the list -* If scene is null, frame range of 1-250 +* If scene is null, frame range of 1-250 is used * A pointer to this surface is returned */ struct DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas, Scene *scene) @@ -1124,7 +1116,6 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn 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; @@ -2140,7 +2131,7 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) /* Check for validity */ if (!tface) return printError(canvas, "No UV data on canvas."); - if (surface->image_resolution < 16 || surface->image_resolution > 8096) return printError(canvas, "Invalid resolution."); + if (surface->image_resolution < 16 || surface->image_resolution > 8192) return printError(canvas, "Invalid resolution."); w = h = surface->image_resolution; @@ -2576,9 +2567,9 @@ void dynamicPaint_outputImage(DynamicPaintSurface *surface, char* filename, shor if (sData == NULL || sData->type_data == NULL) {printError(surface->canvas, "Image save failed: Invalid surface.");return;} - if (format == DPOUTPUT_JPEG) sprintf(output_file,"%s.jpg",filename); - else if (format == DPOUTPUT_OPENEXR) sprintf(output_file,"%s.exr",filename); - else sprintf(output_file,"%s.png",filename); + if (format == DPOUTPUT_JPEG) BLI_snprintf(output_file, sizeof(output_file),"%s.jpg",filename); + else if (format == DPOUTPUT_OPENEXR) BLI_snprintf(output_file, sizeof(output_file),"%s.exr",filename); + else BLI_snprintf(output_file, sizeof(output_file),"%s.png",filename); /* Validate output file path */ BLI_path_abs(output_file, G.main->name); @@ -2684,208 +2675,6 @@ typedef struct BrushMaterials { int tot; } BrushMaterials; -/* A modified part of shadeinput.c -> shade_input_set_uv() -* Used for sampling UV mapped texture color */ -static void textured_face_generate_uv(float *uv, float *normal, float *hit, float *v1, float *v2, float *v3) -{ - - float detsh, t00, t10, t01, t11, xn, yn, zn; - int axis1, axis2; - - /* find most stable axis to project */ - xn= fabs(normal[0]); - yn= fabs(normal[1]); - zn= fabs(normal[2]); - - if(zn>=xn && zn>=yn) { axis1= 0; axis2= 1; } - else if(yn>=xn && yn>=zn) { axis1= 0; axis2= 2; } - else { axis1= 1; axis2= 2; } - - /* compute u,v and derivatives */ - t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; - t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; - - detsh= 1.0f/(t00*t11-t10*t01); - t00*= detsh; t01*=detsh; - t10*=detsh; t11*=detsh; - - uv[0] = (hit[axis1]-v3[axis1])*t11-(hit[axis2]-v3[axis2])*t10; - uv[1] = (hit[axis2]-v3[axis2])*t00-(hit[axis1]-v3[axis1])*t01; - - /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */ - CLAMP(uv[0], -2.0f, 1.0f); - CLAMP(uv[1], -2.0f, 1.0f); -} - -/* a modified part of shadeinput.c -> shade_input_set_shade_texco() -* Used for sampling UV mapped texture color */ -static void textured_face_get_uv(float *uv_co, float *normal, float *uv, int faceIndex, short quad, MTFace *tface) -{ - float *uv1, *uv2, *uv3; - float l; - - l= 1.0f+uv[0]+uv[1]; - - uv1= tface[faceIndex].uv[0]; - uv2= (quad) ? tface[faceIndex].uv[2] : tface[faceIndex].uv[1]; - uv3= (quad) ? tface[faceIndex].uv[3] : tface[faceIndex].uv[2]; - - uv_co[0]= -1.0f + 2.0f*(l*uv3[0]-uv[0]*uv1[0]-uv[1]*uv2[0]); - uv_co[1]= -1.0f + 2.0f*(l*uv3[1]-uv[0]*uv1[1]-uv[1]*uv2[1]); - uv_co[2]= 0.0f; /* texture.c assumes there are 3 coords */ -} - -/* -* 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) -*/ -static void dynamicPaint_copyUpdatedMaterial(Material *orig_mat, Scene *scene, Material **mat_target) -{ - MTex *mtex = NULL; - MTex *orig_mtex = NULL; - Tex *tex = NULL; - Material *mat; - int tex_nr; - - if (orig_mat == NULL) return; - - /* update material anims */ - BKE_animsys_evaluate_animdata(scene, &orig_mat->id, orig_mat->adt, BKE_curframe(scene), ADT_RECALC_ANIM); - - /* copy material */ - mat = MEM_callocN(sizeof(Material), "Temp Brush Material"); - memcpy(mat, orig_mat, sizeof(Material)); - - for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { - orig_mtex = mat->mtex[tex_nr]; - - mtex = MEM_callocN(sizeof(MTex), "Temp MTex Copy"); - memcpy(mtex, orig_mtex, sizeof(MTex)); - mat->mtex[tex_nr] = mtex; - tex= mtex->tex; - - /* 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); - - /* 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; - } - /* strip all mapto flags except color and alpha */ - mtex->mapto = (orig_mtex->mapto & MAP_COL) | (orig_mtex->mapto & MAP_ALPHA); - } - 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; - } - /* 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); - } - } - - /* update texture anims */ - BKE_animsys_evaluate_animdata(scene, &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); - } - 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); - } - } - - /* 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; -} - -/* free all duplicate data allocated by dynamicPaint_copyUpdatedMaterial() */ -static void dynamicPaint_freeMaterialCopy(Material *mat) -{ - int tex_nr; - if (!mat) - return; - - /* free mtexes */ - for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { - 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); - } - 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); - } - MEM_freeN(mtex); - } - } - - MEM_freeN(mat); -} - /* Initialize materials for brush object: * Calculates inverse matrices for linked objects, updates * volume caches etc. */ @@ -2901,14 +2690,16 @@ static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, int i, tot=(*give_totcolp(brushOb)); /* allocate material pointer array */ - bMats->ob_mats = MEM_callocN(sizeof(Material*)*(tot), "BrushMaterials"); - for (i=0; iob_mats[i]); + if (tot) { + bMats->ob_mats = MEM_callocN(sizeof(Material*)*(tot), "BrushMaterials"); + for (i=0; iob_mats[i] = RE_init_sample_material(give_current_material(brushOb,(i+1)), scene); + } } bMats->tot = tot; } else { - dynamicPaint_copyUpdatedMaterial(ui_mat, scene, &bMats->mat); + bMats->mat = RE_init_sample_material(ui_mat, scene); } } @@ -2919,38 +2710,22 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) if (bMats->ob_mats) { int i; for (i=0; itot; i++) { - dynamicPaint_freeMaterialCopy(bMats->ob_mats[i]); + RE_free_sample_material(bMats->ob_mats[i]); } MEM_freeN(bMats->ob_mats); } - else { - dynamicPaint_freeMaterialCopy(bMats->mat); + else if (bMats->mat) { + RE_free_sample_material(bMats->mat); } } /* * Get material diffuse color and alpha (including linked textures) in given coordinates -* -* 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 */ -void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, float surfaceCoord[3], float xyz[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) +void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) { - - MFace *mface; - int v1, v2, v3; - MVert *mvert; - float uv[3], normal[3]; - - ShadeInput shi = {0}; Material *mat = bMats->mat; - - /* Get face data */ - mvert = orcoDm->getVertArray(orcoDm); - mface = orcoDm->getFaceArray(orcoDm); + MFace *mface = orcoDm->getFaceArray(orcoDm); /* If no material defined, use the one assigned to the mesh face */ if (mat == NULL) { @@ -2963,89 +2738,7 @@ void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *al else return; } - 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= 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 (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); - } + RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb); } @@ -3857,32 +3550,18 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, ParticleSys return 1; } + /* begin thread safe malloc */ + BLI_begin_threaded_malloc(); + /* only continue if particle bb is close enough to canvas bb */ if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) { int c_index; int total_cells = grid->dim[0]*grid->dim[1]*grid->dim[2]; - int num_of_threads = 1; - - /* nearest particles search array for each thread */ - KDTreeNearest **nearest_th = NULL; - int nearest_limit = particlesAdded/10; - if (nearest_limit<10) nearest_limit = 10; /* balance tree */ BLI_kdtree_balance(tree); -#ifdef _OPENMP - num_of_threads = omp_get_max_threads(); -#endif - - nearest_th = MEM_callocN((num_of_threads)*sizeof(KDTreeNearest), "nearest_for_threads"); - - if (brush->flags & MOD_DPAINT_PART_RAD) - for (c_index=0; c_indexrealCoord[bData->s_pos[index]].v, NULL, nearest, nearest_limit); + particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest); /* Find particle that produces highest influence */ for(n=0; nflags & MOD_DPAINT_PART_RAD) - for (c_index=0; c_index *totfoundstack) - return 0; - - to = ptn + found; - - to->index = index; - to->dist = sqrt(dist); - copy_v3_v3(to->co, co); - return 1; -} -int BLI_kdtree_range_search_thread_safe(KDTree *tree, float range, float *co, float *nor, KDTreeNearest *nearest, int limit) -{ - KDTreeNode *root, *node= NULL; - KDTreeNode **stack, *defaultstack[500]; - KDTreeNearest *foundstack=nearest; - float range2 = range*range, dist2; - int totstack, cur=0, found=0; - - if(!tree || !tree->root) - return 0; - - stack= defaultstack; - totstack= 500; - - root= tree->root; - - if(co[root->d] + range < root->co[root->d]) { - if(root->left) - stack[cur++]=root->left; - } - else if(co[root->d] - range > root->co[root->d]) { - if(root->right) - stack[cur++]=root->right; - } - else { - dist2 = squared_distance(root->co, co, root->nor, nor); - if(dist2 <= range2) - add_in_range_thread_safe(foundstack, found++, &limit, root->index, dist2, root->co); - - if(root->left) - stack[cur++]=root->left; - if(root->right) - stack[cur++]=root->right; - } - - while(cur--) { - node=stack[cur]; - - if(co[node->d] + range < node->co[node->d]) { - if(node->left) - stack[cur++]=node->left; - } - else if(co[node->d] - range > node->co[node->d]) { - if(node->right) - stack[cur++]=node->right; - } - else { - dist2 = squared_distance(node->co, co, node->nor, nor); - if(dist2 <= range2) - if (!add_in_range_thread_safe(foundstack, found++, &limit, node->index, dist2, node->co)) - break; - - if(node->left) - stack[cur++]=node->left; - if(node->right) - stack[cur++]=node->right; - } - - /* abort if running out of stack */ - if(cur+3 > totstack) - break; - } - - if(stack != defaultstack) - MEM_freeN(stack); - - if(found) - qsort(foundstack, found, sizeof(KDTreeNearest), range_compare); - return found; } \ No newline at end of file diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 097ad2bcd74..b4923169179 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -660,3 +660,17 @@ void BLI_thread_queue_nowait(ThreadQueue *queue) pthread_mutex_unlock(&queue->mutex); } +void BLI_begin_threaded_malloc(void) +{ + if(thread_levels == 0) { + MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + } + thread_levels++; +} + +void BLI_end_threaded_malloc(void) +{ + thread_levels--; + if(thread_levels==0) + MEM_set_lock_callback(NULL, NULL); +} \ No newline at end of file diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a3b60b18c39..70d6ffd0936 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4129,14 +4129,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) } if(pmd->brush) { - if (pmd->brush) { - pmd->brush = newdataadr(fd, pmd->brush); - pmd->brush->pmd = pmd; - pmd->brush->psys = newdataadr(fd, pmd->brush->psys); - pmd->brush->paint_ramp = newdataadr(fd, pmd->brush->paint_ramp); - pmd->brush->vel_ramp = newdataadr(fd, pmd->brush->vel_ramp); - pmd->brush->dm = NULL; - } + pmd->brush = newdataadr(fd, pmd->brush); + pmd->brush->pmd = pmd; + pmd->brush->psys = newdataadr(fd, pmd->brush->psys); + pmd->brush->paint_ramp = newdataadr(fd, pmd->brush->paint_ramp); + pmd->brush->vel_ramp = newdataadr(fd, pmd->brush->vel_ramp); + pmd->brush->dm = NULL; } } else if (md->type==eModifierType_Collision) { diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index a868cb55ca5..9a7e5a564c4 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -23,6 +23,7 @@ #include #include "BLI_blenlib.h" +#include "BLI_string.h" #include "DNA_dynamicpaint_types.h" #include "DNA_modifier_types.h" @@ -333,24 +334,24 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf /* color map */ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { if (surface->flags & MOD_DPAINT_OUT1) { - sprintf(filename, "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame); + BLI_snprintf(filename, sizeof(filename), "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame); dynamicPaint_outputImage(surface, filename, format, DPOUTPUT_PAINT); } if (surface->flags & MOD_DPAINT_OUT2) { - sprintf(filename, "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name2, pad, (int)frame); + BLI_snprintf(filename, sizeof(filename), "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name2, pad, (int)frame); dynamicPaint_outputImage(surface, filename, format, DPOUTPUT_WET); } } /* displacement map */ else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { - sprintf(filename, "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame); + BLI_snprintf(filename, sizeof(filename), "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame); dynamicPaint_outputImage(surface, filename, format, DPOUTPUT_DISPLACE); } /* waves */ else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { - sprintf(filename, "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame); + BLI_snprintf(filename, sizeof(filename), "%s%s%s%s%i", surface->image_output_path, dir_slash, surface->output_name, pad, (int)frame); dynamicPaint_outputImage(surface, filename, format, DPOUTPUT_WAVES); } } @@ -365,6 +366,7 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) { DynamicPaintModifierData *pmd = NULL; + DynamicPaintCanvasSettings *canvas; Object *ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data; int status = 0; double timer = PIL_check_seconds_timer(); @@ -380,15 +382,16 @@ int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) } /* Make sure we're dealing with a canvas */ - if (!pmd->canvas) { + canvas = pmd->canvas; + if (!canvas) { BKE_report(op->reports, RPT_ERROR, "Bake Failed: Invalid Canvas."); return 0; } - surface = get_activeSurface(pmd->canvas); + surface = get_activeSurface(canvas); /* Set state to baking and init surface */ - pmd->canvas->error[0] = '\0'; - pmd->canvas->flags |= MOD_DPAINT_BAKING; + canvas->error[0] = '\0'; + canvas->flags |= MOD_DPAINT_BAKING; G.afbreek= 0; /* reset blender_test_break*/ /* Bake Dynamic Paint */ @@ -405,37 +408,20 @@ int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) /* Format time string */ char timestr[30]; double time = PIL_check_seconds_timer() - timer; - int tmp_val; - timestr[0] = '\0'; - - /* days (just in case someone actually has a very slow pc) */ - tmp_val = (int)floor(time / 86400.0f); - if (tmp_val > 0) sprintf(timestr, "%i Day(s) - ", tmp_val); - /* hours */ - time -= 86400.0f * tmp_val; - tmp_val = (int)floor(time / 3600.0f); - if (tmp_val > 0) sprintf(timestr, "%s%i h ", timestr, tmp_val); - /* minutes */ - time -= 3600.0f * tmp_val; - tmp_val = (int)floor(time / 60.0f); - if (tmp_val > 0) sprintf(timestr, "%s%i min ", timestr, tmp_val); - /* seconds */ - time -= 60.0f * tmp_val; - tmp_val = (int)ceil(time); - sprintf(timestr, "%s%i s", timestr, tmp_val); + BLI_timestr(time, timestr); /* Show bake info */ - sprintf(pmd->canvas->ui_info, "Bake Complete! (Time: %s)", timestr); - printf("%s\n", pmd->canvas->ui_info); + BLI_snprintf(canvas->ui_info, sizeof(canvas->ui_info), "Bake Complete! (%s)", timestr); + printf("%s\n", canvas->ui_info); } else { if (strlen(pmd->canvas->error)) { /* If an error occured */ - sprintf(pmd->canvas->ui_info, "Bake Failed: %s", pmd->canvas->error); - BKE_report(op->reports, RPT_ERROR, pmd->canvas->ui_info); + BLI_snprintf(canvas->ui_info, sizeof(canvas->ui_info), "Bake Failed: %s", pmd->canvas->error); + BKE_report(op->reports, RPT_ERROR, canvas->ui_info); } else { /* User cancelled the bake */ sprintf(pmd->canvas->ui_info, "Baking Cancelled!"); - BKE_report(op->reports, RPT_WARNING, pmd->canvas->ui_info); + BKE_report(op->reports, RPT_WARNING, canvas->ui_info); } /* Print failed bake to console */ diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index 5fe9b657bde..aebd8d0f07a 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -198,9 +198,9 @@ typedef struct DynamicPaintBrushSettings { struct ColorBand *vel_ramp; /* Velocity paint ramp */ short proximity_falloff; - short brush_settings_context; /* ui settings display */ short wave_type; short ray_dir; + short pad; float wave_factor, wave_clamp; float max_velocity, smudge_strength; diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index 730b4047798..c3dcc65c3d4 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -710,22 +710,11 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) {MOD_DPAINT_RAY_ZPLUS, "ZPLUS", 0, "Z-Axis", ""}, {0, NULL, 0, NULL, NULL}}; - static EnumPropertyItem buttons_dynamicpaint_settings_menu[] = { - {0, "GENERAL", ICON_MOD_DYNAMICPAINT, "", "Show general settings"}, - {1, "VELOCITY", ICON_CURVE_PATH, "", "Show velocity related settings"}, - {2, "WAVE", ICON_MOD_WAVE, "", "Show wave related settings"}, - {0, NULL, 0, NULL, NULL}}; - srna = RNA_def_struct(brna, "DynamicPaintBrushSettings", NULL); RNA_def_struct_ui_text(srna, "Brush Settings", "Brush settings"); RNA_def_struct_sdna(srna, "DynamicPaintBrushSettings"); RNA_def_struct_path_func(srna, "rna_DynamicPaintBrushSettings_path"); - prop= RNA_def_property(srna, "brush_settings_context", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, buttons_dynamicpaint_settings_menu); - RNA_def_property_enum_sdna(prop, NULL, "brush_settings_context"); - RNA_def_property_ui_text(prop, "Brush Context", ""); - /* * Paint */ @@ -767,7 +756,7 @@ 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_items(prop, prop_dynamicpaint_brush_wave_type); - RNA_def_property_ui_text(prop, "Paint Type", ""); + RNA_def_property_ui_text(prop, "Brush Effect", ""); prop= RNA_def_property(srna, "wave_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, -2.0, 2.0); diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 0c40aea3bd9..707de14cab5 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -12,7 +12,7 @@ * */ -#include "stddef.h" +#include #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -21,8 +21,8 @@ #include "MEM_guardedalloc.h" #include "BKE_cdderivedmesh.h" -#include "BKE_modifier.h" #include "BKE_dynamicpaint.h" +#include "BKE_modifier.h" #include "depsgraph_private.h" @@ -54,12 +54,34 @@ static void freeData(ModifierData *md) static CustomDataMask requiredDataMask(Object *ob, ModifierData *md) { + DynamicPaintModifierData *pmd = (DynamicPaintModifierData*)md; CustomDataMask dataMask = 0; - dataMask |= (1 << CD_MTFACE); - dataMask |= (1 << CD_MCOL); - dataMask |= (1 << CD_MDEFORMVERT); + if (pmd->canvas) { + DynamicPaintSurface *surface = pmd->canvas->surfaces.first; + for(; surface; surface=surface->next) { + /* tface */ + if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ || + surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) { + dataMask |= (1 << CD_MTFACE); + } + /* mcol */ + if (surface->type == MOD_DPAINT_SURFACE_T_PAINT || + surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) { + dataMask |= (1 << CD_MCOL); + } + /* CD_MDEFORMVERT */ + if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { + dataMask |= (1 << CD_MDEFORMVERT); + } + } + } + if (pmd->brush) { + if (pmd->brush->mat) { + dataMask |= (1 << CD_MTFACE); + } + } return dataMask; } diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index e98f481b162..deae2ed9b66 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -50,6 +50,7 @@ struct RNode; struct Render; struct MTex; struct ImBuf; +struct DerivedMesh; // RADIO REMOVED, Maybe this will be useful later //void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re); @@ -65,5 +66,11 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result); void antialias_tagbuf(int xsize, int ysize, char *rectmove); +/* dynamicpaint.c */ +struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene); +void RE_free_sample_material(struct Material *mat); +void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], + int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob); + #endif /* RE_RENDER_EXT_H */ diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index 294c7b53766..9815cfdff7d 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 col_r[4]); void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float hor[3], float zen[3], float *blend, int skyflag, short thread); void do_material_tex(struct ShadeInput *shi); void do_lamp_tex(LampRen *la, const float lavec[3], struct ShadeInput *shi, float col_r[3], int effect); -void do_volume_tex(struct ShadeInput *shi, const float *xyz, int mapto_flag, float *col, float *val, struct Render *re); +void do_volume_tex(struct ShadeInput *shi, const float xyz[3], int mapto_flag, float col[3], 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 2d9ce24b46c..a050fd8622b 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -40,6 +40,7 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_texture_types.h" #include "DNA_object_types.h" #include "DNA_lamp_types.h" @@ -57,10 +58,12 @@ #include "BKE_node.h" #include "BKE_plugin_types.h" - +#include "BKE_animsys.h" +#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_scene.h" #include "BKE_library.h" #include "BKE_image.h" @@ -3474,4 +3477,257 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) shi->vcol[3]*= texr.ta; } +/* A modified part of shadeinput.c -> shade_input_set_uv() +* Used for sampling UV mapped texture color */ +static void textured_face_generate_uv(float *uv, float *normal, float *hit, float *v1, float *v2, float *v3) +{ + + float detsh, t00, t10, t01, t11, xn, yn, zn; + int axis1, axis2; + + /* find most stable axis to project */ + xn= fabs(normal[0]); + yn= fabs(normal[1]); + zn= fabs(normal[2]); + + if(zn>=xn && zn>=yn) { axis1= 0; axis2= 1; } + else if(yn>=xn && yn>=zn) { axis1= 0; axis2= 2; } + else { axis1= 1; axis2= 2; } + + /* compute u,v and derivatives */ + t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; + t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; + + detsh= 1.0f/(t00*t11-t10*t01); + t00*= detsh; t01*=detsh; + t10*=detsh; t11*=detsh; + + uv[0] = (hit[axis1]-v3[axis1])*t11-(hit[axis2]-v3[axis2])*t10; + uv[1] = (hit[axis2]-v3[axis2])*t00-(hit[axis1]-v3[axis1])*t01; + + /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */ + CLAMP(uv[0], -2.0f, 1.0f); + CLAMP(uv[1], -2.0f, 1.0f); +} + +/* Generate an updated copy of material to use for color sampling. */ +Material *RE_init_sample_material(Material *orig_mat, Scene *scene) +{ + Tex *tex = NULL; + Material *mat; + int tex_nr; + + if (!orig_mat) return NULL; + + /* copy material */ + mat = localize_material(orig_mat); + + /* update material anims */ + BKE_animsys_evaluate_animdata(scene, &mat->id, mat->adt, BKE_curframe(scene), ADT_RECALC_ANIM); + + /* strip material copy from unsupported flags */ + for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { + MTex *mtex = mat->mtex[tex_nr]; + + /* only keep compatible texflags */ + mtex->texflag = mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE | MTEX_ALPHAMIX); + + /* depending of material type, strip non-compatible mapping modes */ + if (mat->material_type == MA_TYPE_SURFACE) { + if (!ELEM4(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) { + /* ignore this texture */ + mtex->texco = 0; + continue; + } + /* strip all mapto flags except color and alpha */ + mtex->mapto = (mtex->mapto & MAP_COL) | (mtex->mapto & MAP_ALPHA); + } + else if (mat->material_type == MA_TYPE_VOLUME) { + if (!ELEM3(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) { + /* ignore */ + mtex->texco = 0; + continue; + } + /* strip all mapto flags except color and alpha */ + mtex->mapto = mtex->mapto & (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | 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); + } + } + + /* copy texture */ + tex= mtex->tex = localize_texture(mtex->tex); + + /* update texture anims */ + BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_curframe(scene), ADT_RECALC_ANIM); + + /* update texture cache if required */ + if(tex->type==TEX_VOXELDATA) { + cache_voxeldata(tex, (int)scene->r.cfra); + } + if(tex->type==TEX_POINTDENSITY) { + /* set dummy values for render and do cache */ + 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 = 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); + } + } + } + return mat; +} + +/* free all duplicate data allocated by RE_init_sample_material() */ +void RE_free_sample_material(Material *mat) +{ + int tex_nr; + + /* free textures */ + for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { + MTex *mtex= mat->mtex[tex_nr]; + free_texture(mtex->tex); + } + } + + free_material(mat); +} + + + +/* +* Get material diffuse color and alpha (including linked textures) in given coordinates +* +* color,alpha : input/output color values +* volume_co : sample coordinate in global space. used by volumetric materials +* surface_co : sample surface coordinate in global space. used by "surface" materials +* face_index : surface face index +* hit_quad : whether point is on second "half" of a quad +* orcoDm : orco state derived mesh +*/ +void RE_sample_material_color(Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], int face_index, short hit_quad, DerivedMesh *orcoDm, Object *ob) +{ + MFace *mface; + int v1, v2, v3; + MVert *mvert; + float uv[3], normal[3]; + ShadeInput shi = {0}; + + /* Get face data */ + mvert = orcoDm->getVertArray(orcoDm); + mface = orcoDm->getFaceArray(orcoDm); + + if (!mvert || !mface || !mat) return; + v1=mface[face_index].v1, v2=mface[face_index].v2, v3=mface[face_index].v3; + if (hit_quad) {v2=mface[face_index].v3; v3=mface[face_index].v4;} + normal_tri_v3( normal, mvert[v1].co, mvert[v2].co, mvert[v3].co); + + /* generate shadeinput with data required */ + shi.mat = mat; + + /* fill shadeinput data depending on material type */ + if (mat->material_type == MA_TYPE_SURFACE) { + /* global coordinates */ + VECCOPY(shi.gl, surface_co); + /* object space coordinates */ + VECCOPY(shi.co, surface_co); + mul_m4_v3(ob->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 */ + 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= 0) { + float *uv1, *uv2, *uv3; + float l; + 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 */ + l= 1.0f+uv[0]+uv[1]; + + uv1= tface[face_index].uv[0]; + uv2= (hit_quad) ? tface[face_index].uv[2] : tface[face_index].uv[1]; + uv3= (hit_quad) ? tface[face_index].uv[3] : tface[face_index].uv[2]; + + shi.uv[i].uv[0]= -1.0f + 2.0f*(l*uv3[0]-uv[0]*uv1[0]-uv[1]*uv2[0]); + shi.uv[i].uv[1]= -1.0f + 2.0f*(l*uv3[1]-uv[0]*uv1[1]-uv[1]*uv2[1]); + shi.uv[i].uv[2]= 0.0f; /* texture.c assumes there are 3 coords */ + } + } + /* 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 (mat->material_type == MA_TYPE_VOLUME) { + ObjectInstanceRen obi = {0}; + Render re = {0}; + obi.ob = ob; + 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, volume_co, (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY), + color, alpha, &re); + } +} + /* eof */ diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index f3e5fc63bda..e20c6ee174c 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -1103,6 +1103,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) { ShadeInputCol *scol= &shi->col[i]; char *cp1, *cp2, *cp3; + float a[3]; shi->totcol++; scol->name= name; @@ -1111,18 +1112,21 @@ void shade_input_set_shade_texco(ShadeInput *shi) cp2= (char *)(mcol+j2); cp3= (char *)(mcol+j3); - /* alpha value */ - scol->col[3]= (l*((float)cp3[0]) - u*((float)cp1[0]) - v*((float)cp2[0]))/255.0f; - - /* try to prevent invalid color sampling of zero alpha points */ - if (!cp1[0]) cp1 = cp2; if (!cp1[0]) cp1 = cp3; - if (!cp2[0]) cp2 = cp1; if (!cp2[0]) cp2 = cp3; - if (!cp3[0]) cp3 = cp1; if (!cp3[0]) cp3 = cp2; + /* alpha values */ + a[0] = ((float)cp1[0])/255.f; + a[1] = ((float)cp2[0])/255.f; + a[2] = ((float)cp3[0])/255.f; + scol->col[3]= l*a[2] - u*a[0] - v*a[1]; - /* sample color value */ - scol->col[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f; - scol->col[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f; - scol->col[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f; + /* sample premultiplied color value */ + scol->col[0]= (l*((float)cp3[3])*a[2] - u*((float)cp1[3])*a[0] - v*((float)cp2[3])*a[1])/255.f; + scol->col[1]= (l*((float)cp3[2])*a[2] - u*((float)cp1[2])*a[0] - v*((float)cp2[2])*a[1])/255.f; + scol->col[2]= (l*((float)cp3[1])*a[2] - u*((float)cp1[1])*a[0] - v*((float)cp2[1])*a[1])/255.f; + + /* if not zero alpha, restore non-multiplied color */ + if (scol->col[3]) { + mul_v3_fl(scol->col, 1.0f/scol->col[3]); + } } if(shi->totcol) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 0056b073c81..eece830f5b9 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -874,10 +874,10 @@ void shade_color(ShadeInput *shi, ShadeResult *shr) shi->alpha= shi->vcol[3]; } else if(ma->mode & (MA_VERTEXCOLP)) { - float inv_alpha = 1.0f - shi->vcol[3]; - shi->r= shi->r*inv_alpha + shi->vcol[0]*shi->vcol[3]; - shi->g= shi->g*inv_alpha + shi->vcol[1]*shi->vcol[3]; - shi->b= shi->b*inv_alpha + shi->vcol[2]*shi->vcol[3]; + float neg_alpha = 1.0f - shi->vcol[3]; + shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3]; + shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3]; + shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3]; } if(ma->texco) @@ -1671,10 +1671,10 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shi->alpha= shi->vcol[3]; } else if(ma->mode & (MA_VERTEXCOLP)) { - float inv_alpha = 1.0f - shi->vcol[3]; - shi->r= shi->r*inv_alpha + shi->vcol[0]*shi->vcol[3]; - shi->g= shi->g*inv_alpha + shi->vcol[1]*shi->vcol[3]; - shi->b= shi->b*inv_alpha + shi->vcol[2]*shi->vcol[3]; + float neg_alpha = 1.0f - shi->vcol[3]; + shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3]; + shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3]; + shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3]; } if(ma->texco){ do_material_tex(shi); diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index e4e361d6a68..e8a27607e11 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -123,8 +123,12 @@ int multitex_thread(struct Tex *tex, float *texvec, float *dxt, float *dyt, int int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres){return 0;} 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 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) {} + +/* material_ext.c */ +struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene) {return (struct Material *)NULL;} +void RE_free_sample_material(struct Material *mat) {} +void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], + int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob) {} /* nodes */ struct RenderResult *RE_GetResult(struct Render *re){return (struct RenderResult *) NULL;} @@ -149,8 +153,6 @@ struct Render *RE_NewRender(const char *name){return (struct Render*) NULL;} void RE_SwapResult(struct Render *re, struct RenderResult **rr){} void RE_BlenderFrame(struct Render *re, struct Scene *scene, int frame){} int RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, int imtype, float layout[12]) { return 0; } -void cache_voxeldata(struct Tex *tex, int scene_frame){} -void cache_pointdensity(struct Render *re, struct Tex *tex){} /* rna */ float *give_cursor(struct Scene *scene, struct View3D *v3d){return (float *) NULL;}