Merge branch 'master' into blender2.8

This commit is contained in:
Sergey Sharybin 2017-05-31 15:51:17 +02:00
commit f32a18994a
62 changed files with 820 additions and 545 deletions

View File

@ -19,7 +19,7 @@
#
# ***** END LGPL LICENSE BLOCK *****
remove_extra_strict_flags()
remove_strict_flags()
if(CMAKE_COMPILER_IS_GNUCC)
remove_cc_flag("-Wunused-macros")

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
#include "render/mesh.h"
#include "render/object.h"
#include "render/scene.h"
@ -293,7 +292,7 @@ static void create_mesh_volume_attribute(BL::Object& b_ob,
if(!b_domain)
return;
Attribute *attr = mesh->attributes.add(std);
VoxelAttribute *volume_data = attr->data_voxel();
bool is_float, is_linear;
@ -982,7 +981,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
else
used_shaders.push_back(scene->default_surface);
}
/* test if we need to sync */
int requested_geometry_flags = Mesh::GEOMETRY_NONE;
if(render_layer.use_surfaces) {
@ -1017,12 +1016,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
/* ensure we only sync instanced meshes once */
if(mesh_synced.find(mesh) != mesh_synced.end())
return mesh;
mesh_synced.insert(mesh);
/* create derived mesh */
array<int> oldtriangle = mesh->triangles;
/* compares curve_keys rather than strands in order to handle quick hair
* adjustments in dynamic BVH - other methods could probably do this better*/
array<float3> oldcurve_keys = mesh->curve_keys;
@ -1111,7 +1110,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
if(memcmp(&oldcurve_radius[0], &mesh->curve_radius[0], sizeof(float)*oldcurve_radius.size()) != 0)
rebuild = true;
}
mesh->tag_update(scene, rebuild);
return mesh;
@ -1140,7 +1139,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
if(scene->need_motion() == Scene::MOTION_BLUR) {
if(!mesh->use_motion_blur)
return;
/* see if this mesh needs motion data at this time */
vector<float> object_times = object->motion_times();
bool found = false;
@ -1172,7 +1171,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
if(!numverts && !numkeys)
return;
/* skip objects without deforming modifiers. this is not totally reliable,
* would need a more extensive check to see which objects are animated */
BL::Mesh b_mesh(PointerRNA_NULL);

View File

@ -299,7 +299,7 @@ static inline uint get_layer(const BL::Array<int, 20>& array)
for(uint i = 0; i < 20; i++)
if(array[i])
layer |= (1 << i);
return layer;
}
@ -434,7 +434,7 @@ static inline string get_string(PointerRNA& ptr, const char *name)
string str(cstr);
if(cstr != cstrbuf)
MEM_freeN(cstr);
return str;
}
@ -451,7 +451,7 @@ static inline string blender_absolute_path(BL::BlendData& b_data,
{
if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
string dirname;
if(b_id.library()) {
BL::ID b_library_id(b_id.library());
dirname = blender_absolute_path(b_data,
@ -544,7 +544,7 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
return b_smd.domain_settings();
}
}
return BL::SmokeDomainSettings(PointerRNA_NULL);
}
@ -816,4 +816,3 @@ protected:
CCL_NAMESPACE_END
#endif /* __BLENDER_UTIL_H__ */

View File

@ -191,7 +191,7 @@ class PrincipledBSSRDFClosure : public CBSSRDFClosure {
public:
void setup(ShaderData *sd, int path_flag, float3 weight)
{
alloc(sd, path_flag, weight * albedo, CLOSURE_BSSRDF_PRINCIPLED_ID);
alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_ID);
}
};

View File

@ -57,8 +57,8 @@ shader node_principled_bsdf(
if (diffuse_weight > 1e-5) {
if (Subsurface > 1e-5) {
color Albedo = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
BSDF = bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, Albedo, Roughness);
color mixed_ss_base_color = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
BSDF = mixed_ss_base_color * bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, SubsurfaceColor, Roughness);
} else {
BSDF = BaseColor * principled_diffuse(Normal, Roughness);
}

View File

@ -141,8 +141,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 weight = sd->svm_closure_weight * mix_weight;
#ifdef __SUBSURFACE__
float3 albedo = subsurface_color * subsurface + base_color * (1.0f - subsurface);
float3 subsurf_weight = weight * albedo * diffuse_weight;
float3 mixed_ss_base_color = subsurface_color * subsurface + base_color * (1.0f - subsurface);
float3 subsurf_weight = weight * mixed_ss_base_color * diffuse_weight;
float subsurf_sample_weight = fabsf(average(subsurf_weight));
/* disable in case of diffuse ancestor, can't see it well then and
@ -154,7 +154,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
/* need to set the base color in this case such that the
* rays get the correctly mixed color after transmitting
* the object */
base_color = albedo;
base_color = mixed_ss_base_color;
}
/* diffuse */
@ -186,7 +186,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->sample_weight = subsurf_sample_weight;
bssrdf->radius = radius.x;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.x;
bssrdf->albedo = subsurface_color.x;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
bssrdf->roughness = roughness;
@ -200,7 +200,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->sample_weight = subsurf_sample_weight;
bssrdf->radius = radius.y;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.y;
bssrdf->albedo = subsurface_color.y;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
bssrdf->roughness = roughness;
@ -214,7 +214,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->sample_weight = subsurf_sample_weight;
bssrdf->radius = radius.z;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.z;
bssrdf->albedo = subsurface_color.z;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
bssrdf->roughness = roughness;

View File

@ -111,11 +111,6 @@ public:
&& tile_size == params.tile_size
&& start_resolution == params.start_resolution
&& threads == params.threads
&& use_denoising == params.use_denoising
&& denoising_radius == params.denoising_radius
&& denoising_strength == params.denoising_strength
&& denoising_feature_strength == params.denoising_feature_strength
&& denoising_relative_pca == params.denoising_relative_pca
&& display_buffer_linear == params.display_buffer_linear
&& cancel_timeout == params.cancel_timeout
&& reset_timeout == params.reset_timeout

View File

