diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2018-02-27 14:17:23 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2018-02-27 14:17:23 +0300 |
commit | f9b2e4a16b1beb62afdcb6e910d7d4bc39950b20 (patch) | |
tree | 9b117c15199402a141d1eea61ff65662d2c4ecd5 /source/blender | |
parent | fdd7b788ace22d5bdf4fc48fcc6ea5b90fd2a615 (diff) | |
parent | 6aadd61bd892d3908ed815171553a3c52144ec6c (diff) |
Merge branch 'master' into soc-2017-normal-tools
Diffstat (limited to 'source/blender')
45 files changed, 982 insertions, 420 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index c99da724794..6cd93e19e95 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -28,7 +28,7 @@ * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 279 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 8a736c9952d..05ba3ac1df4 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -792,6 +792,7 @@ struct ShadeResult; #define SH_NODE_BEVEL 197 #define SH_NODE_DISPLACEMENT 198 #define SH_NODE_VECTOR_DISPLACEMENT 199 +#define SH_NODE_VOLUME_PRINCIPLED 200 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 00f5f0f84b6..5d4b1ae8170 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3616,6 +3616,7 @@ static void registerShaderNodes(void) register_node_type_sh_holdout(); register_node_type_sh_volume_absorption(); register_node_type_sh_volume_scatter(); + register_node_type_sh_volume_principled(); register_node_type_sh_subsurface_scattering(); register_node_type_sh_mix_shader(); register_node_type_sh_add_shader(); diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 81a5874ef4c..0561af8507d 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -1104,7 +1104,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti /* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part * distribution (see T47983 and its two example files). It allows us to consider pos as * 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not), - * and avoid stumbling over float imprecisions in element_sum. + * and avoid stumbling over float impression in element_sum. * Note: moved face and volume distribution to this as well (instead of starting at zero), * for the same reasons, see T52682. */ pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index dc1c0da4401..5b36b0f9f84 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -972,20 +972,20 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw); - wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL); + wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, sds->clipping, NULL); clip_grid = wt_density_grid; if (fluid_fields & SM_ACTIVE_FIRE) { - OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid); - OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid); - OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid); + OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid); + OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid); + OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid); } if (fluid_fields & SM_ACTIVE_COLORS) { - OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid); + OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, sds->clipping, wt_density_grid); } - OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid); + OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, sds->clipping, wt_density_grid); } if (sds->fluid) { @@ -999,33 +999,33 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx); OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt); - const char *name = (!sds->wt) ? "density" : "density low"; - density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL); + const char *name = (!sds->wt) ? "density" : "density_low"; + density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, sds->clipping, NULL); clip_grid = sds->wt ? clip_grid : density_grid; - OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL); + OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, sds->clipping, NULL); if (fluid_fields & SM_ACTIVE_HEAT) { - OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid); - OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid); + OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, sds->clipping, clip_grid); + OpenVDB_export_grid_fl(writer, "heat_old", heatold, sds->res, sds->fluidmat, sds->clipping, clip_grid); } if (fluid_fields & SM_ACTIVE_FIRE) { - name = (!sds->wt) ? "flame" : "flame low"; - OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid); - name = (!sds->wt) ? "fuel" : "fuel low"; - OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid); - name = (!sds->wt) ? "react" : "react low"; - OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid); + name = (!sds->wt) ? "flame" : "flame_low"; + OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, sds->clipping, density_grid); + name = (!sds->wt) ? "fuel" : "fuel_low"; + OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, sds->clipping, density_grid); + name = (!sds->wt) ? "react" : "react_low"; + OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, sds->clipping, density_grid); } if (fluid_fields & SM_ACTIVE_COLORS) { - name = (!sds->wt) ? "color" : "color low"; - OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid); + name = (!sds->wt) ? "color" : "color_low"; + OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, sds->clipping, density_grid); } - OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid); - OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL); + OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, sds->clipping, clip_grid); + OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, sds->clipping, NULL); } return 1; @@ -1104,25 +1104,25 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_ OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res); - const char *name = (!sds->wt) ? "density" : "density low"; + const char *name = (!sds->wt) ? "density" : "density_low"; OpenVDB_import_grid_fl(reader, name, &dens, sds->res); if (cache_fields & SM_ACTIVE_HEAT) { OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res); - OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res); + OpenVDB_import_grid_fl(reader, "heat_old", &heatold, sds->res); } if (cache_fields & SM_ACTIVE_FIRE) { - name = (!sds->wt) ? "flame" : "flame low"; + name = (!sds->wt) ? "flame" : "flame_low"; OpenVDB_import_grid_fl(reader, name, &flame, sds->res); - name = (!sds->wt) ? "fuel" : "fuel low"; + name = (!sds->wt) ? "fuel" : "fuel_low"; OpenVDB_import_grid_fl(reader, name, &fuel, sds->res); - name = (!sds->wt) ? "react" : "react low"; + name = (!sds->wt) ? "react" : "react_low"; OpenVDB_import_grid_fl(reader, name, &react, sds->res); } if (cache_fields & SM_ACTIVE_COLORS) { - name = (!sds->wt) ? "color" : "color low"; + name = (!sds->wt) ? "color" : "color_low"; OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res); } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 3adba9fbce8..bf473603c0e 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -523,8 +523,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->burning_rate = 0.75f; smd->domain->flame_smoke = 1.0f; smd->domain->flame_vorticity = 0.5f; - smd->domain->flame_ignition = 1.25f; - smd->domain->flame_max_temp = 1.75f; + smd->domain->flame_ignition = 1.5f; + smd->domain->flame_max_temp = 3.0f; /* color */ smd->domain->flame_smoke_color[0] = 0.7f; smd->domain->flame_smoke_color[1] = 0.7f; @@ -551,6 +551,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->coba = NULL; smd->domain->coba_field = FLUID_FIELD_DENSITY; + + smd->domain->clipping = 1e-3f; } else if (smd->type & MOD_SMOKE_TYPE_FLOW) { diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index dd7def16ca8..106dd125575 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -189,7 +189,7 @@ void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask, options->image1_mask = NULL; } -/* Peform tracking from a reference_marker to destination_ibuf. +/* Perform tracking from a reference_marker to destination_ibuf. * Uses marker as an initial position guess. * * Returns truth if tracker returned success, puts result diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index c08329ef34f..f69b35ce5a9 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -185,7 +185,7 @@ size_t BLI_file_size(const char *path) } /** - * Returns the st_mode from statting the specified path name, or 0 if it couldn't be statted + * Returns the st_mode from stat-ing the specified path name, or 0 if stat fails * (most likely doesn't exist or no access). */ int BLI_exists(const char *name) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index d27c1ce16d3..f1c40aae399 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1735,6 +1735,24 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } + if (!MAIN_VERSION_ATLEAST(main, 279, 3)) { + if (!DNA_struct_elem_find(fd->filesdna, "SmokeDomainSettings", "float", "clipping")) { + Object *ob; + ModifierData *md; + + for (ob = main->object.first; ob; ob = ob->id.next) { + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if (smd->domain) { + smd->domain->clipping = 1e-3f; + } + } + } + } + } + } + { /* Fix for invalid state of screen due to bug in older versions. */ for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) { diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index bd5cb05a1fa..3eefe84b214 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -49,40 +49,270 @@ bool AnimationExporter::exportAnimations(Scene *sce) return has_animations; } -// called for each exported object +bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count) +{ + for (int i = 0; i < values.size(); i += channel_count) { + for (int j = 0; j < channel_count; j++) { + if (!bc_in_range(values[j], values[i+j], 0.000001)) + return false; + } + } + return true; +} +/* + * This function creates a complete LINEAR Collada <Animation> Entry with all needed + * <source>, <sampler>, and <channel> entries. + * This is is used for creating sampled Transformation Animations for either: + * + * 1-axis animation: + * times contains the time points in seconds from within the timeline + * values contains the data (list of single floats) + * channel_count = 1 + * axis_name = ['X' | 'Y' | 'Z'] + * is_rot indicates if the animation is a rotation + * + * 3-axis animation: + * times contains the time points in seconds from within the timeline + * values contains the data (list of floats where each 3 entries are one vector) + * channel_count = 3 + * axis_name = "" (actually not used) + * is_rot = false (see xxx below) + * + * xxx: I tried to create a 3 axis rotation animation + * like for translation or scale. But i could not + * figure out how to setup the channel for this case. + * So for now rotations are exported as 3 separate 1-axis collada animations + * See export_sampled_animation() further down. + */ +void AnimationExporter::create_sampled_animation(int channel_count, + std::vector<float> ×, + std::vector<float> &values, + std::string ob_name, + std::string label, + std::string axis_name, + bool is_rot) +{ + char anim_id[200]; + + if (is_flat_line(values, channel_count)) + return; + + BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str()); + + openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); + + /* create input source */ + std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, ""); + + /* create output source */ + std::string output_id; + if (channel_count == 1) + output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str()); + else if (channel_count == 3) + output_id = create_xyz_source(&values[0], times.size(), anim_id); + else if (channel_count == 16) + output_id = create_4x4_source(times, values, anim_id); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); + std::string empty; + sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); + + /* TODO create in/out tangents source (LINEAR) */ + std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, ""); + + /* Create Sampler */ + sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + addSampler(sampler); + + /* Create channel */ + std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : ""); + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + +} + +/* + * Export all animation FCurves of an Object. + * + * Note: This uses the keyframes as sample points, + * and exports "baked keyframes" while keeping the tangent infromation + * of the FCurves intact. This works for simple cases, but breaks + * especially when negative scales are involved in the animation. + * + * If it is necessary to conserve the Animation precisely then + * use export_sampled_animation_set() instead. + */ +void AnimationExporter::export_keyframed_animation_set(Object *ob) +{ + FCurve *fcu = (FCurve *)ob->adt->action->curves.first; + if (!fcu) { + return; /* object has no animation */ + } + + if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) { + + std::vector<float> ctimes; + find_keyframes(ob, ctimes); + if (ctimes.size() > 0) + export_sampled_matrix_animation(ob, ctimes); + } + else { + char *transformName; + while (fcu) { + //for armature animations as objects + if (ob->type == OB_ARMATURE) + transformName = fcu->rna_path; + else + transformName = extract_transform_name(fcu->rna_path); + + if ( + STREQ(transformName, "location") || + STREQ(transformName, "scale") || + (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) || + STREQ(transformName, "rotation_quaternion")) + { + create_keyframed_animation(ob, fcu, transformName, false); + } + fcu = fcu->next; + } + } +} + +/* + * Export the sampled animation of an Object. + * + * Note: This steps over all animation frames (step size is given in export_settings.sample_size) + * and then evaluates the transformation, + * and exports "baked samples" This works always, however currently the interpolation type is set + * to LINEAR for now. (maybe later this can be changed to BEZIER) + * + * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead. + * However be aware that exporting keyframed animation may modify the animation slightly. + * Also keyframed animation exports tend to break when negative scales are involved. + */ +void AnimationExporter::export_sampled_animation_set(Object *ob) +{ + std::vector<float>ctimes; + find_sampleframes(ob, ctimes); + if (ctimes.size() > 0) { + if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) + export_sampled_matrix_animation(ob, ctimes); + else + export_sampled_transrotloc_animation(ob, ctimes); + } +} + +void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes) +{ + UnitConverter converter; + + std::vector<float> values; + + for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) { + float fmat[4][4]; + float outmat[4][4]; + + bc_update_scene(scene, *ctime); + BKE_object_matrix_local_get(ob, fmat); + + converter.mat4_to_dae(outmat, fmat); + + if (this->export_settings->limit_precision) + bc_sanitize_mat(outmat, 6); + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + values.push_back(outmat[j][i]); + } + + std::string ob_name = id_name(ob); + + create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false); +} + +void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes) +{ + static int LOC = 0; + static int EULX = 1; + static int EULY = 2; + static int EULZ = 3; + static int SCALE = 4; + + std::vector<float> baked_curves[5]; + + for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) { + float fmat[4][4]; + float floc[3]; + float fquat[4]; + float fsize[3]; + float feul[3]; + + bc_update_scene(scene, *ctime); + + BKE_object_matrix_local_get(ob, fmat); + mat4_decompose(floc, fquat, fsize, fmat); + quat_to_eul(feul, fquat); + + baked_curves[LOC].push_back(floc[0]); + baked_curves[LOC].push_back(floc[1]); + baked_curves[LOC].push_back(floc[2]); + + baked_curves[EULX].push_back(feul[0]); + baked_curves[EULY].push_back(feul[1]); + baked_curves[EULZ].push_back(feul[2]); + + baked_curves[SCALE].push_back(fsize[0]); + baked_curves[SCALE].push_back(fsize[1]); + baked_curves[SCALE].push_back(fsize[2]); + + } + + std::string ob_name = id_name(ob); + + create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false); + create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false); + + /* Not sure how to export rotation as a 3channel animation, + * so separate into 3 single animations for now: + */ + + create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true); + create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true); + create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true); + + fprintf(stdout, "Animation Export: Baked %d frames for %s (sampling rate: %d)\n", + (int)baked_curves[0].size(), + ob->id.name, + this->export_settings->sampling_rate); +} + +/* called for each exported object */ void AnimationExporter::operator()(Object *ob) { - FCurve *fcu; char *transformName; + /* bool isMatAnim = false; */ /* UNUSED */ //Export transform animations if (ob->adt && ob->adt->action) { - fcu = (FCurve *)ob->adt->action->curves.first; - //transform matrix export for bones are temporarily disabled here. if (ob->type == OB_ARMATURE) { + /* Export skeletal animation (if any)*/ bArmature *arm = (bArmature *)ob->data; for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) write_bone_animation_matrix(ob, bone); } - while (fcu) { - //for armature animations as objects - if (ob->type == OB_ARMATURE) - transformName = fcu->rna_path; - else - transformName = extract_transform_name(fcu->rna_path); - - if ((STREQ(transformName, "location") || STREQ(transformName, "scale")) || - (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) || - (STREQ(transformName, "rotation_quaternion"))) - { - dae_animation(ob, fcu, transformName, false); - } - fcu = fcu->next; + /* Armatures can have object animation and skeletal animation*/ + if (this->export_settings->sampling_rate < 1) { + export_keyframed_animation_set(ob); + } + else { + export_sampled_animation_set(ob); } - } export_object_constraint_animation(ob); @@ -92,14 +322,14 @@ void AnimationExporter::operator()(Object *ob) //Export Lamp parameter animations if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) { - fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first); + FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first); while (fcu) { transformName = extract_transform_name(fcu->rna_path); if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) || (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance"))) { - dae_animation(ob, fcu, transformName, true); + create_keyframed_animation(ob, fcu, transformName, true); } fcu = fcu->next; } @@ -107,7 +337,7 @@ void AnimationExporter::operator()(Object *ob) //Export Camera parameter animations if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) { - fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first); + FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first); while (fcu) { transformName = extract_transform_name(fcu->rna_path); @@ -116,7 +346,7 @@ void AnimationExporter::operator()(Object *ob) (STREQ(transformName, "clip_end")) || (STREQ(transformName, "clip_start"))) { - dae_animation(ob, fcu, transformName, true); + create_keyframed_animation(ob, fcu, transformName, true); } fcu = fcu->next; } @@ -128,7 +358,7 @@ void AnimationExporter::operator()(Object *ob) if (!ma) continue; if (ma->adt && ma->adt->action) { /* isMatAnim = true; */ - fcu = (FCurve *)ma->adt->action->curves.first; + FCurve *fcu = (FCurve *)ma->adt->action->curves.first; while (fcu) { transformName = extract_transform_name(fcu->rna_path); @@ -136,7 +366,7 @@ void AnimationExporter::operator()(Object *ob) (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) || (STREQ(transformName, "ior"))) { - dae_animation(ob, fcu, transformName, true, ma); + create_keyframed_animation(ob, fcu, transformName, true, ma); } fcu = fcu->next; } @@ -167,7 +397,7 @@ void AnimationExporter::export_morph_animation(Object *ob) while (fcu) { transformName = extract_transform_name(fcu->rna_path); - dae_animation(ob, fcu, transformName, true); + create_keyframed_animation(ob, fcu, transformName, true); fcu = fcu->next; } @@ -200,7 +430,7 @@ void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<fl obtar = ct->tar; if (obtar) - find_frames(obtar, frames); + find_keyframes(obtar, frames); } if (cti->flush_constraint_targets) @@ -265,8 +495,8 @@ std::string AnimationExporter::getAnimationPathId(const FCurve *fcu) return translate_id(rna_path); } -//convert f-curves to animation curves and write -void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma) +/* convert f-curves to animation curves and write */ +void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma) { const char *axis_name = NULL; char anim_id[200]; @@ -274,6 +504,8 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa bool has_tangents = false; bool quatRotation = false; + Object *obj = NULL; + if (STREQ(transformName, "rotation_quaternion") ) { fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n"); quatRotation = true; @@ -291,15 +523,26 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa axis_name = axis_names[fcu->array_index]; } - //axis names for transforms - else if (STREQ(transformName, "location") || - STREQ(transformName, "scale") || - STREQ(transformName, "rotation_euler") || - STREQ(transformName, "rotation_quaternion")) + /* + * Note: Handle transformation animations separately (to apply matrix inverse to fcurves) + * We will use the object to evaluate the animation on all keyframes and calculate the + * resulting object matrix. We need this to incorporate the + * effects of the parent inverse matrix (when it contains a rotation component) + * + * TODO: try to combine exported fcurves into 3 channel animations like done + * in export_sampled_animation(). For now each channel is exported as separate <Animation>. + */ + + else if ( + STREQ(transformName, "scale") || + STREQ(transformName, "location") || + STREQ(transformName, "rotation_euler")) { const char *axis_names[] = {"X", "Y", "Z"}; - if (fcu->array_index < 3) + if (fcu->array_index < 3) { axis_name = axis_names[fcu->array_index]; + obj = ob; + } } else { /* no axis name. single parameter */ @@ -308,7 +551,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa std::string ob_name = std::string("null"); - //Create anim Id + /* Create anim Id */ if (ob->type == OB_ARMATURE) { ob_name = getObjectBoneName(ob, fcu); BLI_snprintf( @@ -357,7 +600,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id); } else { - output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name); + output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj); } // create interpolations source @@ -369,10 +612,10 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa if (has_tangents) { // create in_tangent source - intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name); + intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj); // create out_tangent source - outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name); + outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj); } std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; @@ -475,8 +718,11 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B if (!pchan) return; - //every inserted keyframe of bones. - find_frames(ob_arm, fra); + + if (this->export_settings->sampling_rate < 1) + find_keyframes(ob_arm, fra); + else + find_sampleframes(ob_arm, fra); if (flag & ARM_RESTPOS) { arm->flag &= ~ARM_RESTPOS; @@ -755,14 +1001,60 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman } } +// old function to keep compatibility for calls where offset and object are not needed std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name) { - std::string source_id = anim_id + get_semantic_suffix(semantic); + return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL); +} - //bool is_angle = STREQ(fcu->rna_path, "rotation"); - bool is_angle = false; +void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime) +{ + BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); + ListBase *conlist = get_active_constraints(ob); + bConstraint *con; + for (con = (bConstraint *)conlist->first; con; con = con->next) { + ListBase targets = { NULL, NULL }; + + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + + if (cti && cti->get_constraint_targets) { + bConstraintTarget *ct; + Object *obtar; + cti->get_constraint_targets(con, &targets); + for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { + obtar = ct->tar; - if (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path,"spot_size")) is_angle = true; + if (obtar) { + BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM); + BKE_object_where_is_calc_time(scene, obtar, ctime); + } + } + + if (cti->flush_constraint_targets) + cti->flush_constraint_targets(con, &targets, 1); + } + } + BKE_object_where_is_calc_time(scene, ob, ctime); +} + +/* + * ob is needed to aply parent inverse information to fcurve. + * TODO: Here we have to step over all keyframes for each object and for each fcurve. + * Instead of processing each fcurve one by one, + * step over the animation from keyframe to keyframe, + * then create adjusted fcurves (and entries) for all affected objects. + * Then we would need to step through the scene only once. + */ +std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob) +{ + std::string source_id = anim_id + get_semantic_suffix(semantic); + + bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size")); + bool is_euler = strstr(fcu->rna_path, "rotation_euler"); + bool is_translation = strstr(fcu->rna_path, "location"); + bool is_scale = strstr(fcu->rna_path, "scale"); + bool is_tangent = false; + int offset_index = 0; COLLADASW::FloatSourceF source(mSW); source.setId(source_id); @@ -773,27 +1065,76 @@ std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemanti case COLLADASW::InputSemantic::INPUT: case COLLADASW::InputSemantic::OUTPUT: source.setAccessorStride(1); + offset_index = 0; break; case COLLADASW::InputSemantic::IN_TANGENT: case COLLADASW::InputSemantic::OUT_TANGENT: source.setAccessorStride(2); + offset_index = 1; + is_tangent = true; break; default: break; } - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); add_source_parameters(param, semantic, is_angle, axis_name, false); source.prepareToAppendValues(); - for (unsigned int i = 0; i < fcu->totvert; i++) { + for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) { + float fixed_val = 0; + if (ob) { + float fmat[4][4]; + float frame = fcu->bezt[frame_index].vec[1][0]; + float ctime = BKE_scene_frame_get_from_ctime(scene, frame); + + evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe + + BKE_object_matrix_local_get(ob, fmat); + float floc[3]; + float fquat[4]; + float fsize[3]; + mat4_decompose(floc, fquat, fsize, fmat); + + if (is_euler) { + float eul[3]; + quat_to_eul(eul, fquat); + fixed_val = RAD2DEGF(eul[fcu->array_index]); + } + else if (is_translation) { + fixed_val = floc[fcu->array_index]; + } + else if (is_scale) { + fixed_val = fsize[fcu->array_index]; + } + } + float values[3]; // be careful! + float offset = 0; int length = 0; - get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length); - for (int j = 0; j < length; j++) - source.appendValues(values[j]); + get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length); + if (is_tangent) { + float bases[3]; + int len = 0; + get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len); + offset = values[offset_index] - bases[0]; + } + + for (int j = 0; j < length; j++) { + float val; + if (j == offset_index) { + if (ob) { + val = fixed_val + offset; + } + else { + val = values[j] + offset; + } + } else { + val = values[j]; + } + source.appendValues(val); + } } source.finish(); @@ -837,9 +1178,9 @@ std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLA return source_id; } - - -//Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified ) +/* + * only to get OUTPUT source values ( if rotation and hence the axis is also specified ) + */ std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name) { std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -869,7 +1210,10 @@ std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic return source_id; } -// only used for sources with INPUT semantic + +/* + * only used for sources with INPUT semantic + */ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name) { std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -900,9 +1244,47 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti return source_id; } +std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id) +{ + COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; + std::string source_id = anim_id + get_semantic_suffix(semantic); + + COLLADASW::Float4x4Source source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(ctimes.size()); + source.setAccessorStride(16); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, false, NULL, true); + + source.prepareToAppendValues(); + + std::vector<float>::iterator it; + + for (it = values.begin(); it != values.end(); it+=16) { + float mat[4][4]; + + bc_copy_m4_farray(mat, &*it); + + UnitConverter converter; + double outmat[4][4]; + converter.mat4_to_dae_double(outmat, mat); + + if (this->export_settings->limit_precision) + bc_sanitize_mat(outmat, 6); + + source.appendValues(outmat); + } + + source.finish(); + return source_id; +} std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id) { + bool is_bone_animation = ob->type == OB_ARMATURE && bone; + COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -920,7 +1302,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj bPoseChannel *parchan = NULL; bPoseChannel *pchan = NULL; - if (ob->type == OB_ARMATURE && bone) { + if (is_bone_animation) { bPose *pose = ob->pose; pchan = BKE_pose_channel_find_name(pose, bone->name); if (!pchan) @@ -935,13 +1317,11 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj int j = 0; for (it = frames.begin(); it != frames.end(); it++) { float mat[4][4], ipar[4][4]; + float frame = *it; - float ctime = BKE_scene_frame_get_from_ctime(scene, *it); - CFRA = BKE_scene_frame_get_from_ctime(scene, *it); - //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene,scene->lay); - BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); - - if (bone) { + float ctime = BKE_scene_frame_get_from_ctime(scene, frame); + bc_update_scene(scene, ctime); + if (is_bone_animation) { if (pchan->flag & POSE_CHAIN) { enable_fcurves(ob->adt->action, NULL); BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); @@ -959,9 +1339,10 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj else copy_m4_m4(mat, pchan->pose_mat); - // OPEN_SIM_COMPATIBILITY - // AFAIK animation to second life is via BVH, but no - // reason to not have the collada-animation be correct + /* OPEN_SIM_COMPATIBILITY + * AFAIK animation to second life is via BVH, but no + * reason to not have the collada-animation be correct + */ if (export_settings->open_sim) { float temp[4][4]; copy_m4_m4(temp, bone->arm_mat); @@ -980,7 +1361,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj } else { - calc_ob_mat_at_time(ob, ctime, mat); + copy_m4_m4(mat, ob->obmat); } UnitConverter converter; @@ -1008,7 +1389,9 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj } -// only used for sources with OUTPUT semantic ( locations and scale) +/* + * only used for sources with OUTPUT semantic ( locations and scale) + */ std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id) { COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; @@ -1192,8 +1575,10 @@ std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, return std::string(""); } -// Assign sid of the animated parameter or transform -// for rotation, axis name is always appended and the value of append_axis is ignored +/* + * Assign sid of the animated parameter or transform for rotation, + * axis name is always appended and the value of append_axis is ignored + */ std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis) { std::string tm_name; @@ -1277,29 +1662,10 @@ char *AnimationExporter::extract_transform_name(char *rna_path) return dot ? (dot + 1) : rna_path; } -//find keyframes of all the objects animations -void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra) -{ - if (ob->adt && ob->adt->action) { - FCurve *fcu = (FCurve *)ob->adt->action->curves.first; - - for (; fcu; fcu = fcu->next) { - for (unsigned int i = 0; i < fcu->totvert; i++) { - float f = fcu->bezt[i].vec[1][0]; - if (std::find(fra.begin(), fra.end(), f) == fra.end()) - fra.push_back(f); - } - } - - // keep the keys in ascending order - std::sort(fra.begin(), fra.end()); - } -} - - - -// enable fcurves driving a specific bone, disable all the rest -// if bone_name = NULL enable all fcurves +/* + * enable fcurves driving a specific bone, disable all the rest + * if bone_name = NULL enable all fcurves + */ void AnimationExporter::enable_fcurves(bAction *act, char *bone_name) { FCurve *fcu; @@ -1364,14 +1730,53 @@ bool AnimationExporter::hasAnimations(Scene *sce) void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode) { if (rotmode > 0) - find_frames(ob, fra, prefix, "rotation_euler"); + find_keyframes(ob, fra, prefix, "rotation_euler"); else if (rotmode == ROT_MODE_QUAT) - find_frames(ob, fra, prefix, "rotation_quaternion"); + find_keyframes(ob, fra, prefix, "rotation_quaternion"); /*else if (rotmode == ROT_MODE_AXISANGLE) ;*/ } -void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) +/* Take care to always have the first frame and the last frame in the animation + * regardless of the sampling_rate setting + */ +void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra) +{ + int frame = scene->r.sfra; + do { + float ctime = BKE_scene_frame_get_from_ctime(scene, frame); + fra.push_back(ctime); + if (frame == scene->r.efra) + break; + frame += this->export_settings->sampling_rate; + if (frame > scene->r.efra) + frame = scene->r.efra; // make sure the last frame is always exported + + } while (true); +} + +/* + * find keyframes of all the objects animations + */ +void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra) +{ + if (ob->adt && ob->adt->action) { + FCurve *fcu = (FCurve *)ob->adt->action->curves.first; + + for (; fcu; fcu = fcu->next) { + for (unsigned int i = 0; i < fcu->totvert; i++) { + float f = fcu->bezt[i].vec[1][0]; + if (std::find(fra.begin(), fra.end(), f) == fra.end()) + fra.push_back(f); + } + } + + // keep the keys in ascending order + std::sort(fra.begin(), fra.end()); + } +} + +void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) { if (ob->adt && ob->adt->action) { FCurve *fcu = (FCurve *)ob->adt->action->curves.first; @@ -1429,10 +1834,10 @@ void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bo find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode); break; case 1: - find_frames(ob_arm, fra, prefix, "scale"); + find_keyframes(ob_arm, fra, prefix, "scale"); break; case 2: - find_frames(ob_arm, fra, prefix, "location"); + find_keyframes(ob_arm, fra, prefix, "location"); break; default: return; @@ -1539,8 +1944,23 @@ bool AnimationExporter::validateConstraints(bConstraint *con) return valid; } -void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]) +#if 0 +/* + * Needed for sampled animations. + * This function calculates the object matrix at a given time, + * also taking constraints into account. + * + * XXX: Why looking at the constraints here is necessary? + * Maybe this can be done better? + */ +void AnimationExporter::calc_obmat_at_time(Object *ob, float ctime ) { + BKE_scene_frame_set(scene, ctime); + + Main *bmain = bc_get_main(); + EvaluationContext *ev_context = bc_get_evaluation_context(); + BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay); + ListBase *conlist = get_active_constraints(ob); bConstraint *con; for (con = (bConstraint *)conlist->first; con; con = con->next) { @@ -1566,6 +1986,6 @@ void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[ } } BKE_object_where_is_calc_time(scene, ob, ctime); - copy_m4_m4(mat, ob->obmat); } +#endif diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 4736361ad13..52b46353528 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -90,9 +90,11 @@ private: public: AnimationExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings): - COLLADASW::LibraryAnimations(sw), export_settings(export_settings) - { this->sw = sw; } - + COLLADASW::LibraryAnimations(sw), + export_settings(export_settings) + { + this->sw = sw; + } bool exportAnimations(Scene *sce); @@ -102,7 +104,6 @@ public: protected: const ExportSettings *export_settings; - void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL); void export_object_constraint_animation(Object *ob); @@ -143,7 +144,18 @@ protected: float* get_eul_source_for_quat(Object *ob ); + bool is_flat_line(std::vector<float> &values, int channel_count); + void export_keyframed_animation_set(Object *ob); + void create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL); + void export_sampled_animation_set(Object *ob); + void export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes); + void export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes); + void create_sampled_animation(int channel_count, std::vector<float> ×, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot); + + void evaluate_anim_with_constraints(Object *ob, float ctime); + std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name); + std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob); std::string create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id); @@ -152,7 +164,7 @@ protected: std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name); std::string create_xyz_source(float *v, int tot, const std::string& anim_id); - + std::string create_4x4_source(std::vector<float> ×, std::vector<float> &values, const std::string& anim_id); std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id); std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents); @@ -164,8 +176,10 @@ protected: std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis); std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis); - void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name); - void find_frames(Object *ob, std::vector<float> &fra); + void find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name); + void find_keyframes(Object *ob, std::vector<float> &fra); + void find_sampleframes(Object *ob, std::vector<float> &fra); + void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames ); @@ -186,6 +200,6 @@ protected: bool validateConstraints(bConstraint *con); - void calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]); + //void calc_obmat_at_time(Object *ob, float ctime); }; diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 95543b2dc18..bc91b94afd9 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -817,7 +817,6 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a } float rot[4], loc[3], scale[3]; - transpose_m4(mat); bc_rotate_from_reference_quat(rot, qref, mat); copy_qt_qt(qref, rot); diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 5cd5e6d271a..4afe71f47ba 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -282,7 +282,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) } if (oob_counter > 0) { - fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %lu.\n", + fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n", oob_counter, joint_index_by_def_index.size()); } } diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 957fec50e4b..2b5d5692871 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -181,7 +181,7 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char * // COLLADA allows this through multiple <channel>s in <animation>. // For this to work, we need to know objects that use a certain action. -int DocumentExporter::exportCurrentScene(Scene *sce) +int DocumentExporter::exportCurrentScene(EvaluationContext *eval_ctx, Scene *sce) { PointerRNA sceneptr, unit_settings; PropertyRNA *system; /* unused , *scale; */ @@ -302,29 +302,11 @@ int DocumentExporter::exportCurrentScene(Scene *sce) SceneExporter se(writer, &arm_exporter, this->export_settings); - // <library_animations> - AnimationExporter ae(writer, this->export_settings); - -#if 0 - bool has_animations = ae.exportAnimations(sce); - /* The following code seems to be an obsolete workaround - Comment out until it proofs correct that we no longer need it. - */ - if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) { - // channels adressing <matrix> objects is not (yet) supported - // So we force usage of <location>, <translation> and <scale> - fprintf(stdout, - "For animated Ojects we must use decomposed <matrix> elements,\n" \ - "Forcing usage of TransLocRot transformation type."); - se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC); + if (this->export_settings->include_animations) { + // <library_animations> + AnimationExporter ae(writer, this->export_settings); + ae.exportAnimations(sce); } - else { - se.setExportTransformationType(this->export_settings->export_transformation_type); - } -#else - ae.exportAnimations(sce); - se.setExportTransformationType(this->export_settings->export_transformation_type); -#endif se.exportScene(sce); // <scene> diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h index 6e3c1ecd7cd..b2d8214212c 100644 --- a/source/blender/collada/DocumentExporter.h +++ b/source/blender/collada/DocumentExporter.h @@ -39,7 +39,7 @@ class DocumentExporter { public: DocumentExporter(const ExportSettings *export_settings); - int exportCurrentScene(Scene *sce); + int exportCurrentScene(EvaluationContext *eval_ctx, Scene *sce); void exportScenes(const char *filename); private: const ExportSettings *export_settings; diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 6d90edd2f67..73a101108a9 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -39,6 +39,8 @@ public: bool include_armatures; bool include_shapekeys; bool deform_bones_only; + bool include_animations; + int sampling_rate; bool active_uv_only; BC_export_texture_type export_texture_type; diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 73945539931..5a0badf8d3a 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -38,11 +38,6 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, { } -void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type) -{ - this->transformation_type = transformation_type; -} - void SceneExporter::exportScene(Scene *sce) { // <library_visual_scenes> <visual_scene> @@ -138,7 +133,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) // for skinned mesh we write obmat in <bind_shape_matrix> TransformWriter::add_node_transform_identity(colladaNode); else { - TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type); + TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type); } // <instance_geometry> diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index c7c15dba2cb..b896b9abd8d 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -97,11 +97,8 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, public: SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings); void exportScene(Scene *sce); - void setExportTransformationType(BC_export_transformation_type transformation_type); private: - BC_export_transformation_type transformation_type; - // required for writeNodes() for bone-parented objects friend class ArmatureExporter; void exportHierarchy(Scene *sce); void writeNodes(Object *ob, Scene *sce); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 024bc4a4a5c..7f723aae710 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -67,7 +67,8 @@ int collada_import(bContext *C, return 0; } -int collada_export(Scene *sce, +int collada_export(EvaluationContext *eval_ctx, + Scene *sce, const char *filepath, int apply_modifiers, @@ -78,6 +79,8 @@ int collada_export(Scene *sce, int include_armatures, int include_shapekeys, int deform_bones_only, + int include_animations, + int sampling_rate, int active_uv_only, BC_export_texture_type export_texture_type, @@ -103,6 +106,8 @@ int collada_export(Scene *sce, export_settings.include_armatures = include_armatures != 0; export_settings.include_shapekeys = include_shapekeys != 0; export_settings.deform_bones_only = deform_bones_only != 0; + export_settings.include_animations = include_animations; + export_settings.sampling_rate = sampling_rate; export_settings.active_uv_only = active_uv_only != 0; export_settings.export_texture_type = export_texture_type; @@ -139,7 +144,7 @@ int collada_export(Scene *sce, } DocumentExporter exporter(&export_settings); - int status = exporter.exportCurrentScene(sce); + int status = exporter.exportCurrentScene(eval_ctx, sce); BLI_linklist_free(export_settings.export_set, NULL); diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index d31f5a8ba62..09b46c1de58 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -32,6 +32,7 @@ extern "C" { #endif +#include "BKE_depsgraph.h" #include "BLI_linklist.h" #include "BLI_path_util.h" #include "RNA_types.h" @@ -51,6 +52,7 @@ typedef enum BC_export_texture_type { BC_TEXTURE_TYPE_UV } BC_export_texture_type; +struct EvaluationContext; struct bContext; struct Scene; @@ -67,7 +69,8 @@ int collada_import(struct bContext *C, int keep_bind_info); -int collada_export(struct Scene *sce, +int collada_export(struct EvaluationContext *eval_ctx, + struct Scene *sce, const char *filepath, int apply_modifiers, BC_export_mesh_type export_mesh_type, @@ -77,6 +80,8 @@ int collada_export(struct Scene *sce, int include_armatures, int include_shapekeys, int deform_bones_only, + int include_animations, + int sampling_rate, int active_uv_only, BC_export_texture_type export_texture_type, diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 415daccfa3d..fcd92e220c0 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -53,6 +53,7 @@ extern "C" { #include "BKE_mesh.h" #include "BKE_scene.h" #include "BKE_DerivedMesh.h" +#include "BKE_main.h" #include "ED_armature.h" @@ -132,6 +133,25 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) return true; } +Main *bc_get_main() +{ + return G.main; +} + +EvaluationContext *bc_get_evaluation_context() +{ + Main *bmain = G.main; + return bmain->eval_ctx; +} + +void bc_update_scene(Scene *scene, float ctime) +{ + BKE_scene_frame_set(scene, ctime); + Main *bmain = bc_get_main(); + EvaluationContext *ev_context = bc_get_evaluation_context(); + BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay); +} + Object *bc_add_object(Scene *scene, int type, const char *name) { Object *ob = BKE_object_add_only_object(G.main, type, name); @@ -871,6 +891,21 @@ void bc_sanitize_mat(double mat[4][4], int precision) mat[i][j] = double_round(mat[i][j], precision); } +void bc_copy_m4_farray(float r[4][4], float *a) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + r[i][j] = *a++; +} + +void bc_copy_farray_m4(float *r, float a[4][4]) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + *r++ = a[i][j]; + +} + /* * Returns name of Active UV Layer or empty String if no active UV Layer defined. * Assuming the Object is of type MESH diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index e9066d7db46..0069b4d4871 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -63,6 +63,10 @@ extern "C" { typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap; +extern Main *bc_get_main(); +extern EvaluationContext *bc_get_evaluation_context(); +extern void bc_update_scene(Scene *scene, float ctime); + extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index); extern int bc_test_parent_loop(Object *par, Object *ob); extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true); @@ -99,6 +103,13 @@ extern bool bc_is_leaf_bone(Bone *bone); extern EditBone *bc_get_edit_bone(bArmature * armature, char *name); extern int bc_set_layer(int bitfield, int layer, bool enable); extern int bc_set_layer(int bitfield, int layer); + +inline bool bc_in_range(float a, float b, float range) { + return fabsf(a - b) < range; +} +void bc_copy_m4_farray(float r[4][4], float *a); +void bc_copy_farray_m4(float *r, float a[4][4]); + extern void bc_sanitize_mat(float mat[4][4], int precision); extern void bc_sanitize_mat(double mat[4][4], int precision); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 0d51dc8dc76..aa31458aa5b 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -114,7 +114,7 @@ static void animedit_get_yscale_factor(bAnimContext *ac) /* grab scale factor directly from action editor setting * NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally - * since it is a float, and the theem settings methods can only handle chars. + * since it is a float, and the theme settings methods can only handle chars. */ ac->yscale_fac = btheme->tact.keyframe_scale_fac; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b25e1130c60..9a1d47e0154 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1555,6 +1555,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB rcti temp = *rect; temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1; widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false); + rect->xmax = temp.xmin; } /* If there's an icon too (made with uiDefIconTextBut) then draw the icon diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 39065606201..8826dc2971d 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -36,6 +36,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" @@ -87,6 +88,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int include_shapekeys; int deform_bones_only; + int include_animations; + int sample_animations; + int sampling_rate; + int export_texture_type; int use_texture_copies; int active_uv_only; @@ -136,6 +141,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) include_children = RNA_boolean_get(op->ptr, "include_children"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys"); + + include_animations = RNA_boolean_get(op->ptr, "include_animations"); + sample_animations = RNA_boolean_get(op->ptr, "sample_animations"); + sampling_rate = (sample_animations)? RNA_int_get(op->ptr, "sampling_rate") : 0; + deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection"); @@ -155,8 +165,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* get editmode results */ ED_object_editmode_load(CTX_data_edit_object(C)); + EvaluationContext *eval_ctx = G.main->eval_ctx; + Scene *scene = CTX_data_scene(C); - export_count = collada_export(CTX_data_scene(C), + export_count = collada_export(eval_ctx, + scene, filepath, apply_modifiers, export_mesh_type, @@ -165,6 +178,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) include_armatures, include_shapekeys, deform_bones_only, + include_animations, + sampling_rate, active_uv_only, export_texture_type, @@ -200,6 +215,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) { uiLayout *box, *row, *col, *split; + bool include_animations = RNA_boolean_get(imfptr, "include_animations"); /* Export Options: */ box = uiLayoutBox(layout); @@ -229,6 +245,16 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); + if (include_animations) { + uiItemR(row, imfptr, "sample_animations", 0, NULL, ICON_NONE); + row = uiLayoutColumn(box, false); + uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "sample_animations")); + } + /* Texture options */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); @@ -251,6 +277,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE); @@ -270,7 +297,6 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); uiItemL(split, IFACE_("Transformation Type"), ICON_NONE); uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE); - row = uiLayoutRow(box, false); uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE); @@ -366,7 +392,16 @@ void WM_OT_collada_export(wmOperatorType *ot) "Export all Shape Keys from Mesh Objects"); RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", - "Only export deforming bones with armatures"); + "Only export deforming bones with armatures"); + + RNA_def_boolean(func, "include_animations", false, + "Include Animations", "Export Animations if available.\nExporting Animations will enforce the decomposition of node transforms\ninto <translation> <rotation> and <scale> components"); + + RNA_def_boolean(func, "sample_animations", 0, + "Sample Animations", "Auto-generate keyframes with a frame distance set by 'Sampling Rate'.\nWhen disabled, export only the keyframes defined in the animation f-curves (may be less accurate)"); + + RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX, + "Sampling Rate", "The distance between 2 keyframes. 1 means: Every frame is keyed", 1, INT_MAX); RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map", "Export only the selected UV Map"); diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index 0e56dc817e4..907f346c931 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -171,8 +171,8 @@ int graphop_editable_keyframes_poll(bContext *C) /* editable curves must fulfill the following criteria: * - it has bezier keyframes - * - it must not be protected from editing (this is already checked for with the foredit flag - * - F-Curve modifiers do not interfere with the result too much + * - it must not be protected from editing (this is already checked for with the edit flag + * - F-Curve modifiers do not interfere with the result too much * (i.e. the modifier-control drawing check returns false) */ if (fcu->bezt == NULL) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 9d873795eaf..5665a5cff2d 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3048,7 +3048,7 @@ static const float std_node_socket_colors[][4] = { {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */ {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */ {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */ - {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */ + {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */ }; /* common color callbacks for standard types */ @@ -3135,20 +3135,11 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, uiTemplateComponentMenu(layout, ptr, "default_value", text); break; case SOCK_RGBA: - { - uiLayout *row = uiLayoutRow(layout, false); - uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); - /* draw the socket name right of the actual button */ - uiItemR(row, ptr, "default_value", 0, "", 0); - uiItemL(row, text, 0); - break; - } case SOCK_STRING: { - uiLayout *row = uiLayoutRow(layout, true); - /* draw the socket name right of the actual button */ - uiItemR(row, ptr, "default_value", 0, "", 0); + uiLayout *row = uiLayoutSplit(layout, 0.5f, false); uiItemL(row, text, 0); + uiItemR(row, ptr, "default_value", 0, "", 0); break; } default: @@ -3182,11 +3173,6 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); break; } - case SOCK_BOOLEAN: - { - uiItemR(layout, ptr, "default_value", 0, NULL, 0); - break; - } case SOCK_VECTOR: { uiLayout *row; @@ -3196,11 +3182,8 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); break; } + case SOCK_BOOLEAN: case SOCK_RGBA: - { - uiItemR(layout, ptr, "default_value", 0, NULL, 0); - break; - } case SOCK_STRING: { uiItemR(layout, ptr, "default_value", 0, NULL, 0); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d7119302611..e56a3a549fc 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -354,6 +354,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) dy -= NODE_DYS / 2; /* output sockets */ + bool add_output_space = false; + for (nsock = node->outputs.first; nsock; nsock = nsock->next) { if (nodeSocketIsHidden(nsock)) continue; @@ -386,6 +388,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) dy = buty; if (nsock->next) dy -= NODE_SOCKDY; + + add_output_space = true; + } + + if (add_output_space) { + dy -= NODE_DY / 4; } node->prvr.xmin = locx + NODE_DYS; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f999fab88ac..94c7ff5a051 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1555,8 +1555,10 @@ ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int } } -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -unsigned int ED_view3d_backbuf_sample_rect( +/** + * Smart function to sample a rectangle spiral ling outside, nice for backbuf selection + */ +uint ED_view3d_backbuf_sample_rect( ViewContext *vc, const int mval[2], int size, unsigned int min, unsigned int max, float *r_dist) { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 82c239eb320..68c35115584 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -916,61 +916,8 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot) WM_operator_properties_gesture_lasso_select(ot); } - -/* ************************************************* */ - -#if 0 -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo) -{ - Base *base; - unsigned int *bufmin, *bufmax; - int a, b, rc, tel, len, dirvec[4][2], maxob; - unsigned int retval = 0; - - base = LASTBASE; - if (base == 0) return 0; - maxob = base->selcol; - - len = (size - 1) / 2; - rc = 0; - - dirvec[0][0] = 1; - dirvec[0][1] = 0; - dirvec[1][0] = 0; - dirvec[1][1] = -size; - dirvec[2][0] = -1; - dirvec[2][1] = 0; - dirvec[3][0] = 0; - dirvec[3][1] = size; - - bufmin = buf; - bufmax = buf + size * size; - buf += len * size + len; - - for (tel = 1; tel <= size; tel++) { - - for (a = 0; a < 2; a++) { - for (b = 0; b < tel; b++) { - - if (*buf && *buf <= maxob && *buf != dontdo) return *buf; - if (*buf == dontdo) retval = dontdo; /* if only color dontdo is available, still return dontdo */ - - buf += (dirvec[rc][0] + dirvec[rc][1]); - - if (buf < bufmin || buf >= bufmax) return retval; - } - rc++; - rc &= 3; - } - } - return retval; -} -#endif - /* ************************** mouse select ************************* */ - /* The max number of menu items in an object select menu */ typedef struct SelMenuItemF { char idname[MAX_ID_NAME - 2]; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 928a0fc7d1e..bf5a06f0a1c 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -336,6 +336,21 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist /*************** visibility and selection utilities **************/ +static void uvedit_vertex_select_tagged(BMEditMesh *em, Scene *scene, bool select, int cd_loop_uv_offset) +{ + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } +} + bool uvedit_face_visible_nolocal(Scene *scene, BMFace *efa) { ToolSettings *ts = scene->toolsettings; @@ -1366,9 +1381,7 @@ static int uv_select_more_less(bContext *C, const bool select) if (ts->uv_selectmode == UV_SELECT_FACE) { /* clear tags */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - } + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); /* mark loops to be selected */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -1570,9 +1583,7 @@ static void uv_weld_align(bContext *C, int tool) BMIter iter, liter, eiter; /* clear tag */ - BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(eve, BM_ELEM_TAG); - } + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); /* tag verts with a selected UV */ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -2692,12 +2703,8 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { /* Tag all verts as untouched, then touch the ones that have a face center * in the loop and select all MLoopUV's that use a touched vert. */ - BMVert *eve; - - BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(eve, BM_ELEM_TAG); - } - + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -2783,11 +2790,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { /* Tag all verts as untouched, then touch the ones that have a face center * in the loop and select all MLoopUV's that use a touched vert. */ - BMVert *eve; - - BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(eve, BM_ELEM_TAG); - } + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -2911,7 +2914,8 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) else { /* other selection modes */ changed = true; - + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) @@ -2924,15 +2928,21 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) /* UV_SYNC_SELECTION - can't do pinned selection */ if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); } } else if (pinned) { if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); } } } } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } } if (changed) { @@ -2982,19 +2992,6 @@ static int uv_inside_circle(const float uv[2], const float offset[2], const floa return ((x * x + y * y) < 1.0f); } -static bool uv_select_inside_ellipse(BMEditMesh *em, Scene *scene, const bool select, - const float offset[2], const float ellipse[2], BMLoop *l, MLoopUV *luv, - const int cd_loop_uv_offset) -{ - if (uv_inside_circle(luv->uv, offset, ellipse)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - return true; - } - else { - return false; - } -} - static int uv_circle_select_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); @@ -3054,12 +3051,22 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) } } else { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - changed |= uv_select_inside_ellipse(em, scene, select, offset, ellipse, l, luv, cd_loop_uv_offset); + if (uv_inside_circle(luv->uv, offset, ellipse)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } } } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } } if (changed) { @@ -3152,6 +3159,8 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo } } else { /* Vert Sel */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { @@ -3166,11 +3175,16 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo { uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); } } } } } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } } if (changed) { @@ -4168,17 +4182,14 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *loop; BMIter iter, liter; - bool clear = RNA_boolean_get(op->ptr, "clear"); + bool flag_set = !RNA_boolean_get(op->ptr, "clear"); const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) { - if (clear) - BM_elem_flag_disable(loop->e, BM_ELEM_SEAM); - else - BM_elem_flag_enable(loop->e, BM_ELEM_SEAM); + BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set); } } } diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h index cf5b8bf7d8f..53f480bccd7 100644 --- a/source/blender/gpu/GPU_select.h +++ b/source/blender/gpu/GPU_select.h @@ -47,6 +47,7 @@ enum { void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits); bool GPU_select_load_id(unsigned int id); +void GPU_select_finalize(void); unsigned int GPU_select_end(void); bool GPU_select_query_check_active(void); diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index 632b0cfee1b..e2837d96b0f 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -150,6 +150,29 @@ bool GPU_select_load_id(unsigned int id) } /** + * Needed when GL context of #GPU_select_end + * can't be used to finalize selection operations + * (because of context changes). + */ +void GPU_select_finalize(void) +{ + if (!g_select_state.select_is_active) + return; + + switch (g_select_state.algorithm) { + case ALGO_GL_LEGACY: + case ALGO_GL_QUERY: + { + break; + } + default: /* ALGO_GL_PICK */ + { + gpu_select_pick_finalize(); + } + } +} + +/** * Cleanup and flush selection results to buffer. * Return number of hits and hits in buffer. * if \a dopass is true, we will do a second pass with occlusion queries to get the closest hit. diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 0a77420fa25..bd6b43ee42f 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -255,6 +255,7 @@ typedef struct GPUPickState { /* Set after first draw */ bool is_init; + bool is_finalized; unsigned int prev_id; } gl; @@ -366,6 +367,7 @@ void gpu_select_pick_begin( #endif ps->gl.is_init = false; + ps->gl.is_finalized = false; ps->gl.prev_id = 0; } else { @@ -526,6 +528,20 @@ bool gpu_select_pick_load_id(unsigned int id) return true; } + /** + * (Optional), call before 'gpu_select_pick_end' if GL context is not kept. + * is not compatible with regular select case. + * */ +void gpu_select_pick_finalize(void) +{ + GPUPickState *ps = &g_pick_state; + if (ps->gl.is_init) { + /* force finishing last pass */ + gpu_select_pick_load_id(ps->gl.prev_id); + } + ps->gl.is_finalized = true; +} + unsigned int gpu_select_pick_end(void) { GPUPickState *ps = &g_pick_state; @@ -535,9 +551,8 @@ unsigned int gpu_select_pick_end(void) #endif if (ps->is_cached == false) { - if (ps->gl.is_init) { - /* force finishing last pass */ - gpu_select_pick_load_id(ps->gl.prev_id); + if (ps->gl.is_finalized == false) { + gpu_select_pick_finalize(); } glPopAttrib(); diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h index 8935bd7b253..8368aaa9edc 100644 --- a/source/blender/gpu/intern/gpu_select_private.h +++ b/source/blender/gpu/intern/gpu_select_private.h @@ -35,6 +35,7 @@ /* gpu_select_pick */ void gpu_select_pick_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode); bool gpu_select_pick_load_id(unsigned int id); +void gpu_select_pick_finalize(void); unsigned int gpu_select_pick_end(void); void gpu_select_pick_cache_begin(void); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 539b9fa45b4..4cb1c13a44a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1290,7 +1290,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa return 1; } - /* last token is single character channel identifier */ + /* last token is channel identifier */ len = imb_exr_split_token(name, end, &token); if (len == 0) { printf("multilayer read: bad channel name: %s\n", name); @@ -1319,10 +1319,30 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa ok = true; } } + else if (BLI_strcaseeq(token, "red")) { + echan->chan_id = 'R'; + ok = true; + } + else if (BLI_strcaseeq(token, "green")) { + echan->chan_id = 'G'; + ok = true; + } + else if (BLI_strcaseeq(token, "blue")) { + echan->chan_id = 'B'; + ok = true; + } + else if (BLI_strcaseeq(token, "alpha")) { + echan->chan_id = 'A'; + ok = true; + } + else if (BLI_strcaseeq(token, "depth")) { + echan->chan_id = 'Z'; + ok = true; + } if (ok == false) { BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME)); - printf("multilayer read: channel token too long: %s\n", tokenbuf); + printf("multilayer read: unknown channel token: %s\n", tokenbuf); return 0; } } diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index 9932e16e988..c1565bde882 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -217,6 +217,9 @@ typedef struct SmokeDomainSettings { char use_coba; char coba_field; /* simulation field used for the color mapping */ char pad2; + + float clipping; + float pad3; } SmokeDomainSettings; diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 0f22f8d3b0f..3043e636b31 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -262,63 +262,6 @@ static void rna_Scene_alembic_export( #endif -#ifdef WITH_COLLADA -/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */ -#include "../../collada/collada.h" - -/* Note: This definition must match to the generated function call */ -static void rna_Scene_collada_export( - Scene *scene, - const char *filepath, - int apply_modifiers, - - int export_mesh_type, - int selected, - int include_children, - int include_armatures, - int include_shapekeys, - int deform_bones_only, - int active_uv_only, - int export_texture_type, - int use_texture_copies, - int triangulate, - int use_object_instantiation, - int use_blender_profile, - int sort_by_name, - int export_transformation_type, - int open_sim, - int limit_precision, - int keep_bind_info) -{ - collada_export(scene, - filepath, - - apply_modifiers, - export_mesh_type, - - selected, - include_children, - include_armatures, - include_shapekeys, - deform_bones_only, - - active_uv_only, - export_texture_type, - use_texture_copies, - - triangulate, - use_object_instantiation, - use_blender_profile, - sort_by_name, - - export_transformation_type, - open_sim, - limit_precision, - keep_bind_info); -} - -#endif - #else void RNA_api_scene(StructRNA *srna) @@ -374,66 +317,6 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f); RNA_def_function_output(func, parm); -#ifdef WITH_COLLADA - /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */ - func = RNA_def_function(srna, "collada_export", "rna_Scene_collada_export"); - parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Collada file"); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */ - - RNA_def_boolean(func, "apply_modifiers", false, - "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))"); - - RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX, - "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX); - - RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements"); - - RNA_def_boolean(func, "include_children", false, - "Include Children", "Export all children of selected objects (even if not selected)"); - - RNA_def_boolean(func, "include_armatures", false, - "Include Armatures", "Export related armatures (even if not selected)"); - - RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects"); - - RNA_def_boolean(func, "deform_bones_only", false, - "Deform Bones only", "Only export deforming bones with armatures"); - - RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map"); - - RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX, - "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX); - - RNA_def_boolean(func, "use_texture_copies", true, - "Copy", "Copy textures to same folder where the .dae file is exported"); - - RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles"); - - RNA_def_boolean(func, "use_object_instantiation", true, - "Use Object Instances", "Instantiate multiple Objects from same Data"); - - RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile", - "Export additional Blender specific information (for material, shaders, bones, etc.)"); - - RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name"); - - RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, - "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); - - RNA_def_boolean(func, "open_sim", false, - "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); - - RNA_def_boolean(func, "limit_precision", false, - "Limit Precision", - "Reduce the precision of the exported data to 6 digits"); - - RNA_def_boolean(func, "keep_bind_info", false, - "Keep Bind Info", - "Store bind pose information in custom bone properties for later use during Collada export"); - -#endif - #ifdef WITH_ALEMBIC /* XXX Deprecated, will be removed in 2.8 in favour of calling the export operator. */ func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export"); diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 08665f3007a..54daba706c7 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -362,6 +362,42 @@ static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values) #endif } +static void rna_SmokeModifier_temperature_grid_get(PointerRNA *ptr, float *values) +{ +#ifdef WITH_SMOKE + SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; + int length[RNA_MAX_ARRAY_DIMENSION]; + int size = rna_SmokeModifier_grid_get_length(ptr, length); + float *flame; + + BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); + + if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) { + flame = smoke_turbulence_get_flame(sds->wt); + } + else { + flame = smoke_get_flame(sds->fluid); + } + + if (flame) { + /* Output is such that 0..1 maps to 0..1000K */ + float offset = sds->flame_ignition; + float scale = sds->flame_max_temp - sds->flame_ignition; + + for (int i = 0; i < size; i++) { + values[i] = (flame[i] > 0.01f) ? offset + flame[i] * scale : 0.0f; + } + } + else { + memset(values, 0, size * sizeof(float)); + } + + BLI_rw_mutex_unlock(sds->fluid_mutex); +#else + UNUSED_VARS(ptr, values); +#endif +} + static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value) { SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data; @@ -677,6 +713,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_float_funcs(prop, "rna_SmokeModifier_heat_grid_get", NULL, NULL); RNA_def_property_ui_text(prop, "Heat Grid", "Smoke heat grid"); + prop = RNA_def_property(srna, "temperature_grid", PROP_FLOAT, PROP_NONE); + RNA_def_property_array(prop, 32); + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length"); + RNA_def_property_float_funcs(prop, "rna_SmokeModifier_temperature_grid_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K"); + prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */ RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "cell_size", "Cell Size"); @@ -854,6 +898,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ColorRamp"); RNA_def_property_ui_text(prop, "Color Ramp", ""); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "clipping", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "clipping"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Clipping", + "Value under which voxels are considered empty space to optimize caching or rendering"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); } static void rna_def_smoke_flow_settings(BlenderRNA *brna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 1acd1c4ea46..5247599bdf7 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -210,6 +210,7 @@ set(SRC shader/nodes/node_shader_tex_wave.c shader/nodes/node_shader_volume_scatter.c shader/nodes/node_shader_volume_absorption.c + shader/nodes/node_shader_volume_principled.c shader/nodes/node_shader_uvAlongStroke.c shader/nodes/node_shader_uvmap.c shader/node_shader_tree.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 6ed71e02823..b00307ed7fb 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -114,6 +114,7 @@ void register_node_type_sh_emission(void); void register_node_type_sh_holdout(void); void register_node_type_sh_volume_absorption(void); void register_node_type_sh_volume_scatter(void); +void register_node_type_sh_volume_principled(void); void register_node_type_sh_bsdf_hair(void); void register_node_type_sh_subsurface_scattering(void); void register_node_type_sh_mix_shader(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 2db23c2122d..bc90e33ed03 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -92,6 +92,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BS DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","") DefNode( ShaderNode, SH_NODE_VOLUME_ABSORPTION, 0, "VOLUME_ABSORPTION", VolumeAbsorption, "Volume Absorption", "" ) DefNode( ShaderNode, SH_NODE_VOLUME_SCATTER, 0, "VOLUME_SCATTER", VolumeScatter, "Volume Scatter", "" ) +DefNode( ShaderNode, SH_NODE_VOLUME_PRINCIPLED, 0, "PRINCIPLED_VOLUME", VolumePrincipled, "Principled Volume", "" ) DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" ) DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" ) DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c new file mode 100644 index 00000000000..f9a481e6c7e --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c @@ -0,0 +1,85 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_volume_principled_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, + { SOCK_STRING, 1, N_("Color Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, + { SOCK_STRING, 1, N_("Density Attribute"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, N_("Absorption Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Emission Strength"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1000.0f}, + { SOCK_RGBA, 1, N_("Emission Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Blackbody Intensity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, N_("Blackbody Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Temperature"), 1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6500.0f}, + { SOCK_STRING, 1, N_("Temperature Attribute"),0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_volume_principled_out[] = { + { SOCK_SHADER, 0, N_("Volume")}, + { -1, 0, "" } +}; + +static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) { + if (STREQ(sock->name, "Density Attribute")) { + strcpy(((bNodeSocketValueString *)sock->default_value)->value, "density"); + } + else if (STREQ(sock->name, "Temperature Attribute")) { + strcpy(((bNodeSocketValueString *)sock->default_value)->value, "temperature"); + } + } +} + +static int node_shader_gpu_volume_principled(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) +{ + return false; +} + +/* node type definition */ +void register_node_type_sh_volume_principled(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_volume_principled_in, sh_node_volume_principled_out); + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_init(&ntype, node_shader_init_volume_principled); + node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_volume_principled); + + nodeRegisterType(&ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c index 0c5647b4ba8..ed56df257b7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c @@ -32,7 +32,7 @@ static bNodeSocketTemplate sh_node_volume_scatter_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" } }; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 2d72bcf4d58..71d6ec673e6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -2144,11 +2144,13 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U char path[FILE_MAX]; RNA_string_get(op->ptr, "filepath", path); - if (BLI_exists(path)) { + if (RNA_boolean_get(op->ptr, "check_existing") && BLI_exists(path)) { ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, path); } else { ret = wm_save_as_mainfile_exec(C, op); + /* Without this there is no feedback the file was saved. */ + BKE_reportf(op->reports, RPT_INFO, "Saved \"%s\"", BLI_path_basename(path)); } } else { |