@ -890,16 +890,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
// send motion. Mark as 'sent' so motion will always get dispatched.
eventSent = true;
#if defined(_MSC_VER)
// using Microsoft compiler & header files
// they invented the RawInput API, so this version is (probably) correct.
BYTE const *data = raw.data.hid.bRawData;
// struct RAWHID {
// DWORD dwSizeHid;
// DWORD dwCount;
// BYTE bRawData[1];
// };
#endif
BYTE packetType = data[0];
switch (packetType) {

View File

@ -1,3 +1,156 @@
commit efd7a93317e0278b99e66785f667823e451daef1
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue May 9 10:16:42 2017 +0200
Fix strict compiler warnings, unused variables
commit 8efd47e13dfdd3f7209bc96f26d0b13127dd6376
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Dec 14 10:44:57 2016 +0100
Fix T50243: libmv_panography_test is broken
There was fully wrong logic in comparison: was actually accessing memory
past the array boundary. Run test manually and the figure seems correct
to me now.
Spotted by @LazyDodo, thanks!
commit 6dfb9cd1bd14669d84be789000ce234747fb00ff
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Jul 14 11:49:38 2016 +0200
Fix some strict compiler warnings
One of them was a real bug!
commit f61adaecf7b29ebe6677be0e1c825f0a8d475e4b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 31 11:22:34 2017 +0200
Enable explicit schur complement for BA step
This is something we do in Blender and only reason it was not
enabled for standalone Libmv is because we did not have fresh
enough version of Ceres bundled.
commit fc5d3a1d4880c6658aff693c1c1e8c10c96ce1a7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Nov 2 15:32:11 2016 +0100
Update tests to make tests pass after recent Ceres update
Just a precision issue, difference is around 1e-7. Should be fine to
simply update expected value.
commit e1ac9f6124110c1a90d8e417bea47acfcbdcca42
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 31 10:54:48 2017 +0200
Update Ceres to latest release 1.12.0
commit ac1571352b4962f110929b963f8616d7310ceea5
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Apr 7 17:10:44 2017 +0200
Fix crash of keyframe selection on 32bit linux
commit 5f8df3da965686df39a6ae5c9f17482075017bf4
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue Jan 19 14:00:53 2016 +0500
Solve some strict warnings in tests
commit 8ea3a5d752a9ce3337ab7643897472a4d33747f1
Author: Brecht Van Lommel <brechtvanlommel@gmail.com>
Date: Sat Feb 18 23:52:31 2017 +0100
Fix a few compiler warnings with macOS / clang.
commit ffbe81461770e70736e80b8cab8e6eb1f8b27160
Author: Mike Erwin <significant.bit@gmail.com>
Date: Wed May 31 10:43:08 2017 +0200
Fix comparison of identicals
Some of these check that dimensions match before running code that
assumes they do match.
Found with PVS-Studio T48917.
commit 206c01999cde16c1c6c43a8e13ffa86020821d98
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 31 10:39:16 2017 +0200
Add basic track masking API in place
This brings back ability to mask non-interesting parts of
specific track (the feature got lost with new auto-track API).
Added it back by extending frame accessor class. This isn't really
a frame thing, but we don't have other type of accessor here.
Surely, we can use old-style API here and pass mask via region
tracker options for this particular case, but then it becomes much
less obvious how real auto-tracker will access this mask with old
style API.
So seems we do need an accessor for such data, just matter of
finding better place than frame accessor.
commit faa069cb826892780356477cc10602390fecf06b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 31 10:36:26 2017 +0200
Tests: Tweak epsilon to avoid what looks a false-positive failure
commit 7c84e45c1d330871477ba3516f57178e5b9d101f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 31 10:15:43 2017 +0200
CMake: Fix mistake in closing branch
commit cb769a0d319a8c95948153d78a4c3378a0142ece
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Jul 21 12:52:33 2016 +0200
Set of fixes for MSVC215
- Move GLOG/GFLAGS defines to a more global scope,
this way ANY of our own libraries will use proper
declspec.
- Compile png/zlib/openexif on Windows as well since
those are required for a correct linking.
commit bb95c8654fd2cea72d66ed04cd825cc3712ea804
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Jul 20 18:14:46 2016 +0200
Disable unexisting Ceres option
Explicit Schur complement requires having
newer Ceres than we currently have bundled.
commit a2e12c959ef32cc9382244d1581992c2f7aa9c09
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Jul 20 18:04:57 2016 +0200
Various fixes for MSVC
- Update Eigen to 3.2.7 since this brings crucial
fixes for MSVC 2015.
- Switch to STATIC build by default.
There are issues building current sources as dynamic
libraries with MSVC2015 and additionally building
dynamic Ceres is not recommended anyway, so let's
not do this for the time being.
If anyone finds a way to make this all working --
it'llsurely be a welcome addition.
commit 7a676106720fb126a27ff010abdd8bb65d7e0d9a
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Jan 4 18:30:12 2016 +0500
@ -365,239 +518,3 @@ Date: Thu May 8 15:50:26 2014 +0200
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D516
commit 4405dff60ea08d454b64da1a7c0595d9328cf8a3
Author: Keir Mierle <mierle@gmail.com>
Date: Thu May 8 15:38:14 2014 +0200
Add public SetMarkers to AutoTrack
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D515
commit c90837f6db276a3b1f610eaad509155f6a43b24f
Author: Keir Mierle <mierle@gmail.com>
Date: Thu May 8 15:17:48 2014 +0200
Make autotrack skeleton compile
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D514
commit be01baa2e82e36f63e548f073157e68d2ff870c0
Author: Keir Mierle <mierle@gmail.com>
Date: Wed May 7 18:48:55 2014 +0200
Add preliminary TrackMarkerToFrame in autotrack
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D509
commit 0cab028d591b3d08672ca86eb6c6e4ac1aacf1d0
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 7 17:59:11 2014 +0200
Remove assert from ArrayND Resize
That assert broke initialization of arrays which doesn't
own the data since constructor uses Resize to set shape
and strides.
Strides are still to be fixed, but that's for later.
commit 64f9c118029a9351e9023e96527c120e1d724d5b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 7 17:42:21 2014 +0200
Fix ArrayND freeing the data it doesn't own
Can't really guarantee it works fully correct now,
but at least this check is needed anyway and compilation
works just fine.
Reviewers: keir
Reviewed By: keir
Differential Revision: https://developer.blender.org/D508
commit 0618f1c8e88dfc738cdde55784da80b889905e7c
Author: Keir Mierle <mierle@gmail.com>
Date: Wed May 7 12:03:32 2014 +0200
Minor changes
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D505
commit 5c34335e1bb90c4ed701ee830c718ed4e20dbffa
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 7 11:12:23 2014 +0200
Fix compilation error in frame accessor
- int64 is not a standard type, we've got int64_t defined in
std int. We also have an msvc port of this header, so should
not be an issue.
- Fixed inconsistency in usage of CacheKey and Key, used Key.
- Some functions weren't marked as virtual.
Additional change: added self to authors.
Reviewers: keir
Reviewed By: keir
Differential Revision: https://developer.blender.org/D504
commit 06bc207614e262cd688e2c3ed820ade7c77bdb66
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 6 22:30:59 2014 +0200
Start new Tracks implementation
This adds the new Tracks implementation, as well as a
trivial test to show it compiles.
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D502
commit 25ce061e6da69881460ba7718bb0d660a2380a02
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 6 19:10:51 2014 +0200
Add Reconstruction class for new API
This starts the new Reconstruction class (with support for e.g. planes). This
also starts the new namespace "mv" which will eventually have all the symbols
we wish to export.
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D501
commit 0a6af3e29016048978aea607673340500e050339
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 6 17:52:53 2014 +0200
Add a new Tracks implementation
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D500
commit 887b68d29c2b198f4939f9ab5153881aa2c1806e
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 6 17:01:39 2014 +0200
Initial commit of unfinished AutoTrack API
This starts the creating the new AutoTrack API. The new API will
make it possible for libmv to do full autotracking, including
predictive tracking and also support multiple motion models (3D
planes etc).
The first goal (not in this patch) is to convert Blender to use
the new API without adding any new functionality.
Note: This does not add any of the API to the build system!
It likely does not compile.
Reviewers: sergey
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D499
commit 08cc227d431d257d27f300fbb8e6991e663302da
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Tue May 6 13:09:22 2014 +0200
Fix homography test failure
It was caused by assuming that reconstructed homography matrix
should look exactly the same as the matrix used to generate a
test case.
It's not actually valid assumption because different-looking
matrices could correspond to the same exact transform.
In this change we make it so actual "re-projected" vectors
are being checked, not the values in matrix. This makes it
more predictable verification.
Reviewers: keir
Reviewed By: keir
Differential Revision: https://developer.blender.org/D488
commit 0b7d83dc9627447dc7df64d7e3a468aefe9ddc13
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Apr 23 19:14:55 2014 +0600
Fix compilation on OSX after previous commit
EXPECT_EQ wasn't defined in the scope.
commit d14049e00dabf8fdf49056779f0a3718fbb39e8f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Apr 23 15:08:16 2014 +0600
Move aligned malloc implementation into own file
It was rather stupid having it in brute region tracker,
now it is in own file in base library (which was also
added in this commit, before this it consist of header
files only).
Reviewers: keir
Reviewed By: keir
Differential Revision: https://developer.blender.org/D479
commit 0ddf3851bfcb8de43660b119a25a77a25674200d
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 21 14:14:03 2014 +0600
Optimization of PearsonProductMomentCorrelation
Pass the arrays by reference rather than by value,
should give some percent of speedup.
Also don't pass the dimensions to the function but
get them from the images themselves.
Hopefully this will give some %% of tracker speedup.
commit f68fdbe5896a6c5bd8b500caeec61b876c5e44c6
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Apr 21 14:10:43 2014 +0600
Fix wrong assert in ResizeImage()
The assert didn't make any sense because ComputeBoundingBox()
is intended to return bounding box in the following way:
(xmin, xmax, ymin, ymax).

View File

@ -120,6 +120,7 @@ if(WITH_LIBMV)
add_definitions(\${GFLAGS_DEFINES})
add_definitions(\${GLOG_DEFINES})
add_definitions(\${CERES_DEFINES})
add_definitions(-DLIBMV_GFLAGS_NAMESPACE=\${GFLAGS_NAMESPACE})
list(APPEND INC
\${GFLAGS_INCLUDE_DIRS}

View File

@ -134,6 +134,11 @@ struct LibmvFrameAccessor : public FrameAccessor {
&width,
&height);
if (cache_key == NULL) {
// No mask for the given track.
return NULL;
}
// TODO(sergey): Dumb code for until we can set data directly.
FloatImage temp_image(float_buffer,
height,

View File

@ -93,7 +93,7 @@ class SpellChecker:
"deadzone",
"deconstruct",
"defocus",
"denoise",
"denoise", "denoising",
"deselect", "deselecting", "deselection",
"despill", "despilling",
"dirtree",
@ -439,6 +439,7 @@ class SpellChecker:
"editmode",
"fcurve", "fcurves",
"fedge", "fedges",
"filmic",
"fluidsim",
"frameserver",
"freestyle",

View File

@ -338,19 +338,19 @@ class SEQUENCER_MT_add(Menu):
if len(bpy.data.scenes) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("sequencer.scene_strip_add", text="Scene...")
layout.operator("sequencer.scene_strip_add", text="Scene")
else:
layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene...")
if len(bpy.data.movieclips) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("sequencer.movieclip_strip_add", text="Clips...")
layout.operator("sequencer.movieclip_strip_add", text="Clips")
else:
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip...")
if len(bpy.data.masks) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("sequencer.mask_strip_add", text="Masks...")
layout.operator("sequencer.mask_strip_add", text="Masks")
else:
layout.operator_menu_enum("sequencer.mask_strip_add", "mask", text="Mask...")
@ -362,7 +362,7 @@ class SEQUENCER_MT_add(Menu):
class SEQUENCER_MT_add_effect(Menu):
bl_label = "Effect Strip..."
bl_label = "Effect Strip"
def draw(self, context):
layout = self.layout

View File

@ -47,8 +47,8 @@ struct AlembicExportParams {
double frame_start;
double frame_end;
double frame_step_xform;
double frame_step_shape;
unsigned int frame_samples_xform;
unsigned int frame_samples_shape;
double shutter_open;
double shutter_close;

View File

@ -72,8 +72,8 @@ ExportSettings::ExportSettings()
, renderable_only(false)
, frame_start(1)
, frame_end(1)
, frame_step_xform(1)
, frame_step_shape(1)
, frame_samples_xform(1)
, frame_samples_shape(1)
, shutter_open(0.0)
, shutter_close(1.0)
, global_scale(1.0f)
@ -189,60 +189,56 @@ AbcExporter::~AbcExporter()
delete m_writer;
}
void AbcExporter::getShutterSamples(double step, bool time_relative,
void AbcExporter::getShutterSamples(unsigned int nr_of_samples,
bool time_relative,
std::vector<double> &samples)
{
Scene *scene = m_scene; /* for use in the FPS macro */
samples.clear();
const double time_factor = time_relative ? m_scene->r.frs_sec : 1.0;
const double shutter_open = m_settings.shutter_open;
const double shutter_close = m_settings.shutter_close;
unsigned int frame_offset = time_relative ? m_settings.frame_start : 0;
double time_factor = time_relative ? FPS : 1.0;
double shutter_open = m_settings.shutter_open;
double shutter_close = m_settings.shutter_close;
double time_inc = (shutter_close - shutter_open) / nr_of_samples;
/* sample all frame */
if (shutter_open == 0.0 && shutter_close == 1.0) {
for (double t = 0.0; t < 1.0; t += step) {
samples.push_back((t + m_settings.frame_start) / time_factor);
}
}
else {
/* sample between shutter open & close */
const int nsamples = static_cast<int>(std::max((1.0 / step) - 1.0, 1.0));
const double time_inc = (shutter_close - shutter_open) / nsamples;
/* sample between shutter open & close */
for (int sample=0; sample < nr_of_samples; ++sample) {
double sample_time = shutter_open + time_inc * sample;
double time = (frame_offset + sample_time) / time_factor;
for (double t = shutter_open; t <= shutter_close; t += time_inc) {
samples.push_back((t + m_settings.frame_start) / time_factor);
}
samples.push_back(time);
}
}
Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step)
{
TimeSamplingPtr time_sampling;
std::vector<double> samples;
if (m_settings.frame_start == m_settings.frame_end) {
time_sampling.reset(new Alembic::Abc::TimeSampling());
return time_sampling;
return TimeSamplingPtr(new Alembic::Abc::TimeSampling());
}
getShutterSamples(step, true, samples);
Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / m_scene->r.frs_sec);
time_sampling.reset(new Alembic::Abc::TimeSampling(ts, samples));
Alembic::Abc::TimeSamplingType ts(
static_cast<uint32_t>(samples.size()),
1.0 / m_scene->r.frs_sec);
return time_sampling;
return TimeSamplingPtr(new Alembic::Abc::TimeSampling(ts, samples));
}
void AbcExporter::getFrameSet(double step, std::set<double> &frames)
void AbcExporter::getFrameSet(unsigned int nr_of_samples,
std::set<double> &frames)
{
frames.clear();
std::vector<double> shutter_samples;
getShutterSamples(step, false, shutter_samples);
getShutterSamples(nr_of_samples, false, shutter_samples);
for (double frame = m_settings.frame_start; frame <= m_settings.frame_end; frame += 1.0) {
for (int j = 0, e = shutter_samples.size(); j < e; ++j) {
for (size_t j = 0; j < nr_of_samples; ++j) {
frames.insert(frame + shutter_samples[j]);
}
}
@ -274,20 +270,20 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
/* Create time samplings for transforms and shapes. */
TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform);
TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_samples_xform);
m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time);
TimeSamplingPtr shape_time;
if ((m_settings.frame_step_shape == m_settings.frame_step_xform) ||
if ((m_settings.frame_samples_shape == m_settings.frame_samples_xform) ||
(m_settings.frame_start == m_settings.frame_end))
{
shape_time = trans_time;
m_shape_sampling_index = m_trans_sampling_index;
}
else {
shape_time = createTimeSampling(m_settings.frame_step_shape);
shape_time = createTimeSampling(m_settings.frame_samples_shape);
m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time);
}
@ -299,13 +295,12 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
/* Make a list of frames to export. */
std::set<double> xform_frames;
getFrameSet(m_settings.frame_step_xform, xform_frames);
getFrameSet(m_settings.frame_samples_xform, xform_frames);
std::set<double> shape_frames;
getFrameSet(m_settings.frame_step_shape, shape_frames);
getFrameSet(m_settings.frame_samples_shape, shape_frames);
/* Merge all frames needed. */
std::set<double> frames(xform_frames);
frames.insert(shape_frames.begin(), shape_frames.end());
@ -328,7 +323,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
const double frame = *begin;
/* 'frame' is offset by start frame, so need to cancel the offset. */
setCurrentFrame(bmain, frame - m_settings.frame_start);
setCurrentFrame(bmain, frame);
if (shape_frames.count(frame) != 0) {
for (int i = 0, e = m_shapes.size(); i != e; ++i) {

View File

@ -53,8 +53,8 @@ struct ExportSettings {
bool renderable_only;
double frame_start, frame_end;
double frame_step_xform;
double frame_step_shape;
double frame_samples_xform;
double frame_samples_shape;
double shutter_open;
double shutter_close;
float global_scale;
@ -106,13 +106,15 @@ public:
void operator()(Main *bmain, float &progress, bool &was_canceled);
protected:
void getShutterSamples(unsigned int nr_of_samples,
bool time_relative,
std::vector<double> &samples);
void getFrameSet(unsigned int nr_of_samples, std::set<double> &frames);
private:
void getShutterSamples(double step, bool time_relative, std::vector<double> &samples);
Alembic::Abc::TimeSamplingPtr createTimeSampling(double step);
void getFrameSet(double step, std::set<double> &frames);
void createTransformWritersHierarchy(EvaluationContext *eval_ctx);
AbcTransformWriter * createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
void exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent);

View File

@ -108,6 +108,7 @@ void AbcTransformWriter::do_write()
scale_m4_fl(scale_mat, m_settings.global_scale);
scale_mat[3][3] = m_settings.global_scale; /* also scale translation */
mul_m4_m4m4(yup_mat, yup_mat, scale_mat);
yup_mat[3][3] /= m_settings.global_scale; /* normalise the homogeneous component */
}
m_matrix = convert_matrix(yup_mat);

View File

@ -341,8 +341,8 @@ bool ABC_export(
job->settings.frame_start = params->frame_start;
job->settings.frame_end = params->frame_end;
job->settings.frame_step_xform = params->frame_step_xform;
job->settings.frame_step_shape = params->frame_step_shape;
job->settings.frame_samples_xform = params->frame_samples_xform;
job->settings.frame_samples_shape = params->frame_samples_shape;
job->settings.shutter_open = params->shutter_open;
job->settings.shutter_close = params->shutter_close;
@ -976,7 +976,9 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader,
return NULL;
}
ISampleSelector sample_sel(time);
/* kFloorIndex is used to be compatible with non-interpolating
* properties; they use the floor. */
ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex);
return abc_reader->read_derivedmesh(dm, sample_sel, read_flag, err_str);
}

View File

@ -144,6 +144,8 @@ void BKE_texture_get_value(
const struct Scene *scene, struct Tex *texture,
float *tex_co, struct TexResult *texres, bool use_color_management);
void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool);
#ifdef __cplusplus
}
#endif

View File

@ -2125,6 +2125,8 @@ static void mesh_calc_modifiers(
DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL);
append_mask |= CD_MASK_PREVIEW_MLOOPCOL;
}
dm->deformedOnly = false;
}
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
@ -2465,6 +2467,8 @@ static void editbmesh_calc_modifiers(
deformedVerts = NULL;
}
}
dm->deformedOnly = false;
}
/* In case of active preview modifier, make sure preview mask remains for following modifiers. */

View File

@ -695,4 +695,8 @@ void BKE_pose_eval_proxy_copy(struct EvaluationContext *UNUSED(eval_ctx), Object
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
}
/* Rest of operations are NO-OP in depsgraph, so can clear
* flag now.
*/
ob->recalc &= ~OB_RECALC_ALL;
}

View File

@ -1897,8 +1897,8 @@ static DerivedMesh *dynamicPaint_Modifier_apply(
/* apply weights into a vertex group, if doesnt exists add a new layer */
if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) {
dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
NULL, sData->total_points, surface->output_name);
dvert = CustomData_add_layer(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
NULL, sData->total_points);
}
if (defgrp_index != -1 && dvert) {
int i;

View File

@ -62,6 +62,7 @@
#include "BLI_blenlib.h"
#include "BLI_math_vector.h"
#include "BLI_mempool.h"
#include "BLI_threads.h"
#include "BLI_timecode.h" /* for stamp timecode format */
#include "BLI_utildefines.h"
@ -4132,33 +4133,32 @@ typedef struct ImagePoolEntry {
typedef struct ImagePool {
ListBase image_buffers;
BLI_mempool *memory_pool;
} ImagePool;
ImagePool *BKE_image_pool_new(void)
{
ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolEntry), 0, 128, BLI_MEMPOOL_NOP);
return pool;
}
void BKE_image_pool_free(ImagePool *pool)
{
ImagePoolEntry *entry, *next_entry;
/* use single lock to dereference all the image buffers */
/* Use single lock to dereference all the image buffers. */
BLI_spin_lock(&image_spin);
for (entry = pool->image_buffers.first; entry; entry = next_entry) {
next_entry = entry->next;
if (entry->ibuf)
for (ImagePoolEntry *entry = pool->image_buffers.first;
entry != NULL;
entry = entry->next)
{
if (entry->ibuf) {
IMB_freeImBuf(entry->ibuf);
MEM_freeN(entry);
}
}
BLI_spin_unlock(&image_spin);
BLI_mempool_destroy(pool->memory_pool);
MEM_freeN(pool);
}
@ -4210,7 +4210,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
ibuf = image_acquire_ibuf(ima, iuser, NULL);
entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry");
entry = BLI_mempool_alloc(pool->memory_pool);
entry->image = ima;
entry->frame = frame;
entry->index = index;

View File

@ -4192,9 +4192,10 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha
if (free_imbuf) {
if (ibuf_change) {
if (seq->type == SEQ_TYPE_MOVIE)
if (seq->type == SEQ_TYPE_MOVIE) {
BKE_sequence_free_anim(seq);
if (seq->type == SEQ_TYPE_SPEED) {
}
else if (seq->type == SEQ_TYPE_SPEED) {
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
}
}

View File

@ -1519,3 +1519,33 @@ void BKE_texture_get_value(
{
BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
}
static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) {
Image *image = (Image *)node->id;
BKE_image_pool_acquire_ibuf(image, NULL, pool);
}
else if (node->type == NODE_GROUP && node->id != NULL) {
/* TODO(sergey): Do we need to control recursion here? */
bNodeTree *nested_tree = (bNodeTree *)node->id;
texture_nodes_fetch_images_for_pool(nested_tree, pool);
}
}
}
/* Make sure all images used by texture are loaded into pool. */
void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool)
{
if (texture->nodetree != NULL) {
texture_nodes_fetch_images_for_pool(texture->nodetree, pool);
}
else {
if (texture->type == TEX_IMAGE) {
if (texture->ima != NULL) {
BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool);
}
}
}
}

View File

@ -168,6 +168,8 @@ unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr);
unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr);
bool BLI_ghashutil_intcmp(const void *a, const void *b);
size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b);
unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4(key) ( \
@ -295,6 +297,25 @@ double BLI_ghash_calc_quality(GHash *gh);
double BLI_gset_calc_quality(GSet *gs);
#endif /* GHASH_INTERNAL_API */
#define GHASH_FOREACH_BEGIN(type, var, what) \
do { \
GHashIterator gh_iter##var; \
GHASH_ITER(gh_iter##var, what) { \
type var = (type)(BLI_ghashIterator_getValue(&gh_iter##var)); \
#define GHASH_FOREACH_END() \
} \
} while(0)
#define GSET_FOREACH_BEGIN(type, var, what) \
do { \
GSetIterator gh_iter##var; \
GSET_ITER(gh_iter##var, what) { \
type var = (type)(BLI_gsetIterator_getKey(&gh_iter##var));
#define GSET_FOREACH_END() \
} \
} while(0)
#ifdef __cplusplus
}

View File

@ -126,6 +126,11 @@ if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \
(lb_iter != lb_init)); \
}
#define LINKLIST_FOREACH(type, var, list) \
for (type var = (type)((list)->first); \
var != NULL; \
var = (type)(((Link*)(var))->next))
#ifdef __cplusplus
}
#endif

View File

@ -106,6 +106,13 @@ void *BLI_task_pool_userdata(TaskPool *pool);
/* optional mutex to use from run function */
ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
/* Delayed push, use that to reduce thread overhead by accumulating
* all new tasks into local queue first and pushing it to scheduler
* from within a single mutex lock.
*/
void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id);
void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id);
/* Parallel for routines */
typedef void (*TaskParallelRangeFunc)(void *userdata, const int iter);
typedef void (*TaskParallelRangeFuncEx)(void *userdata, void *userdata_chunk, const int iter, const int thread_id);

View File

@ -1225,6 +1225,11 @@ bool BLI_ghashutil_intcmp(const void *a, const void *b)
return (a != b);
}
size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
{
return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
}
/**
* This function implements the widely used "djb" hash apparently posted
* by Daniel Bernstein to comp.lang.c some time ago. The 32 bit

View File

@ -52,7 +52,14 @@
*
* This allows thread to fetch next task without locking the whole queue.
*/
#define LOCALQUEUE_SIZE 1
#define LOCAL_QUEUE_SIZE 1
/* Number of tasks which are allowed to be scheduled in a delayed manner.
*
* This allows to use less locks per graph node children schedule. More details
* could be found at TaskThreadLocalStorage::do_delayed_push.
*/
#define DELAYED_QUEUE_SIZE 4096
#ifndef NDEBUG
# define ASSERT_THREAD_ID(scheduler, thread_id) \
@ -129,9 +136,28 @@ typedef struct TaskMemPoolStats {
#endif
typedef struct TaskThreadLocalStorage {
/* Memory pool for faster task allocation.
* The idea is to re-use memory of finished/discarded tasks by this thread.
*/
TaskMemPool task_mempool;
/* Local queue keeps thread alive by keeping small amount of tasks ready
* to be picked up without causing global thread locks for synchronization.
*/
int num_local_queue;
Task *local_queue[LOCALQUEUE_SIZE];
Task *local_queue[LOCAL_QUEUE_SIZE];
/* Thread can be marked for delayed tasks push. This is helpful when it's
* know that lots of subsequent task pushed will happen from the same thread
* without "interrupting" for task execution.
*
* We try to accumulate as much tasks as possible in a local queue without
* any locks first, and then we push all of them into a scheduler's queue
* from within a single mutex lock.
*/
bool do_delayed_push;
int num_delayed_queue;
Task *delayed_queue[DELAYED_QUEUE_SIZE];
} TaskThreadLocalStorage;
struct TaskPool {
@ -378,6 +404,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
const int thread_id)
{
BLI_assert(!tls->do_delayed_push);
while (tls->num_local_queue > 0) {
/* We pop task from queue before handling it so handler of the task can
* push next job to the local queue.
@ -391,6 +418,7 @@ BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
local_task->run(local_pool, local_task->taskdata, thread_id);
task_free(local_pool, local_task, thread_id);
}
BLI_assert(!tls->do_delayed_push);
}
static void *task_scheduler_thread_run(void *thread_p)
@ -408,7 +436,9 @@ static void *task_scheduler_thread_run(void *thread_p)
TaskPool *pool = task->pool;
/* run task */
BLI_assert(!tls->do_delayed_push);
task->run(pool, task->taskdata, thread_id);
BLI_assert(!tls->do_delayed_push);
/* delete task */
task_free(pool, task, thread_id);
@ -547,6 +577,27 @@ static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriori
BLI_mutex_unlock(&scheduler->queue_mutex);
}
static void task_scheduler_push_all(TaskScheduler *scheduler,
TaskPool *pool,
Task **tasks,
int num_tasks)
{
if (num_tasks == 0) {
return;
}
task_pool_num_increase(pool, num_tasks);
BLI_mutex_lock(&scheduler->queue_mutex);
for (int i = 0; i < num_tasks; i++) {
BLI_addhead(&scheduler->queue, tasks[i]);
}
BLI_condition_notify_all(&scheduler->queue_cond);
BLI_mutex_unlock(&scheduler->queue_mutex);
}
static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
{
Task *task, *nexttask;
@ -714,38 +765,59 @@ void BLI_task_pool_free(TaskPool *pool)
BLI_end_threaded_malloc();
}
BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id)
{
return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work));
}
static void task_pool_push(
TaskPool *pool, TaskRunFunction run, void *taskdata,
bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority,
int thread_id)
{
/* Allocate task and fill it's properties. */
Task *task = task_alloc(pool, thread_id);
task->run = run;
task->taskdata = taskdata;
task->free_taskdata = free_taskdata;
task->freedata = freedata;
task->pool = pool;
/* For suspended pools we put everything yo a global queue first
* and exit as soon as possible.
*
* This tasks will be moved to actual execution when pool is
* activated by work_and_wait().
*/
if (pool->is_suspended) {
BLI_addhead(&pool->suspended_queue, task);
atomic_fetch_and_add_z(&pool->num_suspended, 1);
return;
}
if (thread_id != -1 &&
(thread_id != pool->thread_id || pool->do_work))
{
/* Populate to any local queue first, this is cheapest push ever. */
if (task_can_use_local_queues(pool, thread_id)) {
ASSERT_THREAD_ID(pool->scheduler, thread_id);
TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
if (tls->num_local_queue < LOCALQUEUE_SIZE) {
/* Try to push to a local execution queue.
* These tasks will be picked up next.
*/
if (tls->num_local_queue < LOCAL_QUEUE_SIZE) {
tls->local_queue[tls->num_local_queue] = task;
tls->num_local_queue++;
return;
}
/* If we are in the delayed tasks push mode, we push tasks to a
* temporary local queue first without any locks, and then move them
* to global execution queue with a single lock.
*/
if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) {
tls->delayed_queue[tls->num_delayed_queue] = task;
tls->num_delayed_queue++;
return;
}
}
/* Do push to a global execution ppol, slowest possible method,
* causes quite reasonable amount of threading overhead.
*/
task_scheduler_push(pool->scheduler, task, priority);
}
@ -816,7 +888,9 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* if found task, do it, otherwise wait until other tasks are done */
if (found_task) {
/* run task */
BLI_assert(!tls->do_delayed_push);
work_task->run(pool, work_task->taskdata, pool->thread_id);
BLI_assert(!tls->do_delayed_push);
/* delete task */
task_free(pool, task, pool->thread_id);
@ -871,6 +945,30 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
return &pool->user_mutex;
}
void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id)
{
if (task_can_use_local_queues(pool, thread_id)) {
ASSERT_THREAD_ID(pool->scheduler, thread_id);
TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
tls->do_delayed_push = true;
}
}
void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id)
{
if (task_can_use_local_queues(pool, thread_id)) {
ASSERT_THREAD_ID(pool->scheduler, thread_id);
TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
BLI_assert(tls->do_delayed_push);
task_scheduler_push_all(pool->scheduler,
pool,
tls->delayed_queue,
tls->num_delayed_queue);
tls->do_delayed_push = false;
tls->num_delayed_queue = 0;
}
}
/* Parallel range routines */
/**

View File

@ -205,6 +205,15 @@ static int bev_debug_flags = 0;
#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
/* Are d1 and d2 parallel or nearly so? */
static bool nearly_parallel(const float d1[3], const float d2[3])
{
float ang;
ang = angle_v3v3(d1, d2);
return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - M_PI) < BEVEL_EPSILON_ANG);
}
/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
@ -1059,7 +1068,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
EdgeHalf *e;
Profile *pro;
float co1[3], co2[3], co3[3], d1[3], d2[3], l;
float co1[3], co2[3], co3[3], d1[3], d2[3];
bool do_linear_interp;
copy_v3_v3(co1, bndv->nv.co);
@ -1097,8 +1106,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
normalize_v3(d1);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
l = normalize_v3(pro->plane_no);
if (l <= BEVEL_EPSILON_BIG) {
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
/* co1 - midco -co2 are collinear.
* Should be case that beveled edge is coplanar with two boundary verts.
* We want to move the profile to that common plane, if possible.
@ -1130,17 +1139,24 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co);
normalize_v3(d3);
normalize_v3(d4);
add_v3_v3v3(co3, co1, d3);
add_v3_v3v3(co4, co2, d4);
isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
if (isect_kind != 0) {
copy_v3_v3(pro->midco, meetco);
}
else {
if (nearly_parallel(d3, d4)) {
/* offset lines are collinear - want linear interpolation */
mid_v3_v3v3(pro->midco, co1, co2);
do_linear_interp = true;
}
else {
add_v3_v3v3(co3, co1, d3);
add_v3_v3v3(co4, co2, d4);
isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
if (isect_kind != 0) {
copy_v3_v3(pro->midco, meetco);
}
else {
/* offset lines don't intersect - want linear interpolation */
mid_v3_v3v3(pro->midco, co1, co2);
do_linear_interp = true;
}
}
}
}
copy_v3_v3(pro->cob, co2);
@ -1149,8 +1165,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
sub_v3_v3v3(d2, pro->midco, co2);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
l = normalize_v3(pro->plane_no);
if (l <= BEVEL_EPSILON_BIG) {
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
/* whole profile is collinear with edge: just interpolate */
do_linear_interp = true;
}

View File

@ -90,7 +90,6 @@ set(SRC
intern/depsgraph_types.h
util/deg_util_function.h
util/deg_util_hash.h
)
if(WITH_CXX11)

View File

@ -30,9 +30,6 @@
#include "intern/builder/deg_builder.h"
// TODO(sergey): Use own wrapper over STD.
#include <stack>
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_ID.h"
@ -40,6 +37,10 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
extern "C" {
#include "BLI_stack.h"
}
#include "intern/depsgraph.h"
#include "intern/depsgraph_types.h"
#include "intern/nodes/deg_node.h"

View File

@ -32,10 +32,10 @@
// TOO(sergey): Use some wrappers over those?
#include <cstdio>
#include <cstdlib>
#include <stack>
extern "C" {
#include "BLI_utildefines.h"
#include "BLI_stack.h"
}
#include "util/deg_util_foreach.h"
@ -48,12 +48,6 @@ extern "C" {
namespace DEG {
struct StackEntry {
OperationDepsNode *node;
StackEntry *from;
DepsRelation *via_relation;
};
void deg_graph_detect_cycles(Depsgraph *graph)
{
enum {
@ -65,7 +59,15 @@ void deg_graph_detect_cycles(Depsgraph *graph)
NODE_IN_STACK = 2,
};
std::stack<StackEntry> traversal_stack;
struct StackEntry {
OperationDepsNode *node;
StackEntry *from;
DepsRelation *via_relation;
};
BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry),
"DEG detect cycles stack");
foreach (OperationDepsNode *node, graph->operations) {
bool has_inlinks = false;
foreach (DepsRelation *rel, node->inlinks) {
@ -78,7 +80,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
entry.node = node;
entry.from = NULL;
entry.via_relation = NULL;
traversal_stack.push(entry);
BLI_stack_push(traversal_stack, &entry);
node->tag = NODE_IN_STACK;
}
else {
@ -87,9 +89,9 @@ void deg_graph_detect_cycles(Depsgraph *graph)
node->done = 0;
}
while (!traversal_stack.empty()) {
StackEntry& entry = traversal_stack.top();
OperationDepsNode *node = entry.node;
while (!BLI_stack_is_empty(traversal_stack)) {
StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
OperationDepsNode *node = entry->node;
bool all_child_traversed = true;
for (int i = node->done; i < node->outlinks.size(); ++i) {
DepsRelation *rel = node->outlinks[i];
@ -102,7 +104,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
node->full_identifier().c_str(),
rel->name);
StackEntry *current = &entry;
StackEntry *current = entry;
while (current->node != to) {
BLI_assert(current != NULL);
printf(" '%s' depends on '%s' through '%s'\n",
@ -117,9 +119,9 @@ void deg_graph_detect_cycles(Depsgraph *graph)
else if (to->tag == NODE_NOT_VISITED) {
StackEntry new_entry;
new_entry.node = to;
new_entry.from = &entry;
new_entry.from = entry;
new_entry.via_relation = rel;
traversal_stack.push(new_entry);
BLI_stack_push(traversal_stack, &new_entry);
to->tag = NODE_IN_STACK;
all_child_traversed = false;
node->done = i;
@ -129,9 +131,11 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
if (all_child_traversed) {
node->tag = NODE_VISITED;
traversal_stack.pop();
BLI_stack_discard(traversal_stack);
}
}
BLI_stack_free(traversal_stack);
}
} // namespace DEG

View File

@ -412,7 +412,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob)
BuilderWalkUserData data;
data.builder = this;
data.scene = scene;
modifiers_foreachObjectLink(ob, modifier_walk, &data);
BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
}

View File

@ -113,6 +113,41 @@ extern "C" {
namespace DEG {
namespace {
struct BuilderWalkUserData {
DepsgraphRelationBuilder *builder;
Main *bmain;
Scene *scene;
};
static void modifier_walk(void *user_data,
struct Object * /*ob*/,
struct Object **obpoin,
int /*cb_flag*/)
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*obpoin) {
data->builder->build_object(data->bmain, data->scene, *obpoin);
}
}
void constraint_walk(bConstraint * /*con*/,
ID **idpoin,
bool /*is_reference*/,
void *user_data)
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*idpoin) {
ID *id = *idpoin;
if (GS(id->name) == ID_OB) {
data->builder->build_object(data->bmain, data->scene, (Object *)id);
}
}
}
} /* namespace */
/* ***************** */
/* Relations Builder */
@ -407,6 +442,21 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
"[ObLocal -> ObParent]");
}
if (ob->modifiers.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
data.bmain = bmain;
data.scene = scene;
modifiers_foreachObjectLink(ob, modifier_walk, &data);
}
if (ob->constraints.first != NULL) {
BuilderWalkUserData data;
data.builder = this;
data.bmain = bmain;
data.scene = scene;
BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
}
/* object constraints */
if (ob->constraints.first != NULL) {
OperationKey constraint_key(&ob->id,

View File

@ -43,6 +43,7 @@ extern "C" {
#include "DNA_windowmanager_types.h"
#include "BLI_task.h"
#include "BLI_listbase.h"
#include "BKE_idcode.h"
#include "BKE_library.h"

View File

@ -123,7 +123,9 @@ static void deg_task_run_func(TaskPool *pool,
#endif
}
BLI_task_pool_delayed_push_begin(pool, thread_id);
schedule_children(pool, state->graph, node, thread_id);
BLI_task_pool_delayed_push_end(pool, thread_id);
}
typedef struct CalculatePengindData {

View File

@ -164,14 +164,33 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
* Plus it ensures visibility changes and relations and
* layers visibility update has proper flags to work with.
*/
if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
object->recalc |= OB_RECALC_TIME;
}
else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
object->recalc |= OB_RECALC_OB;
}
else {
object->recalc |= OB_RECALC_DATA;
switch (comp_node->type) {
case DEPSNODE_TYPE_UNDEFINED:
case DEPSNODE_TYPE_OPERATION:
case DEPSNODE_TYPE_ROOT:
case DEPSNODE_TYPE_TIMESOURCE:
case DEPSNODE_TYPE_ID_REF:
case DEPSNODE_TYPE_SUBGRAPH:
case DEPSNODE_TYPE_PARAMETERS:
case DEPSNODE_TYPE_SEQUENCER:
case DEPSNODE_TYPE_LAYER_COLLECTIONS:
/* Ignore, does not translate to object component. */
break;
case DEPSNODE_TYPE_ANIMATION:
object->recalc |= OB_RECALC_TIME;
break;
case DEPSNODE_TYPE_TRANSFORM:
object->recalc |= OB_RECALC_OB;
break;
case DEPSNODE_TYPE_GEOMETRY:
case DEPSNODE_TYPE_EVAL_POSE:
case DEPSNODE_TYPE_BONE:
case DEPSNODE_TYPE_EVAL_PARTICLES:
case DEPSNODE_TYPE_SHADING:
case DEPSNODE_TYPE_CACHE:
case DEPSNODE_TYPE_PROXY:
object->recalc |= OB_RECALC_DATA;
break;
}
}
}

View File

@ -49,7 +49,6 @@ extern "C" {
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
#include "util/deg_util_hash.h"
namespace DEG {
@ -158,8 +157,8 @@ static unsigned int id_deps_node_hash_key(const void *key_v)
{
const IDDepsNode::ComponentIDKey *key =
reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
return hash_combine(BLI_ghashutil_uinthash(key->type),
BLI_ghashutil_strhash_p(key->name));
return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->type),
BLI_ghashutil_strhash_p(key->name));
}
static bool id_deps_node_hash_key_cmp(const void *a, const void *b)

View File

@ -35,6 +35,7 @@
extern "C" {
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "DNA_object_types.h"
@ -44,7 +45,6 @@ extern "C" {
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
#include "util/deg_util_hash.h"
namespace DEG {
@ -95,8 +95,8 @@ static unsigned int comp_node_hash_key(const void *key_v)
{
const ComponentDepsNode::OperationIDKey *key =
reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v);
return hash_combine(BLI_ghashutil_uinthash(key->opcode),
BLI_ghashutil_strhash_p(key->name));
return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->opcode),
BLI_ghashutil_strhash_p(key->name));
}
static bool comp_node_hash_key_cmp(const void *a, const void *b)

View File

@ -32,13 +32,11 @@
#include "MEM_guardedalloc.h"
extern "C" {
#include "BLI_utildefines.h"
} /* extern "C" */
#include "BLI_ghash.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_hash.h"
namespace DEG {

View File

@ -38,28 +38,3 @@
#else
# error "Depsgraph requires either Boost or C++11 for range-based loops."
#endif
#define GHASH_FOREACH_BEGIN(type, var, what) \
do { \
GHashIterator gh_iter##var; \
GHASH_ITER(gh_iter##var, what) { \
type var = reinterpret_cast<type>(BLI_ghashIterator_getValue(&gh_iter##var)); \
#define GHASH_FOREACH_END() \
} \
} while(0)
#define GSET_FOREACH_BEGIN(type, var, what) \
do { \
GSetIterator gh_iter##var; \
GSET_ITER(gh_iter##var, what) { \
type var = reinterpret_cast<type>(BLI_gsetIterator_getKey(&gh_iter##var)); \
#define GSET_FOREACH_END() \
} \
} while(0)
#define LINKLIST_FOREACH(type, var, list) \
for (type var = (type)((list)->first); \
var != NULL; \
var = (type)(((Link*)(var))->next))

View File

@ -1,41 +0,0 @@
/*
* ***** 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) 2014 Blender Foundation.
* All rights reserved.
*
* Original Author: Brecht van Lommel
* Contributor(s): Lukas Toenne
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/depsgraph/util/deg_util_hash.h
* \ingroup depsgraph
*/
#pragma once
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */
BLI_INLINE size_t hash_combine(size_t hash_a, size_t hash_b)
{
return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
}

View File

@ -748,10 +748,10 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Blank Frame";
ot->name = "Insert Blank Frame";
ot->idname = "GPENCIL_OT_blank_frame_add";
ot->description = "Add a new frame with nothing in it on the current frame. "
"If there is already a frame, all existing frames are shifted one frame later";
ot->description = "Inserts a blank frame on the current frame "
"(all subsequently existing frames, if any, are shifted right by one frame)";
/* callbacks */
ot->exec = gp_blank_frame_add_exec;

View File

@ -102,12 +102,12 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
char filename[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filename);
const struct AlembicExportParams params = {
struct AlembicExportParams params = {
.frame_start = RNA_int_get(op->ptr, "start"),
.frame_end = RNA_int_get(op->ptr, "end"),
.frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"),
.frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"),
.frame_samples_xform = RNA_int_get(op->ptr, "xsamples"),
.frame_samples_shape = RNA_int_get(op->ptr, "gsamples"),
.shutter_open = RNA_float_get(op->ptr, "sh_open"),
.shutter_close = RNA_float_get(op->ptr, "sh_close"),
@ -133,8 +133,17 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.global_scale = RNA_float_get(op->ptr, "global_scale"),
};
/* Take some defaults from the scene, if not specified explicitly. */
Scene *scene = CTX_data_scene(C);
if (params.frame_start == INT_MIN) {
params.frame_start = SFRA;
}
if (params.frame_end == INT_MIN) {
params.frame_end = EFRA;
}
const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
bool ok = ABC_export(CTX_data_scene(C), C, filename, &params, as_background_job);
bool ok = ABC_export(scene, C, filename, &params, as_background_job);
return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@ -295,11 +304,17 @@ void WM_OT_alembic_export(wmOperatorType *ot)
FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX,
"Start Frame", "Start Frame", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "start", INT_MIN, INT_MIN, INT_MAX,
"Start Frame",
"Start frame of the export, use the default value to "
"take the start frame of the current scene",
INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX,
"End Frame", "End Frame", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "end", INT_MIN, INT_MIN, INT_MAX,
"End Frame",
"End frame of the export, use the default value to "
"take the end frame of the current scene",
INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "xsamples", 1, 1, 128,
"Transform Samples", "Number of times per frame transformations are sampled", 1, 128);

View File

@ -51,6 +51,7 @@
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_modifier.h"
@ -414,22 +415,18 @@ static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports)
}
}
else {
if (ob->mat[i]) {
BKE_reportf(reports, RPT_ERROR,
Material *mat = give_current_material(ob, i);
if (mat != NULL) {
BKE_reportf(reports, RPT_INFO,
"No active image found in material \"%s\" (%d) for object \"%s\"",
ob->mat[i]->id.name + 2, i, ob->id.name + 2);
}
else if (((Mesh *) ob->data)->mat[i]) {
BKE_reportf(reports, RPT_ERROR,
"No active image found in material \"%s\" (%d) for object \"%s\"",
((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2);
mat->id.name + 2, i, ob->id.name + 2);
}
else {
BKE_reportf(reports, RPT_ERROR,
"No active image found in material (%d) for object \"%s\"",
BKE_reportf(reports, RPT_INFO,
"No active image found in material slot (%d) for object \"%s\"",
i, ob->id.name + 2);
}
return false;
continue;
}
image->id.tag |= LIB_TAG_DOIT;
@ -569,7 +566,11 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
if ((image->id.tag & LIB_TAG_DOIT)) {
/* Some materials have no image, we just ignore those cases. */
if (image == NULL) {
bake_images->lookup[i] = -1;
}
else if (image->id.tag & LIB_TAG_DOIT) {
for (j = 0; j < i; j++) {
if (bake_images->data[j].image == image) {
bake_images->lookup[i] = j;

View File

@ -85,6 +85,7 @@
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_sca.h"
@ -2006,6 +2007,18 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
single_tex_users_expand(bmain);
}
/* Relink nodetrees' pointers that have been duplicated. */
FOREACH_NODETREE(bmain, ntree, id)
{
/* This is a bit convoluted, we want to root ntree of copied IDs and only those,
* so we first check that old ID has been copied and that ntree is root tree of old ID,
* then get root tree of new ID and remap its pointers to new ID... */
if (id->newid && (&ntree->id != id)) {
ntree = ntreeFromID(id->newid);
BKE_libblock_relink_to_newid(&ntree->id);
}
} FOREACH_NODETREE_END
/* Relink datablock pointer properties */
{
IDP_RelinkProperty(scene->id.properties);

View File

@ -345,7 +345,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf == NULL) {
if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) {
BKE_image_release_ibuf(ima, ibuf, lock);
return OPERATOR_CANCELLED;
}

View File

@ -429,6 +429,13 @@ static void object_delete_cb(
tselem->id = NULL;
#endif
}
else {
/* No base, means object is no more instantiated in any scene.
* Should not happen ideally, but does happens, see T51625.
* Rather than twisting in all kind of ways to address all possible cases leading to that situation, simpler
* to allow deleting such object as a mere generic data-block. */
WM_operator_name_call(C, "OUTLINER_OT_id_delete", WM_OP_INVOKE_REGION_WIN, NULL);
}
}
static void id_local_cb(

View File

@ -3329,6 +3329,9 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act);
if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other);
BKE_sequence_invalidate_cache(scene, seq_act);
BKE_sequence_invalidate_cache(scene, seq_other);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;

View File

@ -177,19 +177,18 @@ unsigned int getRowLength(int width, LogImageElement logElement)
return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4;
else if (logElement.packing == 1 || logElement.packing == 2)
return ((width * logElement.depth - 1) / 3 + 1) * 4;
break;
case 12:
if (logElement.packing == 0)
return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4;
else if (logElement.packing == 1 || logElement.packing == 2)
return width * logElement.depth * 2;
break;
case 16:
return width * logElement.depth * 2;
default:
return 0;
}
return 0;
}
@ -572,20 +571,20 @@ static int logImageElementGetData(LogImageFile *logImage, LogImageElement logEle
return logImageElementGetData10Packed(logImage, logElement, data);
else if (logElement.packing == 1 || logElement.packing == 2)
return logImageElementGetData10(logImage, logElement, data);
break;
case 12:
if (logElement.packing == 0)
return logImageElementGetData12Packed(logImage, logElement, data);
else if (logElement.packing == 1 || logElement.packing == 2)
return logImageElementGetData12(logImage, logElement, data);
break;
case 16:
return logImageElementGetData16(logImage, logElement, data);
default:
/* format not supported */
return 1;
}
/* format not supported */
return 1;
}
static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data)

View File

@ -3746,7 +3746,7 @@ static const char *cpp_classes = ""
"template<typename T, TBeginFunc Tbegin, TNextFunc Tnext, TEndFunc Tend>\n"
"class CollectionIterator {\n"
"public:\n"
" CollectionIterator() : t(iter.ptr), init(false) { iter.valid = false; }\n"
" CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n"
" ~CollectionIterator(void) { if (init) Tend(&iter); };\n"
"\n"
" operator bool(void)\n"

View File

@ -71,8 +71,8 @@ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
if (description && (description)[0]) { \
int i = strlen(description); \
if (i > 3 && (description)[i - 1] == '.' && (description)[i - 3] != '.') { \
fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \
__func__, id1 ? id1 : "", id2 ? id2 : ""); \
fprintf(stderr, "%s: '%s' description from '%s' '%s' ends with a '.' !\n", \
__func__, description, id1 ? id1 : "", id2 ? id2 : ""); \
} \
} (void)0

View File

@ -185,12 +185,16 @@ static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *v
#endif
}
static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *UNUSED(ptr))
static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr)
{
#ifndef WITH_MOD_FLUID
UNUSED_VARS(ptr);
return 0;
#else
return 31;
char value[32];
rna_DomainFluidSettings_memory_estimate_get(ptr, value);
return strlen(value);
#endif
}

View File

@ -520,8 +520,9 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
* thus causing a cycle/infinite-recursion leading to crashes on load [#25298]
*/
if (BKE_group_object_exists(grp, ob) == 0) {
id_us_min(&ob->dup_group->id);
ob->dup_group = grp;
id_lib_extern((ID *)grp);
id_us_plus(&ob->dup_group->id);
}
else {
BKE_report(NULL, RPT_ERROR,

View File

@ -226,8 +226,8 @@ static void rna_Scene_alembic_export(
.frame_start = frame_start,
.frame_end = frame_end,
.frame_step_xform = 1.0 / (double)xform_samples,
.frame_step_shape = 1.0 / (double)geom_samples,
.frame_samples_xform = xform_samples,
.frame_samples_shape = geom_samples,
.shutter_open = shutter_open,
.shutter_close = shutter_close,

View File

@ -1095,7 +1095,7 @@ static void rna_def_strip_element(BlenderRNA *brna)
prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Filename", "");
RNA_def_property_ui_text(prop, "Filename", "Name of the source file");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceElement_update");
prop = RNA_def_property(srna, "orig_width", PROP_INT, PROP_NONE);
@ -1120,25 +1120,25 @@ static void rna_def_strip_crop(BlenderRNA *brna)
prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "top");
RNA_def_property_ui_text(prop, "Top", "");
RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "bottom");
RNA_def_property_ui_text(prop, "Bottom", "");
RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the buttom");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "left");
RNA_def_property_ui_text(prop, "Left", "");
RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "right");
RNA_def_property_ui_text(prop, "Right", "");
RNA_def_property_ui_text(prop, "Right", "Number of pixels to crop from the right side");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
@ -1156,13 +1156,13 @@ static void rna_def_strip_transform(BlenderRNA *brna)
prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "xofs");
RNA_def_property_ui_text(prop, "Offset X", "");
RNA_def_property_ui_text(prop, "Offset X", "Amount to move the input on the X axis within its boundaries");
RNA_def_property_ui_range(prop, -4096, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update");
prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "yofs");
RNA_def_property_ui_text(prop, "Offset Y", "");
RNA_def_property_ui_text(prop, "Offset Y", "Amount to move the input on the Y axis within its boundaries");
RNA_def_property_ui_range(prop, -4096, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update");
@ -1246,7 +1246,7 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
prop = RNA_def_property(srna, "timecode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "tc");
RNA_def_property_enum_items(prop, seq_tc_items);
RNA_def_property_ui_text(prop, "Timecode", "");
RNA_def_property_ui_text(prop, "Timecode", "Method for reading the inputs timecode");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update");
prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE);
@ -1289,17 +1289,17 @@ static void rna_def_color_balance(BlenderRNA *brna)
prop = RNA_def_property(srna, "invert_gain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAIN);
RNA_def_property_ui_text(prop, "Inverse Gain", "");
RNA_def_property_ui_text(prop, "Inverse Gain", "Invert the gain color`");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
prop = RNA_def_property(srna, "invert_gamma", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAMMA);
RNA_def_property_ui_text(prop, "Inverse Gamma", "");
RNA_def_property_ui_text(prop, "Inverse Gamma", "Invert the gamma color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
prop = RNA_def_property(srna, "invert_lift", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_LIFT);
RNA_def_property_ui_text(prop, "Inverse Lift", "");
RNA_def_property_ui_text(prop, "Inverse Lift", "Invert the lift color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
/* not yet used */
@ -1453,13 +1453,13 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MUTE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, true);
RNA_def_property_ui_text(prop, "Mute", "");
RNA_def_property_ui_text(prop, "Mute", "Disable strip so that it cannot be viewed in the output");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_mute_update");
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_LOCK);
RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true);
RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it can't be transformed");
RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it cannot be transformed");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
/* strip positioning */
@ -1481,7 +1481,7 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "start");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Start Frame", "");
RNA_def_property_ui_text(prop, "Start Frame", "X position where the strip begins");
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@ -1552,12 +1552,12 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
RNA_def_property_enum_items(prop, blend_mode_items);
RNA_def_property_ui_text(prop, "Blend Mode", "");
RNA_def_property_ui_text(prop, "Blend Mode", "Method for controlling how the strip combines with other strips");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Blend Opacity", "");
RNA_def_property_ui_text(prop, "Blend Opacity", "Percentage of how much the strip's colors affect other strips");
/* stupid 0-100 -> 0-1 */
RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@ -1566,7 +1566,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
RNA_def_property_float_sdna(prop, NULL, "effect_fader");
RNA_def_property_ui_text(prop, "Effect fader position", "");
RNA_def_property_ui_text(prop, "Effect fader position", "Custom fade value");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "use_default_fade", PROP_BOOLEAN, PROP_NONE);
@ -1714,7 +1714,7 @@ static void rna_def_filter_video(StructRNA *srna)
RNA_def_property_range(prop, 0.0f, 20.0f);
RNA_def_property_ui_range(prop, 0.0f, 2.0f, 3, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Saturation", "");
RNA_def_property_ui_text(prop, "Saturation", "Adjust the intensity of the input's color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "strobe", PROP_FLOAT, PROP_NONE);
@ -2205,13 +2205,13 @@ static void rna_def_transform(StructRNA *srna)
prop = RNA_def_property(srna, "scale_start_x", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScalexIni");
RNA_def_property_ui_text(prop, "Scale X", "");
RNA_def_property_ui_text(prop, "Scale X", "Amount to scale the input in the X axis");
RNA_def_property_ui_range(prop, 0, 10, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScaleyIni");
RNA_def_property_ui_text(prop, "Scale Y", "");
RNA_def_property_ui_text(prop, "Scale Y", "Amount to scale the input in the Y axis");
RNA_def_property_ui_range(prop, 0, 10, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@ -2222,33 +2222,33 @@ static void rna_def_transform(StructRNA *srna)
prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xIni");
RNA_def_property_ui_text(prop, "Translate X", "");
RNA_def_property_ui_text(prop, "Translate X", "Amount to move the input on the X axis");
RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yIni");
RNA_def_property_ui_text(prop, "Translate Y", "");
RNA_def_property_ui_text(prop, "Translate Y", "Amount to move the input on the Y axis");
RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rotIni");
RNA_def_property_range(prop, -360.0f, 360.0f);
RNA_def_property_ui_text(prop, "Rotation", "");
RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "translation_unit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "percent");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
RNA_def_property_enum_items(prop, translation_unit_items);
RNA_def_property_ui_text(prop, "Translation Unit", "");
RNA_def_property_ui_text(prop, "Translation Unit", "Unit of measure to translate the input");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, interpolation_items);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
RNA_def_property_ui_text(prop, "Interpolation", "");
RNA_def_property_ui_text(prop, "Interpolation", "Method to determine how missing pixels are created");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
@ -2260,7 +2260,7 @@ static void rna_def_solid_color(StructRNA *srna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "col");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_ui_text(prop, "Color", "Effect Strip color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
@ -2333,12 +2333,12 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "color");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_ui_text(prop, "Color", "Text color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "shadow_color");
RNA_def_property_ui_text(prop, "Shadow Color", "");
RNA_def_property_ui_text(prop, "Shadow Color", "Shadow color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
@ -2358,13 +2358,13 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
RNA_def_property_enum_items(prop, text_align_x_items);
RNA_def_property_ui_text(prop, "Align X", "");
RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align_y");
RNA_def_property_enum_items(prop, text_align_y_items);
RNA_def_property_ui_text(prop, "Align Y", "");
RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
@ -2512,7 +2512,7 @@ static void rna_def_colorbalance_modifier(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "color_multiply");
RNA_def_property_range(prop, 0.0f, 20.0f);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Multiply Colors", "");
RNA_def_property_ui_text(prop, "Multiply Colors", "Multiply the intensity of each pixel");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
}
@ -2576,13 +2576,13 @@ static void rna_def_brightcontrast_modifier(BlenderRNA *brna)
prop = RNA_def_property(srna, "bright", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "bright");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_text(prop, "Bright", "");
RNA_def_property_ui_text(prop, "Bright", "Adjust the luminosity of the colors");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "contrast");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_text(prop, "Contrast", "");
RNA_def_property_ui_text(prop, "Contrast", "Adjust the difference in luminosity between pixels");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
}
@ -2599,13 +2599,12 @@ static void rna_def_tonemap_modifier(BlenderRNA *brna)
srna = RNA_def_struct(brna, "SequencerTonemapModifierData", "SequenceModifier");
RNA_def_struct_sdna(srna, "SequencerTonemapModifierData");
RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData",
"Tone mapping modifier");
RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData", "Tone mapping modifier");
prop = RNA_def_property(srna, "tonemap_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, type_items);
RNA_def_property_ui_text(prop, "Tonemap Type", "");
RNA_def_property_ui_text(prop, "Tonemap Type", "Tone mapping algorithm");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
prop = RNA_def_property(srna, "key", PROP_FLOAT, PROP_FACTOR);

View File

@ -358,6 +358,7 @@ static void displaceModifier_do(
data.vert_clnors = vert_clnors;
if (dmd->texture != NULL) {
data.pool = BKE_image_pool_new();
BKE_texture_fetch_images_for_pool(dmd->texture, data.pool);
}
BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512);

View File

@ -684,6 +684,10 @@ void RE_bake_pixels_populate(
int mat_nr = mp->mat_nr;
int image_id = bake_images->lookup[mat_nr];
if (image_id < 0) {
continue;
}
bd.bk_image = &bake_images->data[image_id];
bd.primitive_id = ++p_id;

View File

@ -26,6 +26,7 @@ set(INC
..
../../../source/blender/blenlib
../../../source/blender/alembic
../../../source/blender/makesdna
${ALEMBIC_INCLUDE_DIRS}
${BOOST_INCLUDE_DIR}
${HDF5_INCLUDE_DIRS}
@ -44,8 +45,8 @@ else()
endif()
# For motivation on doubling BLENDER_SORTED_LIBS, see ../bmesh/CMakeLists.txt
BLENDER_SRC_GTEST(abc_matrix "abc_matrix_test.cc;${_buildinfo_src}" "${BLENDER_SORTED_LIBS};${BLENDER_SORTED_LIBS}")
BLENDER_SRC_GTEST(alembic "abc_matrix_test.cc;abc_export_test.cc;${_buildinfo_src}" "${BLENDER_SORTED_LIBS};${BLENDER_SORTED_LIBS}")
unset(_buildinfo_src)
setup_liblinks(abc_matrix_test)
setup_liblinks(alembic_test)

View File

@ -0,0 +1,120 @@
#include "testing/testing.h"
// Keep first since utildefines defines AT which conflicts with fucking STL
#include "intern/abc_util.h"
#include "intern/abc_exporter.h"
extern "C" {
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "DNA_scene_types.h"
}
class TestableAbcExporter : public AbcExporter {
public:
TestableAbcExporter(Scene *scene, const char *filename, ExportSettings &settings)
: AbcExporter(scene, filename, settings)
{}
void getShutterSamples(unsigned int nr_of_samples,
bool time_relative,
std::vector<double> &samples)
{
AbcExporter::getShutterSamples(nr_of_samples, time_relative, samples);
}
void getFrameSet(unsigned int nr_of_samples,
std::set<double> &frames) {
AbcExporter::getFrameSet(nr_of_samples, frames);
}
};
TEST(abc_export, TimeSamplesFullShutter) {
ExportSettings settings;
settings.frame_start = 31.0;
settings.frame_end = 223.0;
settings.shutter_open = 0.0;
settings.shutter_close = 1.0;
/* Fake a 25 FPS scene with a nonzero base (because that's sometimes forgotten) */
Scene scene;
scene.r.frs_sec = 50;
scene.r.frs_sec_base = 2;
TestableAbcExporter exporter(&scene, "somefile.abc", settings);
std::vector<double> samples;
/* test 5 samples per frame */
exporter.getShutterSamples(5, true, samples);
EXPECT_EQ(5, samples.size());
EXPECT_NEAR(1.240, samples[0], 1e-5f);
EXPECT_NEAR(1.248, samples[1], 1e-5f);
EXPECT_NEAR(1.256, samples[2], 1e-5f);
EXPECT_NEAR(1.264, samples[3], 1e-5f);
EXPECT_NEAR(1.272, samples[4], 1e-5f);
/* test same, but using frame number offset instead of time */
exporter.getShutterSamples(5, false, samples);
EXPECT_EQ(5, samples.size());
EXPECT_NEAR(0.0, samples[0], 1e-5f);
EXPECT_NEAR(0.2, samples[1], 1e-5f);
EXPECT_NEAR(0.4, samples[2], 1e-5f);
EXPECT_NEAR(0.6, samples[3], 1e-5f);
EXPECT_NEAR(0.8, samples[4], 1e-5f);
/* use the same setup to test getFrameSet() */
std::set<double> frames;
exporter.getFrameSet(5, frames);
EXPECT_EQ(965, frames.size());
EXPECT_EQ(1, frames.count(31.0));
EXPECT_EQ(1, frames.count(31.2));
EXPECT_EQ(1, frames.count(31.4));
EXPECT_EQ(1, frames.count(31.6));
EXPECT_EQ(1, frames.count(31.8));
}
TEST(abc_export, TimeSamples180degShutter) {
ExportSettings settings;
settings.frame_start = 31.0;
settings.frame_end = 223.0;
settings.shutter_open = -0.25;
settings.shutter_close = 0.25;
/* Fake a 25 FPS scene with a nonzero base (because that's sometimes forgotten) */
Scene scene;
scene.r.frs_sec = 50;
scene.r.frs_sec_base = 2;
TestableAbcExporter exporter(&scene, "somefile.abc", settings);
std::vector<double> samples;
/* test 5 samples per frame */
exporter.getShutterSamples(5, true, samples);
EXPECT_EQ(5, samples.size());
EXPECT_NEAR(1.230, samples[0], 1e-5f);
EXPECT_NEAR(1.234, samples[1], 1e-5f);
EXPECT_NEAR(1.238, samples[2], 1e-5f);
EXPECT_NEAR(1.242, samples[3], 1e-5f);
EXPECT_NEAR(1.246, samples[4], 1e-5f);
/* test same, but using frame number offset instead of time */
exporter.getShutterSamples(5, false, samples);
EXPECT_EQ(5, samples.size());
EXPECT_NEAR(-0.25, samples[0], 1e-5f);
EXPECT_NEAR(-0.15, samples[1], 1e-5f);
EXPECT_NEAR(-0.05, samples[2], 1e-5f);
EXPECT_NEAR( 0.05, samples[3], 1e-5f);
EXPECT_NEAR( 0.15, samples[4], 1e-5f);
/* Use the same setup to test getFrameSet().
* Here only a few numbers are tested, due to rounding issues. */
std::set<double> frames;
exporter.getFrameSet(5, frames);
EXPECT_EQ(965, frames.size());
EXPECT_EQ(1, frames.count(30.75));
EXPECT_EQ(1, frames.count(30.95));
EXPECT_EQ(1, frames.count(31.15));
}