diff options
author | Sam Kottler <dev@samkottler.net> | 2020-08-13 17:58:33 +0300 |
---|---|---|
committer | Sam Kottler <dev@samkottler.net> | 2020-08-13 17:58:33 +0300 |
commit | 7c38d008de5ebdcb96ebdd67b8dc459d5551702f (patch) | |
tree | 8fb22f60bc31019e3fe8f5b2bf35159c2e32cda9 /intern | |
parent | cc86e03fd52cd68e66b817590aac80ec2a358d3e (diff) | |
parent | 4e103101f7a20eaa2a61306a1070a04b63a69958 (diff) |
Merge branch 'blender-v2.90-release' into soc-2020-production-ready-light-tree-2
Diffstat (limited to 'intern')
117 files changed, 1379 insertions, 1185 deletions
diff --git a/intern/clog/clog.c b/intern/clog/clog.c index 921ee17a672..d384b9a89e6 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -153,7 +153,6 @@ static void clg_str_reserve(CLogStringBuf *cstr, const uint len) cstr->data = data; cstr->is_alloc = true; } - cstr->len_alloc = len; } } @@ -179,26 +178,34 @@ static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args) { /* Use limit because windows may use '-1' for a formatting error. */ const uint len_max = 65535; - uint len_avail = (cstr->len_alloc - cstr->len); - if (len_avail == 0) { - len_avail = CLOG_BUF_LEN_INIT; - clg_str_reserve(cstr, len_avail); - } while (true) { + uint len_avail = cstr->len_alloc - cstr->len; + va_list args_cpy; va_copy(args_cpy, args); int retval = vsnprintf(cstr->data + cstr->len, len_avail, fmt, args_cpy); va_end(args_cpy); - if (retval != -1) { - cstr->len += retval; + + if (retval < 0) { + /* Some encoding error happened, not much we can do here, besides skipping/cancelling this + * message. */ + break; + } + else if ((uint)retval <= len_avail) { + /* Copy was successful. */ + cstr->len += (uint)retval; break; } else { - len_avail *= 2; - if (len_avail >= len_max) { + /* vsnprintf was not successful, due to lack of allocated space, retval contains expected + * length of the formated string, use it to allocate required amount of memory. */ + uint len_alloc = cstr->len + (uint)retval; + if (len_alloc >= len_max) { + /* Safe upper-limit, just in case... */ break; } - clg_str_reserve(cstr, len_avail); + clg_str_reserve(cstr, len_alloc); + len_avail = cstr->len_alloc - cstr->len; } } } diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 592a69585de..e1ab3b3fbc1 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -76,6 +76,9 @@ struct BlenderCamera { int full_width; int full_height; + int render_width; + int render_height; + BoundBox2D border; BoundBox2D pano_viewplane; BoundBox2D viewport_camera_border; @@ -126,8 +129,10 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_rende bcam->matrix = transform_identity(); /* render resolution */ - bcam->full_width = render_resolution_x(b_render); - bcam->full_height = render_resolution_y(b_render); + bcam->render_width = render_resolution_x(b_render); + bcam->render_height = render_resolution_y(b_render); + bcam->full_width = bcam->render_width; + bcam->full_height = bcam->render_height; } static float blender_camera_focal_distance(BL::RenderEngine &b_engine, @@ -398,8 +403,8 @@ static void blender_camera_sync(Camera *cam, /* panorama sensor */ if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { - float fit_xratio = (float)bcam->full_width * bcam->pixelaspect.x; - float fit_yratio = (float)bcam->full_height * bcam->pixelaspect.y; + float fit_xratio = (float)bcam->render_width * bcam->pixelaspect.x; + float fit_yratio = (float)bcam->render_height * bcam->pixelaspect.y; bool horizontal_fit; float sensor_size; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 391a1b8f473..a06030c8b7d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -59,6 +59,7 @@ BlenderSession::BlenderSession(BL::RenderEngine &b_engine, BL::BlendData &b_data, bool preview_osl) : session(NULL), + scene(NULL), sync(NULL), b_engine(b_engine), b_userpref(b_userpref), @@ -88,6 +89,7 @@ BlenderSession::BlenderSession(BL::RenderEngine &b_engine, int width, int height) : session(NULL), + scene(NULL), sync(NULL), b_engine(b_engine), b_userpref(b_userpref), @@ -492,27 +494,15 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) /* Update denoising parameters. */ session->set_denoising(session_params.denoising); - bool use_denoising = session_params.denoising.use; - bool store_denoising_passes = session_params.denoising.store_passes; - - buffer_params.denoising_data_pass = use_denoising || store_denoising_passes; - buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); - buffer_params.denoising_prefiltered_pass = store_denoising_passes && - session_params.denoising.type == DENOISER_NLM; - - scene->film->denoising_data_pass = buffer_params.denoising_data_pass; - scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass; - scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_pass; - - /* Add passes */ + /* Compute render passes and film settings. */ vector<Pass> passes = sync->sync_render_passes( b_rlay, b_view_layer, session_params.adaptive_sampling, session_params.denoising); - buffer_params.passes = passes; - scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold(); - scene->film->tag_passes_update(scene, passes); - scene->film->tag_update(scene); - scene->integrator->tag_update(scene); + /* Set buffer params, using film settings from sync_render_passes. */ + buffer_params.passes = passes; + buffer_params.denoising_data_pass = scene->film->denoising_data_pass; + buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass; + buffer_params.denoising_prefiltered_pass = scene->film->denoising_prefiltered_pass; BL::RenderResult::views_iterator b_view_iter; @@ -982,7 +972,8 @@ void BlenderSession::update_status_progress() remaining_time = (1.0 - (double)progress) * (render_time / (double)progress); if (background) { - scene_status += " | " + scene->name; + if (scene) + scene_status += " | " + scene->name; if (b_rlay_name != "") scene_status += ", " + b_rlay_name; diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 33e73b5a4b9..ae681432a43 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -678,7 +678,7 @@ static ShaderNode *add_node(Scene *scene, * builtin names for packed images and movies */ int scene_frame = b_scene.frame_current(); - int image_frame = image_user_frame_number(b_image_user, scene_frame); + int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame); image->handle = scene->image_manager->add_image( new BlenderImageLoader(b_image, image_frame), image->image_params()); } @@ -713,7 +713,7 @@ static ShaderNode *add_node(Scene *scene, if (is_builtin) { int scene_frame = b_scene.frame_current(); - int image_frame = image_user_frame_number(b_image_user, scene_frame); + int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame); env->handle = scene->image_manager->add_image(new BlenderImageLoader(b_image, image_frame), env->image_params()); } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index ee90b4dfbfe..f806569c389 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -709,6 +709,16 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, } RNA_END; + scene->film->denoising_data_pass = denoising.use || denoising.store_passes; + scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); + scene->film->denoising_prefiltered_pass = denoising.store_passes && + denoising.type == DENOISER_NLM; + + scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold(); + scene->film->tag_passes_update(scene, passes); + scene->film->tag_update(scene); + scene->integrator->tag_update(scene); + return passes; } diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index ad90a5f8d52..1ea34b41aa2 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -238,7 +238,7 @@ static inline string image_user_file_path(BL::ImageUser &iuser, { char filepath[1024]; iuser.tile(0); - BKE_image_user_frame_calc(NULL, iuser.ptr.data, cfra); + BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra); BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath); string filepath_str = string(filepath); @@ -248,9 +248,9 @@ static inline string image_user_file_path(BL::ImageUser &iuser, return filepath_str; } -static inline int image_user_frame_number(BL::ImageUser &iuser, int cfra) +static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra) { - BKE_image_user_frame_calc(NULL, iuser.ptr.data, cfra); + BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra); return iuser.frame_current(); } diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 80591e0eec8..d0e1e4d6131 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -217,43 +217,29 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float class BlenderVolumeLoader : public VDBImageLoader { public: BlenderVolumeLoader(BL::BlendData &b_data, BL::Volume &b_volume, const string &grid_name) - : VDBImageLoader(grid_name), b_data(b_data), b_volume(b_volume), unload(false) - { - } - - bool load_metadata(ImageMetaData &metadata) override + : VDBImageLoader(grid_name), b_volume(b_volume) { b_volume.grids.load(b_data.ptr.data); - BL::VolumeGrid b_volume_grid = find_grid(); - - if (!b_volume_grid) { - return false; - } - - unload = !b_volume_grid.is_loaded(); #ifdef WITH_OPENVDB - Volume *volume = (Volume *)b_volume.ptr.data; - VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data; - grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); -#endif + BL::Volume::grids_iterator b_grid_iter; + for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) { + BL::VolumeGrid b_volume_grid(*b_grid_iter); + if (b_volume_grid.name() == grid_name) { + const bool unload = !b_volume_grid.is_loaded(); - return VDBImageLoader::load_metadata(metadata); - } + Volume *volume = (Volume *)b_volume.ptr.data; + VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data; + grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); - bool load_pixels(const ImageMetaData &metadata, - void *pixels, - const size_t pixel_size, - const bool associate_alpha) override - { - b_volume.grids.load(b_data.ptr.data); - BL::VolumeGrid b_volume_grid = find_grid(); + if (unload) { + b_volume_grid.unload(); + } - if (!b_volume_grid) { - return false; + break; + } } - - return VDBImageLoader::load_pixels(metadata, pixels, pixel_size, associate_alpha); +#endif } bool equals(const ImageLoader &other) const override @@ -263,36 +249,7 @@ class BlenderVolumeLoader : public VDBImageLoader { return b_volume == other_loader.b_volume && grid_name == other_loader.grid_name; } - void cleanup() override - { - VDBImageLoader::cleanup(); - - BL::VolumeGrid b_volume_grid = find_grid(); - if (b_volume_grid && unload) { - b_volume_grid.unload(); - } - } - - /* Find grid with matching name. Grid point not stored in the class since - * grids may be unloaded before we load the pixels, for example for motion - * blur where we move between frames. */ - BL::VolumeGrid find_grid() - { -#ifdef WITH_OPENVDB - BL::Volume::grids_iterator b_grid_iter; - for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) { - if (b_grid_iter->name() == grid_name) { - return *b_grid_iter; - } - } -#endif - - return BL::VolumeGrid(PointerRNA_NULL); - } - - BL::BlendData b_data; BL::Volume b_volume; - bool unload; }; static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *scene, Mesh *mesh) @@ -342,7 +299,7 @@ static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *s ImageParams params; params.frame = b_volume.grids.frame(); - attr->data_voxel() = scene->image_manager->add_image(loader, params); + attr->data_voxel() = scene->image_manager->add_image(loader, params, false); } } } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 5533eeb006d..db146226dc7 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -539,7 +539,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES) ${SRC_UTIL_HEADERS} COMMAND ${CUBIN_CC_ENV} "$<TARGET_FILE:cycles_cubin_cc>" - -target 52 + -target 50 -ptx -i ${CMAKE_CURRENT_SOURCE_DIR}/${input} ${cuda_flags} @@ -563,7 +563,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES) COMMAND ${CUDA_NVCC_EXECUTABLE} --ptx - -arch=sm_52 + -arch=sm_50 ${cuda_flags} ${input} WORKING_DIRECTORY diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 15cf2e02fdd..2ba3b1c4fdc 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -695,11 +695,9 @@ ccl_device void kernel_path_trace( kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray); -# ifndef __KERNEL_OPTIX__ if (ray.t == 0.0f) { return; } -# endif /* Initialize state. */ float3 throughput = make_float3(1.0f, 1.0f, 1.0f); diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 3d1b6e1d865..145b1fa492c 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -1201,9 +1201,13 @@ void GeometryManager::device_update_volume_images(Device *device, Scene *scene, } ImageHandle &handle = attr.data_voxel(); - const int slot = handle.svm_slot(); - if (slot != -1) { - volume_images.insert(slot); + /* We can build directly from OpenVDB data structures, no need to + * load such images early. */ + if (!handle.vdb_loader()) { + const int slot = handle.svm_slot(); + if (slot != -1) { + volume_images.insert(slot); + } } } } diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 8d187814d64..a5dfcf60d61 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -18,6 +18,7 @@ #include "device/device.h" #include "render/colorspace.h" #include "render/image_oiio.h" +#include "render/image_vdb.h" #include "render/scene.h" #include "render/stats.h" @@ -172,6 +173,31 @@ device_texture *ImageHandle::image_memory(const int tile_index) const return img ? img->mem : NULL; } +VDBImageLoader *ImageHandle::vdb_loader(const int tile_index) const +{ + if (tile_index >= tile_slots.size()) { + return NULL; + } + + ImageManager::Image *img = manager->images[tile_slots[tile_index]]; + + if (img == NULL) { + return NULL; + } + + ImageLoader *loader = img->loader; + + if (loader == NULL) { + return NULL; + } + + if (loader->is_vdb_loader()) { + return dynamic_cast<VDBImageLoader *>(loader); + } + + return NULL; +} + bool ImageHandle::operator==(const ImageHandle &other) const { return manager == other.manager && tile_slots == other.tile_slots; @@ -258,6 +284,11 @@ bool ImageLoader::equals(const ImageLoader *a, const ImageLoader *b) } } +bool ImageLoader::is_vdb_loader() const +{ + return false; +} + /* Image Manager */ ImageManager::ImageManager(const DeviceInfo &info) @@ -362,9 +393,11 @@ ImageHandle ImageManager::add_image(const string &filename, return handle; } -ImageHandle ImageManager::add_image(ImageLoader *loader, const ImageParams ¶ms) +ImageHandle ImageManager::add_image(ImageLoader *loader, + const ImageParams ¶ms, + const bool builtin) { - const int slot = add_image_slot(loader, params, true); + const int slot = add_image_slot(loader, params, builtin); ImageHandle handle; handle.tile_slots.push_back(slot); diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index fffe7c5152a..cb059256ce3 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -39,6 +39,7 @@ class Progress; class RenderStats; class Scene; class ColorSpaceProcessor; +class VDBImageLoader; /* Image Parameters */ class ImageParams { @@ -124,6 +125,8 @@ class ImageLoader { virtual bool equals(const ImageLoader &other) const = 0; static bool equals(const ImageLoader *a, const ImageLoader *b); + virtual bool is_vdb_loader() const; + /* Work around for no RTTI. */ }; @@ -149,6 +152,8 @@ class ImageHandle { int svm_slot(const int tile_index = 0) const; device_texture *image_memory(const int tile_index = 0) const; + VDBImageLoader *vdb_loader(const int tile_index = 0) const; + protected: vector<int> tile_slots; ImageManager *manager; @@ -169,7 +174,7 @@ class ImageManager { ImageHandle add_image(const string &filename, const ImageParams ¶ms, const vector<int> &tiles); - ImageHandle add_image(ImageLoader *loader, const ImageParams ¶ms); + ImageHandle add_image(ImageLoader *loader, const ImageParams ¶ms, const bool builtin = true); void device_update(Device *device, Scene *scene, Progress &progress); void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress); diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp index 500131c2d84..3f7dd45ee88 100644 --- a/intern/cycles/render/image_vdb.cpp +++ b/intern/cycles/render/image_vdb.cpp @@ -185,4 +185,16 @@ void VDBImageLoader::cleanup() #endif } +bool VDBImageLoader::is_vdb_loader() const +{ + return true; +} + +#ifdef WITH_OPENVDB +openvdb::GridBase::ConstPtr VDBImageLoader::get_grid() +{ + return grid; +} +#endif + CCL_NAMESPACE_END diff --git a/intern/cycles/render/image_vdb.h b/intern/cycles/render/image_vdb.h index 7dec63b11e6..4500cfbfb88 100644 --- a/intern/cycles/render/image_vdb.h +++ b/intern/cycles/render/image_vdb.h @@ -43,6 +43,12 @@ class VDBImageLoader : public ImageLoader { virtual void cleanup() override; + virtual bool is_vdb_loader() const override; + +#ifdef WITH_OPENVDB + openvdb::GridBase::ConstPtr get_grid(); +#endif + protected: string grid_name; #ifdef WITH_OPENVDB diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp index 607363d01c6..70189ea4812 100644 --- a/intern/cycles/render/mesh_volume.cpp +++ b/intern/cycles/render/mesh_volume.cpp @@ -15,34 +15,25 @@ */ #include "render/attribute.h" +#include "render/image_vdb.h" #include "render/mesh.h" #include "render/scene.h" +#ifdef WITH_OPENVDB +# include <openvdb/tools/Dense.h> +# include <openvdb/tools/GridTransformer.h> +# include <openvdb/tools/Morphology.h> +#endif + #include "util/util_foreach.h" #include "util/util_hash.h" #include "util/util_logging.h" +#include "util/util_openvdb.h" #include "util/util_progress.h" #include "util/util_types.h" CCL_NAMESPACE_BEGIN -const int64_t VOXEL_INDEX_NONE = -1; - -static int64_t compute_voxel_index(const int3 &resolution, int64_t x, int64_t y, int64_t z) -{ - if (x < 0 || x >= resolution.x) { - return VOXEL_INDEX_NONE; - } - else if (y < 0 || y >= resolution.y) { - return VOXEL_INDEX_NONE; - } - else if (z < 0 || z >= resolution.z) { - return VOXEL_INDEX_NONE; - } - - return x + y * resolution.x + z * resolution.x * resolution.y; -} - struct QuadData { int v0, v1, v2, v3; @@ -123,122 +114,146 @@ static void create_quad(int3 corners[8], quads.push_back(quad); } -struct VolumeParams { - int3 resolution; - float3 cell_size; - float3 start_point; - int pad_size; -}; - -static const int CUBE_SIZE = 8; - /* Create a mesh from a volume. * * The way the algorithm works is as follows: * - * - The coordinates of active voxels from a dense volume (or 3d image) are - * gathered inside an auxiliary volume. - * - Each set of coordinates of an CUBE_SIZE cube are mapped to the same - * coordinate of the auxiliary volume. - * - Quads are created between active and non-active voxels in the auxiliary - * volume to generate a tight mesh around the volume. + * - The topologies of input OpenVDB grids are merged into a temporary grid. + * - Voxels of the temporary grid are dilated to account for the padding necessary for volume + * sampling. + * - Quads are created on the boundary between active and inactive leaf nodes of the temporary + * grid. */ class VolumeMeshBuilder { - /* Auxiliary volume that is used to check if a node already added. */ - vector<char> grid; - - /* The resolution of the auxiliary volume, set to be equal to 1/CUBE_SIZE - * of the original volume on each axis. */ - int3 res; - - size_t number_of_nodes; - - /* Offset due to padding in the original grid. Padding will transform the - * coordinates of the original grid from 0...res to -padding...res+padding, - * so some coordinates are negative, and we need to properly account for - * them. */ - int3 pad_offset; - - VolumeParams *params; - public: - VolumeMeshBuilder(VolumeParams *volume_params); +#ifdef WITH_OPENVDB + /* use a MaskGrid to store the topology to save memory */ + openvdb::MaskGrid::Ptr topology_grid; + openvdb::CoordBBox bbox; +#endif + bool first_grid; - void add_node(int x, int y, int z); + VolumeMeshBuilder(); - void add_node_with_padding(int x, int y, int z); +#ifdef WITH_OPENVDB + void add_grid(openvdb::GridBase::ConstPtr grid, bool do_clipping, float volume_clipping); +#endif - void create_mesh(vector<float3> &vertices, vector<int> &indices, vector<float3> &face_normals); + void add_padding(int pad_size); + + void create_mesh(vector<float3> &vertices, + vector<int> &indices, + vector<float3> &face_normals, + const float face_overlap_avoidance); - private: void generate_vertices_and_quads(vector<int3> &vertices_is, vector<QuadData> &quads); - void convert_object_space(const vector<int3> &vertices, vector<float3> &out_vertices); + void convert_object_space(const vector<int3> &vertices, + vector<float3> &out_vertices, + const float face_overlap_avoidance); void convert_quads_to_tris(const vector<QuadData> &quads, vector<int> &tris, vector<float3> &face_normals); -}; -VolumeMeshBuilder::VolumeMeshBuilder(VolumeParams *volume_params) -{ - params = volume_params; - number_of_nodes = 0; + bool empty_grid() const; - const int64_t x = divide_up(params->resolution.x, CUBE_SIZE); - const int64_t y = divide_up(params->resolution.y, CUBE_SIZE); - const int64_t z = divide_up(params->resolution.z, CUBE_SIZE); +#ifdef WITH_OPENVDB + template <typename GridType> + void merge_grid(openvdb::GridBase::ConstPtr grid, bool do_clipping, float volume_clipping) + { + typename GridType::ConstPtr typed_grid = openvdb::gridConstPtrCast<GridType>(grid); - /* Adding 2*pad_size since we pad in both positive and negative directions - * along the axis. */ - const int64_t px = divide_up(params->resolution.x + 2 * params->pad_size, CUBE_SIZE); - const int64_t py = divide_up(params->resolution.y + 2 * params->pad_size, CUBE_SIZE); - const int64_t pz = divide_up(params->resolution.z + 2 * params->pad_size, CUBE_SIZE); + if (do_clipping) { + using ValueType = typename GridType::ValueType; + typename GridType::Ptr copy = typed_grid->deepCopy(); + typename GridType::ValueOnIter iter = copy->beginValueOn(); - res = make_int3(px, py, pz); - pad_offset = make_int3(px - x, py - y, pz - z); + for (; iter; ++iter) { + if (iter.getValue() < ValueType(volume_clipping)) { + iter.setValueOff(); + } + } - grid.resize(px * py * pz, 0); -} + typed_grid = copy; + } -void VolumeMeshBuilder::add_node(int x, int y, int z) -{ - /* Map coordinates to index space. */ - const int index_x = (x / CUBE_SIZE) + pad_offset.x; - const int index_y = (y / CUBE_SIZE) + pad_offset.y; - const int index_z = (z / CUBE_SIZE) + pad_offset.z; + topology_grid->topologyUnion(*typed_grid); + } +#endif +}; - assert((index_x >= 0) && (index_y >= 0) && (index_z >= 0)); +VolumeMeshBuilder::VolumeMeshBuilder() +{ + first_grid = true; +} - const int64_t index = compute_voxel_index(res, index_x, index_y, index_z); - if (index == VOXEL_INDEX_NONE) { - return; +#ifdef WITH_OPENVDB +void VolumeMeshBuilder::add_grid(openvdb::GridBase::ConstPtr grid, bool do_clipping, float volume_clipping) +{ + /* set the transform of our grid from the first one */ + if (first_grid) { + topology_grid = openvdb::MaskGrid::create(); + topology_grid->setTransform(grid->transform().copy()); + first_grid = false; } - - /* We already have a node here. */ - if (grid[index] == 1) { - return; + /* if the transforms do not match, we need to resample one of the grids so that + * its index space registers with that of the other, here we resample our mask + * grid so memory usage is kept low */ + else if (topology_grid->transform() != grid->transform()) { + openvdb::MaskGrid::Ptr temp_grid = topology_grid->copyWithNewTree(); + temp_grid->setTransform(grid->transform().copy()); + openvdb::tools::resampleToMatch<openvdb::tools::BoxSampler>(*topology_grid, *temp_grid); + topology_grid = temp_grid; + topology_grid->setTransform(grid->transform().copy()); } - ++number_of_nodes; - - grid[index] = 1; + if (grid->isType<openvdb::FloatGrid>()) { + merge_grid<openvdb::FloatGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::Vec3fGrid>()) { + merge_grid<openvdb::Vec3fGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::Vec4fGrid>()) { + merge_grid<openvdb::Vec4fGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::BoolGrid>()) { + merge_grid<openvdb::BoolGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::DoubleGrid>()) { + merge_grid<openvdb::DoubleGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::Int32Grid>()) { + merge_grid<openvdb::Int32Grid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::Int64Grid>()) { + merge_grid<openvdb::Int64Grid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::Vec3IGrid>()) { + merge_grid<openvdb::Vec3IGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::Vec3dGrid>()) { + merge_grid<openvdb::Vec3dGrid>(grid, do_clipping, volume_clipping); + } + else if (grid->isType<openvdb::MaskGrid>()) { + topology_grid->topologyUnion(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid)); + } } +#endif -void VolumeMeshBuilder::add_node_with_padding(int x, int y, int z) +void VolumeMeshBuilder::add_padding(int pad_size) { - for (int px = x - params->pad_size; px < x + params->pad_size; ++px) { - for (int py = y - params->pad_size; py < y + params->pad_size; ++py) { - for (int pz = z - params->pad_size; pz < z + params->pad_size; ++pz) { - add_node(px, py, pz); - } - } - } +#ifdef WITH_OPENVDB + openvdb::tools::dilateVoxels(topology_grid->tree(), pad_size); +#else + (void)pad_size; +#endif } void VolumeMeshBuilder::create_mesh(vector<float3> &vertices, vector<int> &indices, - vector<float3> &face_normals) + vector<float3> &face_normals, + const float face_overlap_avoidance) { /* We create vertices in index space (is), and only convert them to object * space when done. */ @@ -247,7 +262,7 @@ void VolumeMeshBuilder::create_mesh(vector<float3> &vertices, generate_vertices_and_quads(vertices_is, quads); - convert_object_space(vertices_is, vertices); + convert_object_space(vertices_is, vertices, face_overlap_avoidance); convert_quads_to_tris(quads, indices, face_normals); } @@ -255,85 +270,97 @@ void VolumeMeshBuilder::create_mesh(vector<float3> &vertices, void VolumeMeshBuilder::generate_vertices_and_quads(vector<ccl::int3> &vertices_is, vector<QuadData> &quads) { - unordered_map<size_t, int> used_verts; +#ifdef WITH_OPENVDB + const openvdb::MaskGrid::TreeType &tree = topology_grid->tree(); + tree.evalLeafBoundingBox(bbox); - for (int z = 0; z < res.z; ++z) { - for (int y = 0; y < res.y; ++y) { - for (int x = 0; x < res.x; ++x) { - int64_t voxel_index = compute_voxel_index(res, x, y, z); - if (grid[voxel_index] == 0) { - continue; - } + const int3 resolution = make_int3(bbox.dim().x(), bbox.dim().y(), bbox.dim().z()); - /* Compute min and max coords of the node in index space. */ - int3 min = make_int3((x - pad_offset.x) * CUBE_SIZE, - (y - pad_offset.y) * CUBE_SIZE, - (z - pad_offset.z) * CUBE_SIZE); - - /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */ - int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE); - - int3 corners[8] = { - make_int3(min[0], min[1], min[2]), - make_int3(max[0], min[1], min[2]), - make_int3(max[0], max[1], min[2]), - make_int3(min[0], max[1], min[2]), - make_int3(min[0], min[1], max[2]), - make_int3(max[0], min[1], max[2]), - make_int3(max[0], max[1], max[2]), - make_int3(min[0], max[1], max[2]), - }; - - /* Only create a quad if on the border between an active and - * an inactive node. - */ - - voxel_index = compute_voxel_index(res, x - 1, y, z); - if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) { - create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN); - } + unordered_map<size_t, int> used_verts; - voxel_index = compute_voxel_index(res, x + 1, y, z); - if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) { - create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX); - } + for (auto iter = tree.cbeginLeaf(); iter; ++iter) { + openvdb::CoordBBox leaf_bbox = iter->getNodeBoundingBox(); + /* +1 to convert from exclusive to include bounds. */ + leaf_bbox.max() = leaf_bbox.max().offsetBy(1); + + int3 min = make_int3(leaf_bbox.min().x(), leaf_bbox.min().y(), leaf_bbox.min().z()); + int3 max = make_int3(leaf_bbox.max().x(), leaf_bbox.max().y(), leaf_bbox.max().z()); + + int3 corners[8] = { + make_int3(min[0], min[1], min[2]), + make_int3(max[0], min[1], min[2]), + make_int3(max[0], max[1], min[2]), + make_int3(min[0], max[1], min[2]), + make_int3(min[0], min[1], max[2]), + make_int3(max[0], min[1], max[2]), + make_int3(max[0], max[1], max[2]), + make_int3(min[0], max[1], max[2]), + }; + + /* Only create a quad if on the border between an active and an inactive leaf. + * + * We verify that a leaf exists by probing a coordinate that is at its center, + * to do so we compute the center of the current leaf and offset this coordinate + * by the size of a leaf in each direction. + */ + static const int LEAF_DIM = openvdb::MaskGrid::TreeType::LeafNodeType::DIM; + auto center = leaf_bbox.min() + openvdb::Coord(LEAF_DIM / 2); + + if (!tree.probeLeaf(openvdb::Coord(center.x() - LEAF_DIM, center.y(), center.z()))) { + create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_X_MIN); + } - voxel_index = compute_voxel_index(res, x, y - 1, z); - if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) { - create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN); - } + if (!tree.probeLeaf(openvdb::Coord(center.x() + LEAF_DIM, center.y(), center.z()))) { + create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_X_MAX); + } - voxel_index = compute_voxel_index(res, x, y + 1, z); - if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) { - create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX); - } + if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y() - LEAF_DIM, center.z()))) { + create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Y_MIN); + } - voxel_index = compute_voxel_index(res, x, y, z - 1); - if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) { - create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN); - } + if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y() + LEAF_DIM, center.z()))) { + create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Y_MAX); + } - voxel_index = compute_voxel_index(res, x, y, z + 1); - if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) { - create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX); - } - } + if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y(), center.z() - LEAF_DIM))) { + create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Z_MIN); + } + + if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y(), center.z() + LEAF_DIM))) { + create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Z_MAX); } } +#else + (void)vertices_is; + (void)quads; +#endif } void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices, - vector<float3> &out_vertices) + vector<float3> &out_vertices, + const float face_overlap_avoidance) { +#ifdef WITH_OPENVDB + /* compute the offset for the face overlap avoidance */ + bbox = topology_grid->evalActiveVoxelBoundingBox(); + openvdb::Coord dim = bbox.dim(); + + float3 cell_size = make_float3(1.0f / dim.x(), 1.0f / dim.y(), 1.0f / dim.z()); + float3 point_offset = cell_size * face_overlap_avoidance; + out_vertices.reserve(vertices.size()); for (size_t i = 0; i < vertices.size(); ++i) { - float3 vertex = make_float3(vertices[i].x, vertices[i].y, vertices[i].z); - vertex *= params->cell_size; - vertex += params->start_point; - - out_vertices.push_back(vertex); + openvdb::math::Vec3d p = topology_grid->indexToWorld( + openvdb::math::Vec3d(vertices[i].x, vertices[i].y, vertices[i].z)); + float3 vertex = make_float3((float)p.x(), (float)p.y(), (float)p.z()); + out_vertices.push_back(vertex + point_offset); } +#else + (void)vertices; + (void)out_vertices; + (void)face_overlap_avoidance; +#endif } void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads, @@ -359,57 +386,115 @@ void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads, } } -/* ************************************************************************** */ +bool VolumeMeshBuilder::empty_grid() const +{ +#ifdef WITH_OPENVDB + return !topology_grid || topology_grid->tree().leafCount() == 0; +#else + return true; +#endif +} -struct VoxelAttributeGrid { - float *data; - int channels; -}; +#ifdef WITH_OPENVDB +template<typename GridType> +static openvdb::GridBase::ConstPtr openvdb_grid_from_device_texture(device_texture *image_memory, + float volume_clipping, + Transform transform_3d) +{ + using ValueType = typename GridType::ValueType; + + openvdb::CoordBBox dense_bbox(0, + 0, + 0, + image_memory->data_width - 1, + image_memory->data_height - 1, + image_memory->data_depth - 1); + openvdb::tools::Dense<ValueType, openvdb::tools::MemoryLayout::LayoutXYZ> dense( + dense_bbox, static_cast<ValueType *>(image_memory->host_pointer)); + + typename GridType::Ptr sparse = GridType::create(ValueType(0.0f)); + openvdb::tools::copyFromDense(dense, *sparse, ValueType(volume_clipping)); + + /* copyFromDense will remove any leaf node that contains constant data and replace it with a tile, + * however, we need to preserve the leaves in order to generate the mesh, so revoxelize the leaves + * that were pruned. This should not affect areas that were skipped due to the volume_clipping parameter. */ + sparse->tree().voxelizeActiveTiles(); + + /* Compute index to world matrix. */ + float3 voxel_size = make_float3(1.0f / image_memory->data_width, 1.0f / image_memory->data_height, 1.0f / image_memory->data_depth); + + transform_3d = transform_inverse(transform_3d); + + openvdb::Mat4R index_to_world_mat((double)(voxel_size.x * transform_3d[0][0]), 0.0, 0.0, 0.0, + 0.0, (double)(voxel_size.y * transform_3d[1][1]), 0.0, 0.0, + 0.0, 0.0, (double)(voxel_size.z * transform_3d[2][2]), 0.0, + (double)transform_3d[0][3], (double)transform_3d[1][3], (double)transform_3d[2][3], 1.0); + + openvdb::math::Transform::Ptr index_to_world_tfm = openvdb::math::Transform::createLinearTransform(index_to_world_mat); + + sparse->setTransform(index_to_world_tfm); + + return sparse; +} +#endif + +/* ************************************************************************** */ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress) { string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str()); progress.set_status("Updating Mesh", msg); - vector<VoxelAttributeGrid> voxel_grids; - - /* Compute volume parameters. */ - VolumeParams volume_params; - volume_params.resolution = make_int3(0, 0, 0); - - Transform transform = transform_identity(); + VolumeMeshBuilder builder; +#ifdef WITH_OPENVDB foreach (Attribute &attr, mesh->attributes.attributes) { if (attr.element != ATTR_ELEMENT_VOXEL) { continue; } + bool do_clipping = false; + ImageHandle &handle = attr.data_voxel(); - device_texture *image_memory = handle.image_memory(); - int3 resolution = make_int3( - image_memory->data_width, image_memory->data_height, image_memory->data_depth); - if (volume_params.resolution == make_int3(0, 0, 0)) { - volume_params.resolution = resolution; - } - else if (volume_params.resolution != resolution) { - /* TODO: support this as it's common for OpenVDB. */ - VLOG(1) << "Can't create accurate volume mesh, all voxel grid resolutions must be equal\n"; - continue; + /* Try building from OpenVDB grid directly. */ + VDBImageLoader *vdb_loader = handle.vdb_loader(); + openvdb::GridBase::ConstPtr grid; + if (vdb_loader) { + grid = vdb_loader->get_grid(); + + /* If building from an OpenVDB grid, we need to manually clip the values. */ + do_clipping = true; } - VoxelAttributeGrid voxel_grid; - voxel_grid.data = static_cast<float *>(image_memory->host_pointer); - voxel_grid.channels = image_memory->data_elements; - voxel_grids.push_back(voxel_grid); + /* Else fall back to creating an OpenVDB grid from the dense volume data. */ + if (!grid) { + device_texture *image_memory = handle.image_memory(); - /* TODO: support multiple transforms. */ - if (image_memory->info.use_transform_3d) { - transform = image_memory->info.transform_3d; + if (image_memory->data_elements == 1) { + grid = openvdb_grid_from_device_texture<openvdb::FloatGrid>(image_memory, + mesh->volume_clipping, + handle.metadata().transform_3d); + } + else if (image_memory->data_elements == 3) { + grid = openvdb_grid_from_device_texture<openvdb::Vec3fGrid>(image_memory, + mesh->volume_clipping, + handle.metadata().transform_3d); + } + else if (image_memory->data_elements == 4) { + grid = openvdb_grid_from_device_texture<openvdb::Vec4fGrid>(image_memory, + mesh->volume_clipping, + handle.metadata().transform_3d); + } + } + + if (grid) { + builder.add_grid(grid, do_clipping, mesh->volume_clipping); } } +#endif - if (voxel_grids.empty()) { + if (builder.empty_grid()) { return; } @@ -438,56 +523,19 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress) return; } - /* Compute start point and cell size from transform. */ - const int3 resolution = volume_params.resolution; - float3 start_point = make_float3(0.0f, 0.0f, 0.0f); - float3 cell_size = make_float3(1.0f / resolution.x, 1.0f / resolution.y, 1.0f / resolution.z); - - /* TODO: support arbitrary transforms, not just scale + translate. */ - const Transform itfm = transform_inverse(transform); - start_point = transform_point(&itfm, start_point); - cell_size = transform_direction(&itfm, cell_size); + builder.add_padding(pad_size); /* Slightly offset vertex coordinates to avoid overlapping faces with other * volumes or meshes. The proper solution would be to improve intersection in * the kernel to support robust handling of multiple overlapping faces or use * an all-hit intersection similar to shadows. */ - const float3 face_overlap_avoidance = cell_size * 0.1f * - hash_uint_to_float(hash_string(mesh->name.c_str())); - - volume_params.start_point = start_point + face_overlap_avoidance; - volume_params.cell_size = cell_size; - volume_params.pad_size = pad_size; - - /* Build bounding mesh around non-empty volume cells. */ - VolumeMeshBuilder builder(&volume_params); - const float clipping = mesh->volume_clipping; - - for (int z = 0; z < resolution.z; ++z) { - for (int y = 0; y < resolution.y; ++y) { - for (int x = 0; x < resolution.x; ++x) { - int64_t voxel_index = compute_voxel_index(resolution, x, y, z); - - for (size_t i = 0; i < voxel_grids.size(); ++i) { - const VoxelAttributeGrid &voxel_grid = voxel_grids[i]; - const int channels = voxel_grid.channels; - - for (int c = 0; c < channels; c++) { - if (voxel_grid.data[voxel_index * channels + c] >= clipping) { - builder.add_node_with_padding(x, y, z); - break; - } - } - } - } - } - } + const float face_overlap_avoidance = 0.1f * hash_uint_to_float(hash_string(mesh->name.c_str())); /* Create mesh. */ vector<float3> vertices; vector<int> indices; vector<float3> face_normals; - builder.create_mesh(vertices, indices, face_normals); + builder.create_mesh(vertices, indices, face_normals, face_overlap_avoidance); mesh->clear(true); mesh->reserve_mesh(vertices.size(), indices.size() / 3); @@ -514,10 +562,6 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress) indices.size() * sizeof(int)) / (1024.0 * 1024.0) << "Mb."; - - VLOG(1) << "Memory usage volume grid: " - << (resolution.x * resolution.y * resolution.z * sizeof(float)) / (1024.0 * 1024.0) - << "Mb."; } CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index c5033359c6b..70c4214c684 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -945,8 +945,14 @@ void Session::set_pause(bool pause_) } } - if (notify) - pause_cond.notify_all(); + if (session_thread) { + if (notify) { + pause_cond.notify_all(); + } + } + else if (pause_) { + update_status_time(pause_); + } } void Session::set_denoising(const DenoiseParams &denoising) @@ -1150,8 +1156,15 @@ bool Session::render_need_denoise(bool &delayed) return false; } + /* Immediately denoise when we reach the start sample or last sample. */ + const int num_samples_finished = tile_manager.state.sample + 1; + if (num_samples_finished == params.denoising.start_sample || + num_samples_finished == params.samples) { + return true; + } + /* Do not denoise until the sample at which denoising should start is reached. */ - if (tile_manager.state.sample < min(params.denoising.start_sample, params.samples - 1)) { + if (num_samples_finished < params.denoising.start_sample) { return false; } diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index 6dcc7f7b3dd..07b345baff8 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -112,3 +112,4 @@ set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${C CYCLES_TEST(util_avxf_avx "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}") set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}") CYCLES_TEST(util_avxf_avx2 "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}") +CYCLES_TEST(util_transform "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}") diff --git a/intern/cycles/test/util_transform_test.cpp b/intern/cycles/test/util_transform_test.cpp new file mode 100644 index 00000000000..58ce0fdfee4 --- /dev/null +++ b/intern/cycles/test/util_transform_test.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testing/testing.h" + +#include "util/util_transform.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +TEST(transform_motion_decompose, Degenerated) +{ + // Simple case: single degenerated matrix. + { + vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f)}; + vector<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); + EXPECT_TRUE(transform_decomposed_isfinite_safe(&decomp[0])); + } + + // Copy from previous to current. + { + vector<Transform> motion = {transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f)), + transform_scale(0.0f, 0.0f, 0.0f)}; + vector<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); + EXPECT_NEAR(len(decomp[1].x - decomp[0].x), 0.0f, 1e-6f); + } + + // Copy from next to current. + { + vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f), + transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f))}; + vector<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); + EXPECT_NEAR(len(decomp[0].x - decomp[1].x), 0.0f, 1e-6f); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index f5e488d1bd2..a35ec6c7e29 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -88,6 +88,7 @@ set(SRC_HEADERS util_murmurhash.h util_openimagedenoise.h util_opengl.h + util_openvdb.h util_optimization.h util_param.h util_path.h diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h index e979bd9e0c0..07b0878e3d5 100644 --- a/intern/cycles/util/util_math_fast.h +++ b/intern/cycles/util/util_math_fast.h @@ -87,7 +87,7 @@ ccl_device_inline int fast_rint(float x) /* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */ return float_to_int(rintf(x)); #else - /* emulate rounding by adding/substracting 0.5. */ + /* emulate rounding by adding/subtracting 0.5. */ return float_to_int(x + copysignf(0.5f, x)); #endif } @@ -445,12 +445,10 @@ ccl_device_inline float fast_expf(float x) return fast_exp2f(x / M_LN2_F); } -#ifndef __KERNEL_GPU__ -/* MSVC seems to have a code-gen bug here in at least SSE41/AVX - * see T78047 for details. */ -# ifdef _MSC_VER -# pragma optimize("", off) -# endif +#if defined(__KERNEL_CPU__) && !defined(_MSC_VER) +/* MSVC seems to have a code-gen bug here in at least SSE41/AVX, see + * T78047 and T78869 for details. Just disable for now, it only makes + * a small difference in denoising performance. */ ccl_device float4 fast_exp2f4(float4 x) { const float4 one = make_float4(1.0f); @@ -466,14 +464,16 @@ ccl_device float4 fast_exp2f4(float4 x) r = madd4(x, r, make_float4(1.0f)); return __int4_as_float4(__float4_as_int4(r) + (m << 23)); } -# ifdef _MSC_VER -# pragma optimize("", on) -# endif ccl_device_inline float4 fast_expf4(float4 x) { return fast_exp2f4(x / M_LN2_F); } +#else +ccl_device_inline float4 fast_expf4(float4 x) +{ + return make_float4(fast_expf(x.x), fast_expf(x.y), fast_expf(x.z), fast_expf(x.w)); +} #endif ccl_device_inline float fast_exp10(float x) diff --git a/intern/cycles/util/util_math_float4.h b/intern/cycles/util/util_math_float4.h index cd4b3e3b74c..ec5328adb31 100644 --- a/intern/cycles/util/util_math_float4.h +++ b/intern/cycles/util/util_math_float4.h @@ -477,6 +477,24 @@ ccl_device_inline float4 safe_divide_float4_float(const float4 a, const float b) return (b != 0.0f) ? a / b : make_float4(0.0f, 0.0f, 0.0f, 0.0f); } +ccl_device_inline bool isfinite4_safe(float4 v) +{ + return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z) && isfinite_safe(v.w); +} + +ccl_device_inline float4 ensure_finite4(float4 v) +{ + if (!isfinite_safe(v.x)) + v.x = 0.0f; + if (!isfinite_safe(v.y)) + v.y = 0.0f; + if (!isfinite_safe(v.z)) + v.z = 0.0f; + if (!isfinite_safe(v.w)) + v.w = 0.0f; + return v; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_FLOAT4_H__ */ diff --git a/intern/cycles/util/util_openvdb.h b/intern/cycles/util/util_openvdb.h new file mode 100644 index 00000000000..a3ebb03e5a4 --- /dev/null +++ b/intern/cycles/util/util_openvdb.h @@ -0,0 +1,32 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_OPENVDB_H__ +#define __UTIL_OPENVDB_H__ + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> + +namespace openvdb { + +using Vec4fTree = tree::Tree4<Vec4f, 5, 4, 3>::Type; +using Vec4fGrid = Grid<Vec4fTree>; + +}; // namespace openvdb + +#endif + +#endif /* __UTIL_OPENVDB_H__ */ diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 101122740d7..6417752f704 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -269,17 +269,17 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf /* extract scale and shear first */ float3 scale, shear; scale.x = len(colx); - colx /= scale.x; + colx = safe_divide_float3_float(colx, scale.x); shear.z = dot(colx, coly); coly -= shear.z * colx; scale.y = len(coly); - coly /= scale.y; + coly = safe_divide_float3_float(coly, scale.y); shear.y = dot(colx, colz); colz -= shear.y * colx; shear.x = dot(coly, colz); colz -= shear.x * coly; scale.z = len(colz); - colz /= scale.z; + colz = safe_divide_float3_float(colz, scale.z); transform_set_column(&M, 0, colx); transform_set_column(&M, 1, coly); @@ -300,6 +300,7 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size) { + /* Decompose and correct rotation. */ for (size_t i = 0; i < size; i++) { transform_decompose(decomp + i, motion + i); @@ -310,6 +311,27 @@ void transform_motion_decompose(DecomposedTransform *decomp, const Transform *mo decomp[i].x = -decomp[i].x; } } + + /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object + * rotation interpolation when the scale goes to 0 for a time step. + * + * Note that this is very simple and naive implementation, which only deals with degenerated + * scale happening only on one frame. It is possible to improve it further by interpolating + * rotation into s degenerated range using rotation from timesteps from adjacent non-degenerated + * time steps. */ + for (size_t i = 0; i < size; i++) { + const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w); + if (!is_zero(scale)) { + continue; + } + + if (i > 0) { + decomp[i].x = decomp[i - 1].x; + } + else if (i < size - 1) { + decomp[i].x = decomp[i + 1].x; + } + } } Transform transform_from_viewplane(BoundBox2D &viewplane) diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index d0a6264d5cf..d8bbd389aa6 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -466,6 +466,17 @@ ccl_device void transform_motion_array_interpolate(Transform *tfm, transform_compose(tfm, &decomp); } +ccl_device_inline bool transform_isfinite_safe(Transform *tfm) +{ + return isfinite4_safe(tfm->x) && isfinite4_safe(tfm->y) && isfinite4_safe(tfm->z); +} + +ccl_device_inline bool transform_decomposed_isfinite_safe(DecomposedTransform *decomp) +{ + return isfinite4_safe(decomp->x) && isfinite4_safe(decomp->y) && isfinite4_safe(decomp->z) && + isfinite4_safe(decomp->w); +} + #ifndef __KERNEL_GPU__ class BoundBox2D; diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 92061f55128..f23742a9166 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -21,8 +21,7 @@ * \brief GHOST C-API function and type declarations. */ -#ifndef __GHOST_C_API_H__ -#define __GHOST_C_API_H__ +#pragma once #include "GHOST_Types.h" @@ -1072,5 +1071,3 @@ GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context); #ifdef __cplusplus } #endif - -#endif diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h index 8c24261644a..c6316e90ce4 100644 --- a/intern/ghost/GHOST_IContext.h +++ b/intern/ghost/GHOST_IContext.h @@ -22,8 +22,7 @@ * Declaration of GHOST_IContext interface class. */ -#ifndef __GHOST_IContext_H__ -#define __GHOST_IContext_H__ +#pragma once #include "GHOST_Types.h" @@ -63,5 +62,3 @@ class GHOST_IContext { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext") #endif }; - -#endif // __GHOST_IContext_H__ diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h index 0d9bfb2c4de..c63064c123a 100644 --- a/intern/ghost/GHOST_IEvent.h +++ b/intern/ghost/GHOST_IEvent.h @@ -22,8 +22,7 @@ * Declaration of GHOST_IEvent interface class. */ -#ifndef __GHOST_IEVENT_H__ -#define __GHOST_IEVENT_H__ +#pragma once #include "GHOST_Types.h" #include <stddef.h> @@ -78,5 +77,3 @@ class GHOST_IEvent { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IEvent") #endif }; - -#endif // __GHOST_IEVENT_H__ diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h index d677a632a4b..b5975068da0 100644 --- a/intern/ghost/GHOST_IEventConsumer.h +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -22,8 +22,7 @@ * Declaration of GHOST_IEventConsumer interface class. */ -#ifndef __GHOST_IEVENTCONSUMER_H__ -#define __GHOST_IEVENTCONSUMER_H__ +#pragma once #include "GHOST_IEvent.h" @@ -56,5 +55,3 @@ class GHOST_IEventConsumer { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IEventConsumer") #endif }; - -#endif /* __GHOST_IEVENTCONSUMER_H__ */ diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 33600fd1219..04e9d5e4e14 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -24,8 +24,7 @@ * Contains the doxygen documentation main page. */ -#ifndef __GHOST_ISYSTEM_H__ -#define __GHOST_ISYSTEM_H__ +#pragma once #include <stdlib.h> @@ -494,5 +493,3 @@ class GHOST_ISystem { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ISystem") #endif }; - -#endif // __GHOST_ISYSTEM_H__ diff --git a/intern/ghost/GHOST_ISystemPaths.h b/intern/ghost/GHOST_ISystemPaths.h index 297f6333a77..b47d14984d8 100644 --- a/intern/ghost/GHOST_ISystemPaths.h +++ b/intern/ghost/GHOST_ISystemPaths.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_ISYSTEMPATHS_H__ -#define __GHOST_ISYSTEMPATHS_H__ +#pragma once #include "GHOST_Types.h" @@ -97,5 +96,3 @@ class GHOST_ISystemPaths { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ISystemPaths") #endif }; - -#endif diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h index 46f4fdbc303..0f4ac74c466 100644 --- a/intern/ghost/GHOST_ITimerTask.h +++ b/intern/ghost/GHOST_ITimerTask.h @@ -22,8 +22,7 @@ * Declaration of GHOST_ITimerTask interface class. */ -#ifndef __GHOST_ITIMERTASK_H__ -#define __GHOST_ITIMERTASK_H__ +#pragma once #include "GHOST_Types.h" @@ -76,5 +75,3 @@ class GHOST_ITimerTask { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ITimerTask") #endif }; - -#endif // __GHOST_ITIMERTASK_H__ diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 9c72b6f07f9..6e8b61ae5a1 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -22,8 +22,7 @@ * Declaration of GHOST_IWindow interface class. */ -#ifndef __GHOST_IWINDOW_H__ -#define __GHOST_IWINDOW_H__ +#pragma once #include "GHOST_Rect.h" #include "GHOST_Types.h" @@ -363,5 +362,3 @@ class GHOST_IWindow { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow") #endif }; - -#endif // __GHOST_IWINDOW_H__ diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h index 3076de96690..dd266a3b6ae 100644 --- a/intern/ghost/GHOST_IXrContext.h +++ b/intern/ghost/GHOST_IXrContext.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_IXRCONTEXT_H__ -#define __GHOST_IXRCONTEXT_H__ +#pragma once #include "GHOST_Types.h" @@ -40,5 +39,3 @@ class GHOST_IXrContext { virtual bool needsUpsideDownDrawing() const = 0; }; - -#endif // __GHOST_IXRCONTEXT_H__ diff --git a/intern/ghost/GHOST_Path-api.h b/intern/ghost/GHOST_Path-api.h index 53abdf68bb4..4cc232be6b6 100644 --- a/intern/ghost/GHOST_Path-api.h +++ b/intern/ghost/GHOST_Path-api.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_PATH_API_H__ -#define __GHOST_PATH_API_H__ +#pragma once #include "GHOST_Types.h" @@ -71,5 +70,3 @@ extern void GHOST_addToSystemRecentFiles(const char *filename); #ifdef __cplusplus } #endif - -#endif diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index 13632a1c03b..fcc9da20197 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -22,8 +22,7 @@ * Macro's used in GHOST debug target. */ -#ifndef __GHOST_RECT_H__ -#define __GHOST_RECT_H__ +#pragma once #include "GHOST_Types.h" @@ -263,5 +262,3 @@ inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const { return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b); } - -#endif // __GHOST_RECT_H__ diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index b8de31df6c6..5f0516ae121 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_TYPES_H__ -#define __GHOST_TYPES_H__ +#pragma once #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" @@ -677,5 +676,3 @@ typedef struct GHOST_XrError { } GHOST_XrError; #endif - -#endif // __GHOST_TYPES_H__ diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h index 0b824739950..e28fae8870c 100644 --- a/intern/ghost/intern/GHOST_Buttons.h +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -22,8 +22,7 @@ * Declaration of GHOST_Buttons struct. */ -#ifndef __GHOST_BUTTONS_H__ -#define __GHOST_BUTTONS_H__ +#pragma once #include "GHOST_Types.h" @@ -62,5 +61,3 @@ struct GHOST_Buttons { GHOST_TUns8 m_ButtonMiddle : 1; GHOST_TUns8 m_ButtonRight : 1; }; - -#endif // __GHOST_BUTTONS_H__ diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h index 9c3fc642209..a1664e77717 100644 --- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h @@ -22,8 +22,7 @@ * Declaration of GHOST_CallbackEventConsumer class. */ -#ifndef __GHOST_CALLBACKEVENTCONSUMER_H__ -#define __GHOST_CALLBACKEVENTCONSUMER_H__ +#pragma once #include "GHOST_C-api.h" #include "GHOST_IEventConsumer.h" @@ -66,5 +65,3 @@ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_CallbackEventConsumer") #endif }; - -#endif // __GHOST_CALLBACKEVENTCONSUMER_H__ diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h index 411a7de5c79..33eeacbb203 100644 --- a/intern/ghost/intern/GHOST_Context.h +++ b/intern/ghost/intern/GHOST_Context.h @@ -22,8 +22,7 @@ * Declaration of GHOST_Context class. */ -#ifndef __GHOST_CONTEXT_H__ -#define __GHOST_CONTEXT_H__ +#pragma once #include "GHOST_IContext.h" #include "GHOST_Types.h" @@ -160,5 +159,3 @@ bool win32_silent_chk(bool result); # define WIN32_CHK_SILENT(x, silent) ((silent) ? win32_silent_chk(x) : WIN32_CHK(x)) #endif /* _WIN32 */ - -#endif // __GHOST_CONTEXT_H__ diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h index 37c1ac34299..7b1e186dede 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.h +++ b/intern/ghost/intern/GHOST_ContextCGL.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_CONTEXTCGL_H__ -#define __GHOST_CONTEXTCGL_H__ +#pragma once #include "GHOST_Context.h" @@ -137,5 +136,3 @@ class GHOST_ContextCGL : public GHOST_Context { void metalUpdateFramebuffer(); void metalSwapBuffers(); }; - -#endif // __GHOST_CONTEXTCGL_H__ diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h index c482992a6e2..e85516838fc 100644 --- a/intern/ghost/intern/GHOST_ContextD3D.h +++ b/intern/ghost/intern/GHOST_ContextD3D.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_CONTEXTD3D_H__ -#define __GHOST_CONTEXTD3D_H__ +#pragma once #ifndef WIN32 # error WIN32 only! @@ -132,5 +131,3 @@ class GHOST_ContextD3D : public GHOST_Context { ID3D11Device *m_device; ID3D11DeviceContext *m_device_ctx; }; - -#endif /* __GHOST_CONTEXTD3D_H__ */ diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h index da5ca7ef93f..e5dae0d22a8 100644 --- a/intern/ghost/intern/GHOST_ContextEGL.h +++ b/intern/ghost/intern/GHOST_ContextEGL.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_CONTEXTEGL_H__ -#define __GHOST_CONTEXTEGL_H__ +#pragma once #include "GHOST_Context.h" @@ -137,5 +136,3 @@ class GHOST_ContextEGL : public GHOST_Context { static HMODULE s_d3dcompiler; #endif }; - -#endif // __GHOST_CONTEXTEGL_H__ diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h index 07d2601cd17..e5654b1aed7 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.h +++ b/intern/ghost/intern/GHOST_ContextGLX.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_CONTEXTGLX_H__ -#define __GHOST_CONTEXTGLX_H__ +#pragma once #include "GHOST_Context.h" @@ -128,5 +127,3 @@ class GHOST_ContextGLX : public GHOST_Context { /* used to get GLX info */ int GHOST_X11_GL_GetAttributes( int *attribs, int attribs_max, bool is_stereo_visual, bool need_alpha, bool for_fb_config); - -#endif // __GHOST_CONTEXTGLX_H__ diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h index 2a3c08701b4..b1ac349e4a7 100644 --- a/intern/ghost/intern/GHOST_ContextNone.h +++ b/intern/ghost/intern/GHOST_ContextNone.h @@ -23,8 +23,7 @@ * Declaration of GHOST_Context class. */ -#ifndef __GHOST_CONTEXTNONE_H__ -#define __GHOST_CONTEXTNONE_H__ +#pragma once #include "GHOST_Context.h" @@ -86,5 +85,3 @@ class GHOST_ContextNone : public GHOST_Context { private: int m_swapInterval; }; - -#endif // __GHOST_CONTEXTNONE_H__ diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h index 670d930e1e7..ead2e91181c 100644 --- a/intern/ghost/intern/GHOST_ContextSDL.h +++ b/intern/ghost/intern/GHOST_ContextSDL.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_CONTEXTSDL_H__ -#define __GHOST_CONTEXTSDL_H__ +#pragma once #include "GHOST_Context.h" @@ -121,5 +120,3 @@ class GHOST_ContextSDL : public GHOST_Context { static SDL_GLContext s_sharedContext; static int s_sharedCount; }; - -#endif // __GHOST_CONTEXTSDL_H__ diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h index a8d2c18b463..087fca100e4 100644 --- a/intern/ghost/intern/GHOST_ContextWGL.h +++ b/intern/ghost/intern/GHOST_ContextWGL.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_CONTEXTWGL_H__ -#define __GHOST_CONTEXTWGL_H__ +#pragma once //#define WIN32_COMPOSITING @@ -130,5 +129,3 @@ class GHOST_ContextWGL : public GHOST_Context { static HGLRC s_sharedHGLRC; static int s_sharedCount; }; - -#endif // __GHOST_CONTEXTWGL_H__ diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index 5b5c2688297..424f95aa573 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -22,8 +22,7 @@ * Macro's used in GHOST debug target. */ -#ifndef __GHOST_DEBUG_H__ -#define __GHOST_DEBUG_H__ +#pragma once #ifdef _MSC_VER # ifdef DEBUG @@ -79,5 +78,3 @@ #else // WITH_GHOST_DEBUG # define GHOST_ASSERT(x, info) ((void)0) #endif // WITH_GHOST_DEBUG - -#endif // __GHOST_DEBUG_H__ diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h index 58b36c0035b..67b9aada55f 100644 --- a/intern/ghost/intern/GHOST_DisplayManager.h +++ b/intern/ghost/intern/GHOST_DisplayManager.h @@ -22,8 +22,7 @@ * Declaration of GHOST_DisplayManager class. */ -#ifndef __GHOST_DISPLAYMANAGER_H__ -#define __GHOST_DISPLAYMANAGER_H__ +#pragma once #include "GHOST_Types.h" @@ -127,5 +126,3 @@ class GHOST_DisplayManager { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_DisplayManager") #endif }; - -#endif // __GHOST_DISPLAYMANAGER_H__ diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h index c99e93279f7..5edd555a78b 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h @@ -22,8 +22,7 @@ * Declaration of GHOST_DisplayManagerCocoa class. */ -#ifndef __GHOST_DISPLAYMANAGERCOCOA_H__ -#define __GHOST_DISPLAYMANAGERCOCOA_H__ +#pragma once #ifndef __APPLE__ # error Apple only! @@ -93,5 +92,3 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { /** Cached display id's for each display. */ // CGDirectDisplayID* m_displayIDs; }; - -#endif // __GHOST_DISPLAYMANAGERCOCOA_H__ diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h index 266a3e9a699..4ca06faec12 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerNULL.h +++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h @@ -19,8 +19,7 @@ * Declaration of GHOST_DisplayManagerNULL class. */ -#ifndef __GHOST_DISPLAYMANAGERNULL_H__ -#define __GHOST_DISPLAYMANAGERNULL_H__ +#pragma once #include "GHOST_DisplayManager.h" #include "GHOST_SystemNULL.h" @@ -58,5 +57,3 @@ class GHOST_DisplayManagerNULL : public GHOST_DisplayManager { private: GHOST_SystemNULL *m_system; }; - -#endif /* __GHOST_DISPLAYMANAGERNULL_H__ */ diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.h b/intern/ghost/intern/GHOST_DisplayManagerSDL.h index f7704d57ab0..9a79a842057 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerSDL.h +++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.h @@ -19,8 +19,7 @@ * Declaration of GHOST_DisplayManagerSDL class. */ -#ifndef __GHOST_DISPLAYMANAGERSDL_H__ -#define __GHOST_DISPLAYMANAGERSDL_H__ +#pragma once #include "GHOST_DisplayManager.h" @@ -58,5 +57,3 @@ class GHOST_DisplayManagerSDL : public GHOST_DisplayManager { GHOST_SystemSDL *m_system; SDL_DisplayMode m_mode; }; - -#endif /* __GHOST_DISPLAYMANAGERSDL_H__ */ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h index c4ad90b1de7..3392d515c16 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h @@ -22,8 +22,7 @@ * Declaration of GHOST_DisplayManagerWin32 class. */ -#ifndef __GHOST_DISPLAYMANAGERWIN32_H__ -#define __GHOST_DISPLAYMANAGERWIN32_H__ +#pragma once #ifndef WIN32 # error WIN32 only! @@ -87,5 +86,3 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { protected: }; - -#endif // __GHOST_DISPLAYMANAGERWIN32_H__ diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h index 941152aa034..a36ff8d49f1 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.h +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h @@ -22,8 +22,7 @@ * Declaration of GHOST_DisplayManagerX11 class. */ -#ifndef __GHOST_DISPLAYMANAGERX11_H__ -#define __GHOST_DISPLAYMANAGERX11_H__ +#pragma once #include "GHOST_DisplayManager.h" @@ -86,5 +85,3 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { private: GHOST_SystemX11 *m_system; }; - -#endif // diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index ee75c017981..ecce3a68835 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_DROPTARGETWIN32_H__ -#define __GHOST_DROPTARGETWIN32_H__ +#pragma once #include "GHOST_SystemWin32.h" #include "GHOST_WindowWin32.h" @@ -150,5 +149,3 @@ class GHOST_DropTargetWin32 : public IDropTarget { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_DropTargetWin32") #endif }; - -#endif // __GHOST_DROPTARGETWIN32_H__ diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h index 9ca12442085..066f2f6bba2 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.h +++ b/intern/ghost/intern/GHOST_DropTargetX11.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_DROPTARGETX11_H__ -#define __GHOST_DROPTARGETX11_H__ +#pragma once #include "GHOST_SystemX11.h" #include "GHOST_WindowX11.h" @@ -126,5 +125,3 @@ class GHOST_DropTargetX11 { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_DropTargetX11") #endif }; - -#endif // __GHOST_DROPTARGETX11_H__ diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h index 2c14df7f243..845d62fa810 100644 --- a/intern/ghost/intern/GHOST_Event.h +++ b/intern/ghost/intern/GHOST_Event.h @@ -22,8 +22,7 @@ * Declaration of GHOST_Event class. */ -#ifndef __GHOST_EVENT_H__ -#define __GHOST_EVENT_H__ +#pragma once #include "GHOST_IEvent.h" @@ -90,5 +89,3 @@ class GHOST_Event : public GHOST_IEvent { /** Pointer to the event data. */ GHOST_TEventDataPtr m_data; }; - -#endif // __GHOST_EVENT_H__ diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h index 4247ae150a4..7072e0c5409 100644 --- a/intern/ghost/intern/GHOST_EventButton.h +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventButton class. */ -#ifndef __GHOST_EVENTBUTTON_H__ -#define __GHOST_EVENTBUTTON_H__ +#pragma once #include "GHOST_Event.h" #include "GHOST_Window.h" @@ -57,5 +56,3 @@ class GHOST_EventButton : public GHOST_Event { /** The button event data. */ GHOST_TEventButtonData m_buttonEventData; }; - -#endif // __GHOST_EVENTBUTTON_H__ diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h index 8ba657fd9fa..ba85cd74723 100644 --- a/intern/ghost/intern/GHOST_EventCursor.h +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventCursor class. */ -#ifndef __GHOST_EVENTCURSOR_H__ -#define __GHOST_EVENTCURSOR_H__ +#pragma once #include "GHOST_Event.h" @@ -58,5 +57,3 @@ class GHOST_EventCursor : public GHOST_Event { /** The x,y-coordinates of the cursor position. */ GHOST_TEventCursorData m_cursorEventData; }; - -#endif // __GHOST_EVENTCURSOR_H__ diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index 36291e8a254..10975792993 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_EVENTDRAGNDROP_H__ -#define __GHOST_EVENTDRAGNDROP_H__ +#pragma once #include "GHOST_Event.h" extern "C" { @@ -122,5 +121,3 @@ class GHOST_EventDragnDrop : public GHOST_Event { /** The x,y-coordinates of the cursor position. */ GHOST_TEventDragnDropData m_dragnDropEventData; }; - -#endif // __GHOST_EVENTDRAGNDROP_H__ diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h index 8f59c555914..cb71b452d80 100644 --- a/intern/ghost/intern/GHOST_EventKey.h +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventKey class. */ -#ifndef __GHOST_EVENTKEY_H__ -#define __GHOST_EVENTKEY_H__ +#pragma once #include <string.h> @@ -84,5 +83,3 @@ class GHOST_EventKey : public GHOST_Event { /** The key event data. */ GHOST_TEventKeyData m_keyEventData; }; - -#endif // __GHOST_EVENTKEY_H__ diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index ada5abda89b..befbdc72a5c 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventManager class. */ -#ifndef __GHOST_EVENTMANAGER_H__ -#define __GHOST_EVENTMANAGER_H__ +#pragma once #include <deque> #include <vector> @@ -140,5 +139,3 @@ class GHOST_EventManager { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_EventManager") #endif }; - -#endif // __GHOST_EVENTMANAGER_H__ diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index 196d3868ccd..64e67434b74 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_EVENTNDOF_H__ -#define __GHOST_EVENTNDOF_H__ +#pragma once #ifndef WITH_INPUT_NDOF # error NDOF code included in non-NDOF-enabled build @@ -50,5 +49,3 @@ class GHOST_EventNDOFButton : public GHOST_Event { m_data = &m_buttonData; } }; - -#endif // __GHOST_EVENTNDOF_H__ diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h index ead16525ec6..42de4da5ee5 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.h +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventPrinter class. */ -#ifndef __GHOST_EVENTPRINTER_H__ -#define __GHOST_EVENTPRINTER_H__ +#pragma once #include "GHOST_IEventConsumer.h" @@ -48,5 +47,3 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer { */ void getKeyString(GHOST_TKey key, char str[32]) const; }; - -#endif // __GHOST_EVENTPRINTER_H__ diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h index f0d3ffb9e91..8cd24a8a78b 100644 --- a/intern/ghost/intern/GHOST_EventString.h +++ b/intern/ghost/intern/GHOST_EventString.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventString class. */ -#ifndef __GHOST_EVENTSTRING_H__ -#define __GHOST_EVENTSTRING_H__ +#pragma once #include "GHOST_Event.h" @@ -54,5 +53,3 @@ class GHOST_EventString : public GHOST_Event { free(m_data); } }; - -#endif // __GHOST_EVENTSTRING_H__ diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h index 795e969b16d..a22f8a34fad 100644 --- a/intern/ghost/intern/GHOST_EventTrackpad.h +++ b/intern/ghost/intern/GHOST_EventTrackpad.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventTrackpad class. */ -#ifndef __GHOST_EVENTTRACKPAD_H__ -#define __GHOST_EVENTTRACKPAD_H__ +#pragma once #include "GHOST_Event.h" @@ -61,5 +60,3 @@ class GHOST_EventTrackpad : public GHOST_Event { /** The mouse pan data */ GHOST_TEventTrackpadData m_trackpadEventData; }; - -#endif // _GHOST_EVENT_PAN_H_ diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h index 4d3eeb9cd83..ea62e02d08d 100644 --- a/intern/ghost/intern/GHOST_EventWheel.h +++ b/intern/ghost/intern/GHOST_EventWheel.h @@ -22,8 +22,7 @@ * Declaration of GHOST_EventWheel class. */ -#ifndef __GHOST_EVENTWHEEL_H__ -#define __GHOST_EVENTWHEEL_H__ +#pragma once #include "GHOST_Event.h" @@ -51,5 +50,3 @@ class GHOST_EventWheel : public GHOST_Event { /** The z-displacement of the mouse wheel. */ GHOST_TEventWheelData m_wheelEventData; }; - -#endif // __GHOST_EVENTWHEEL_H__ diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h index b199c5f9b28..de8bf9f1a5a 100644 --- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h +++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_IXRGRAPHICSBINDING_H__ -#define __GHOST_IXRGRAPHICSBINDING_H__ +#pragma once #include <memory> #include <string> @@ -71,5 +70,3 @@ class GHOST_IXrGraphicsBinding { std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType( GHOST_TXrGraphicsBinding type, GHOST_Context *ghost_ctx); - -#endif /* __GHOST_IXRGRAPHICSBINDING_H__ */ diff --git a/intern/ghost/intern/GHOST_IconX11.h b/intern/ghost/intern/GHOST_IconX11.h index c5bcf4bedeb..615a7dae6b5 100644 --- a/intern/ghost/intern/GHOST_IconX11.h +++ b/intern/ghost/intern/GHOST_IconX11.h @@ -22,8 +22,7 @@ * Icon image data for X11. */ -#ifndef __GHOST_ICONX11_H__ -#define __GHOST_ICONX11_H__ +#pragma once /* * import bpy @@ -1013,5 +1012,3 @@ static const unsigned long BLENDER_ICONS_WM_X11[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; - -#endif // __GHOST_ICONX11_H__ diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index 112217023a7..74698d50659 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -23,8 +23,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_IME_H__ -#define __GHOST_IME_H__ +#pragma once #ifdef WITH_INPUT_IME @@ -388,4 +387,3 @@ class GHOST_ImeWin32 { }; #endif // WITH_INPUT_IME -#endif // __GHOST_IME_H__ diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h index 27ad4034068..c41ce8b7f39 100644 --- a/intern/ghost/intern/GHOST_ModifierKeys.h +++ b/intern/ghost/intern/GHOST_ModifierKeys.h @@ -22,8 +22,7 @@ * Declaration of GHOST_ModifierKeys struct. */ -#ifndef __GHOST_MODIFIERKEYS_H__ -#define __GHOST_MODIFIERKEYS_H__ +#pragma once #include "GHOST_Types.h" @@ -87,5 +86,3 @@ struct GHOST_ModifierKeys { /** Bitfield that stores the appropriate key state. */ GHOST_TUns8 m_OS : 1; }; - -#endif // __GHOST_MODIFIERKEYS_H__ diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index a190607ca66..d0b49bc13c2 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __GHOST_NDOFMANAGER_H__ -#define __GHOST_NDOFMANAGER_H__ +#pragma once #ifndef WITH_INPUT_NDOF # error NDOF code included in non-NDOF-enabled build @@ -167,5 +166,3 @@ class GHOST_NDOFManager { bool m_motionEventPending; float m_deadZone; // discard motion with each component < this }; - -#endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h index bd1e6903f94..f7c3599502e 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __GHOST_NDOFMANAGERCOCOA_H__ -#define __GHOST_NDOFMANAGERCOCOA_H__ +#pragma once #include "GHOST_NDOFManager.h" @@ -29,5 +28,3 @@ class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager { bool available(); }; - -#endif // #include guard diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h index 75bd022631a..6dd4289ffac 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __GHOST_NDOFMANAGERUNIX_H__ -#define __GHOST_NDOFMANAGERUNIX_H__ +#pragma once #include "GHOST_NDOFManager.h" @@ -32,5 +31,3 @@ class GHOST_NDOFManagerUnix : public GHOST_NDOFManager { private: bool m_available; }; - -#endif /* __GHOST_NDOFMANAGERUNIX_H__ */ diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h index 9ed5e6ab978..62d9b9207dc 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.h +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __GHOST_NDOFMANAGERWIN32_H__ -#define __GHOST_NDOFMANAGERWIN32_H__ +#pragma once #include "GHOST_NDOFManager.h" @@ -24,5 +23,3 @@ class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager { GHOST_NDOFManagerWin32(GHOST_System &); bool available(); }; - -#endif // #include guard diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index c2d712c11cd..e29a9ba0c29 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -22,8 +22,7 @@ * Declaration of GHOST_System class. */ -#ifndef __GHOST_SYSTEM_H__ -#define __GHOST_SYSTEM_H__ +#pragma once #include "GHOST_ISystem.h" @@ -424,5 +423,3 @@ inline GHOST_NDOFManager *GHOST_System::getNDOFManager() const return m_ndofManager; } #endif - -#endif // __GHOST_SYSTEM_H__ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index bbd6f1d8995..8e36cebb88a 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -22,8 +22,7 @@ * Declaration of GHOST_SystemCocoa class. */ -#ifndef __GHOST_SYSTEMCOCOA_H__ -#define __GHOST_SYSTEMCOCOA_H__ +#pragma once #ifndef __APPLE__ # error Apple OSX only! @@ -313,5 +312,3 @@ class GHOST_SystemCocoa : public GHOST_System { /** Is the scroll wheel event generated by a multitouch trackpad or mouse? */ bool m_multiTouchScroll; }; - -#endif // __GHOST_SYSTEMCOCOA_H__ diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h index 186cb92d1aa..5becf110b15 100644 --- a/intern/ghost/intern/GHOST_SystemNULL.h +++ b/intern/ghost/intern/GHOST_SystemNULL.h @@ -19,8 +19,7 @@ * Declaration of GHOST_SystemNULL class. */ -#ifndef __GHOST_SYSTEMNULL_H__ -#define __GHOST_SYSTEMNULL_H__ +#pragma once #include "../GHOST_Types.h" #include "GHOST_DisplayManagerNULL.h" @@ -130,5 +129,3 @@ class GHOST_SystemNULL : public GHOST_System { ((glSettings.flags & GHOST_glStereoVisual) != 0)); } }; - -#endif /* __GHOST_SYSTEMNULL_H__ */ diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h index 04180a143cb..ab53b2813cd 100644 --- a/intern/ghost/intern/GHOST_SystemPaths.h +++ b/intern/ghost/intern/GHOST_SystemPaths.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_SYSTEMPATHS_H__ -#define __GHOST_SYSTEMPATHS_H__ +#pragma once #include "GHOST_ISystemPaths.h" @@ -70,5 +69,3 @@ class GHOST_SystemPaths : public GHOST_ISystemPaths { */ virtual void addToSystemRecentFiles(const char *filename) const = 0; }; - -#endif diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h index b66379649e7..188f6f02286 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_SYSTEMPATHSCOCOA_H__ -#define __GHOST_SYSTEMPATHSCOCOA_H__ +#pragma once #ifndef __APPLE__ # error Apple OSX only! @@ -67,5 +66,3 @@ class GHOST_SystemPathsCocoa : public GHOST_SystemPaths { */ void addToSystemRecentFiles(const char *filename) const; }; - -#endif // __GHOST_SYSTEMPATHSCOCOA_H__ diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.h b/intern/ghost/intern/GHOST_SystemPathsUnix.h index f9f89f6e79b..8d2f26a28aa 100644 --- a/intern/ghost/intern/GHOST_SystemPathsUnix.h +++ b/intern/ghost/intern/GHOST_SystemPathsUnix.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_SYSTEMPATHSUNIX_H__ -#define __GHOST_SYSTEMPATHSUNIX_H__ +#pragma once #include "../GHOST_Types.h" #include "GHOST_SystemPaths.h" @@ -65,5 +64,3 @@ class GHOST_SystemPathsUnix : public GHOST_SystemPaths { */ void addToSystemRecentFiles(const char *filename) const; }; - -#endif /* __GHOST_SYSTEMPATHSUNIX_H__ */ diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h index f1924ea51bc..1a1eab21bad 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.h +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h @@ -21,8 +21,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_SYSTEMPATHSWIN32_H__ -#define __GHOST_SYSTEMPATHSWIN32_H__ +#pragma once #ifndef WIN32 # error WIN32 only! @@ -74,5 +73,3 @@ class GHOST_SystemPathsWin32 : public GHOST_SystemPaths { */ void addToSystemRecentFiles(const char *filename) const; }; - -#endif // __GHOST_SYSTEMPATHSWIN32_H__ diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index 8feec9de61d..4b2c52f8282 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -19,8 +19,7 @@ * Declaration of GHOST_SystemSDL class. */ -#ifndef __GHOST_SYSTEMSDL_H__ -#define __GHOST_SYSTEMSDL_H__ +#pragma once #include "../GHOST_Types.h" #include "GHOST_DisplayManagerSDL.h" @@ -102,5 +101,3 @@ class GHOST_SystemSDL : public GHOST_System { /// The vector of windows that need to be updated. std::vector<GHOST_WindowSDL *> m_dirty_windows; }; - -#endif diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 89cd3406b69..30ee7679287 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -19,8 +19,7 @@ * Declaration of GHOST_SystemWayland class. */ -#ifndef __GHOST_SYSTEMWAYLAND_H__ -#define __GHOST_SYSTEMWAYLAND_H__ +#pragma once #include "../GHOST_Types.h" #include "GHOST_System.h" @@ -107,5 +106,3 @@ class GHOST_SystemWayland : public GHOST_System { struct display_t *d; std::string selection; }; - -#endif /* __GHOST_SYSTEMWAYLAND_H__ */ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 849aa5a96f5..f59b106afd6 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1143,10 +1143,16 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA BYTE state[256] = {0}; int r; GetKeyboardState((PBYTE)state); + bool ctrl_pressed = state[VK_CONTROL] & 0x80; + bool alt_pressed = state[VK_MENU] & 0x80; + /* No text with control key pressed (Alt can be used to insert special characters though!). */ + if (ctrl_pressed && !alt_pressed) { + utf8_char[0] = '\0'; + } // Don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical // composition. - if (MapVirtualKeyW(vk, 2) != 0) { + else if (MapVirtualKeyW(vk, 2) != 0) { // todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here). // Could be up to 24 utf8 bytes. if ((r = ToUnicodeEx( diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 6b7901c2ade..24925b9c403 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -22,8 +22,7 @@ * Declaration of GHOST_SystemWin32 class. */ -#ifndef __GHOST_SYSTEMWIN32_H__ -#define __GHOST_SYSTEMWIN32_H__ +#pragma once #ifndef WIN32 # error WIN32 only! @@ -488,4 +487,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void) } } } -#endif // __GHOST_SYSTEMWIN32_H__ diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 5888605ec95..ad58138d416 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -22,8 +22,7 @@ * Declaration of GHOST_SystemX11 class. */ -#ifndef __GHOST_SYSTEMX11_H__ -#define __GHOST_SYSTEMX11_H__ +#pragma once #include <X11/XKBlib.h> /* allow detectable autorepeate */ #include <X11/Xlib.h> @@ -392,5 +391,3 @@ class GHOST_SystemX11 : public GHOST_System { bool generateWindowExposeEvents(); }; - -#endif diff --git a/intern/ghost/intern/GHOST_TaskbarWin32.h b/intern/ghost/intern/GHOST_TaskbarWin32.h index 58641123c24..e6464f5e626 100644 --- a/intern/ghost/intern/GHOST_TaskbarWin32.h +++ b/intern/ghost/intern/GHOST_TaskbarWin32.h @@ -17,8 +17,7 @@ /** \file * \ingroup GHOST */ -#ifndef __GHOST_TASKBARWIN32_H__ -#define __GHOST_TASKBARWIN32_H__ +#pragma once #ifndef WIN32 # error WIN32 only! @@ -128,5 +127,3 @@ class ITaskbarList3 : public ITaskbarList2 { virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip(HWND hwnd, RECT *prcClip) = 0; }; #endif /* ITaskbarList3 */ - -#endif /*__GHOST_TASKBARWIN32_H__*/ diff --git a/intern/ghost/intern/GHOST_TaskbarX11.h b/intern/ghost/intern/GHOST_TaskbarX11.h index cd00e25106c..25de5aa9511 100644 --- a/intern/ghost/intern/GHOST_TaskbarX11.h +++ b/intern/ghost/intern/GHOST_TaskbarX11.h @@ -17,8 +17,7 @@ /** \file * \ingroup GHOST */ -#ifndef __GHOST_TASKBARX11_H__ -#define __GHOST_TASKBARX11_H__ +#pragma once class GHOST_TaskBarX11 { public: @@ -34,5 +33,3 @@ class GHOST_TaskBarX11 { private: void *handle; }; - -#endif /*__GHOST_TASKBARX11_H__*/ diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h index 039663a7a0e..2e0f5d42230 100644 --- a/intern/ghost/intern/GHOST_TimerManager.h +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -22,8 +22,7 @@ * Declaration of GHOST_TimerManager class. */ -#ifndef __GHOST_TIMERMANAGER_H__ -#define __GHOST_TIMERMANAGER_H__ +#pragma once #include <vector> @@ -112,5 +111,3 @@ class GHOST_TimerManager { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_TimerManager") #endif }; - -#endif // __GHOST_TIMERMANAGER_H__ diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h index 561d9b3e705..6dc0728e19b 100644 --- a/intern/ghost/intern/GHOST_TimerTask.h +++ b/intern/ghost/intern/GHOST_TimerTask.h @@ -22,8 +22,7 @@ * Declaration of GHOST_TimerTask class. */ -#ifndef __GHOST_TIMERTASK_H__ -#define __GHOST_TIMERTASK_H__ +#pragma once #include "GHOST_ITimerTask.h" @@ -179,5 +178,3 @@ class GHOST_TimerTask : public GHOST_ITimerTask { /** Auxiliary storage room. */ GHOST_TUns32 m_auxData; }; - -#endif // __GHOST_TIMERTASK_H__ diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 7cfea5110c5..c8c21b2b08f 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -22,8 +22,7 @@ * Declaration of GHOST_Window class. */ -#ifndef __GHOST_WINDOW_H__ -#define __GHOST_WINDOW_H__ +#pragma once #include "GHOST_IWindow.h" @@ -456,5 +455,3 @@ inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const { return m_cursorShape; } - -#endif // _GHOST_WINDOW_H diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 15429eab5db..97486c9e77a 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -22,8 +22,7 @@ * Declaration of GHOST_WindowCocoa class. */ -#ifndef __GHOST_WINDOWCOCOA_H__ -#define __GHOST_WINDOWCOCOA_H__ +#pragma once #ifndef __APPLE__ # error Apple OSX only! @@ -327,5 +326,3 @@ class GHOST_WindowCocoa : public GHOST_Window { bool m_debug_context; // for debug messages during context setup bool m_is_dialog; }; - -#endif // __GHOST_WINDOWCOCOA_H__ diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h index 661439191c5..34fdfd30f27 100644 --- a/intern/ghost/intern/GHOST_WindowManager.h +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -22,8 +22,7 @@ * Declaration of GHOST_WindowManager class. */ -#ifndef __GHOST_WINDOWMANAGER_H__ -#define __GHOST_WINDOWMANAGER_H__ +#pragma once #include <vector> @@ -149,5 +148,3 @@ class GHOST_WindowManager { MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_WindowManager") #endif }; - -#endif // __GHOST_WINDOWMANAGER_H__ diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index e1aa0cb7f13..0b5a7ee3450 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -19,8 +19,7 @@ * Declaration of GHOST_WindowNULL class. */ -#ifndef __GHOST_WINDOWNULL_H__ -#define __GHOST_WINDOWNULL_H__ +#pragma once #include "GHOST_Window.h" @@ -177,5 +176,3 @@ class GHOST_WindowNULL : public GHOST_Window { return NULL; } }; - -#endif // __GHOST_WINDOWNULL_H__ diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index 5039c742c9d..643c54c282e 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -19,8 +19,7 @@ * Declaration of GHOST_WindowSDL class. */ -#ifndef __GHOST_WINDOWSDL_H__ -#define __GHOST_WINDOWSDL_H__ +#pragma once #include "GHOST_SystemSDL.h" #include "GHOST_Window.h" @@ -149,5 +148,3 @@ class GHOST_WindowSDL : public GHOST_Window { GHOST_TUns16 getDPIHint(); }; - -#endif // __GHOST_WINDOWSDL_H__ diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index ff1eb60e154..1ee41f4d0f6 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -20,8 +20,7 @@ * Declaration of GHOST_WindowWayland class. */ -#ifndef __GHOST_WINDOWWAYLAND_H__ -#define __GHOST_WINDOWWAYLAND_H__ +#pragma once #include "GHOST_Window.h" @@ -124,5 +123,3 @@ class GHOST_WindowWayland : public GHOST_Window { */ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override; }; - -#endif // __GHOST_WINDOWWAYLAND_H__ diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index dbed7c5ee5f..224ff53bf7b 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -22,8 +22,7 @@ * Declaration of GHOST_WindowWin32 class. */ -#ifndef __GHOST_WINDOWWIN32_H__ -#define __GHOST_WINDOWWIN32_H__ +#pragma once #ifndef WIN32 # error WIN32 only! @@ -586,5 +585,3 @@ class GHOST_WindowWin32 : public GHOST_Window { #endif bool m_debug_context; }; - -#endif // __GHOST_WINDOWWIN32_H__ diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 4232ff40b52..ef5d1755f1a 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -22,8 +22,7 @@ * Declaration of GHOST_WindowX11 class. */ -#ifndef __GHOST_WINDOWX11_H__ -#define __GHOST_WINDOWX11_H__ +#pragma once #include "GHOST_Window.h" #include <X11/Xlib.h> @@ -288,5 +287,3 @@ class GHOST_WindowX11 : public GHOST_Window { void motifFullScreen(bool set); bool motifIsFullScreen() const; }; - -#endif // __GHOST_WINDOWX11_H__ diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h index 9be57cd90cc..d2edb40c080 100644 --- a/intern/ghost/intern/GHOST_XrContext.h +++ b/intern/ghost/intern/GHOST_XrContext.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_XRCONTEXT_H__ -#define __GHOST_XRCONTEXT_H__ +#pragma once #include <memory> #include <vector> @@ -131,5 +130,3 @@ class GHOST_XrContext : public GHOST_IXrContext { GHOST_TXrGraphicsBinding determineGraphicsBindingTypeToEnable( const GHOST_XrContextCreateInfo *create_info); }; - -#endif // __GHOST_XRCONTEXT_H__ diff --git a/intern/ghost/intern/GHOST_XrException.h b/intern/ghost/intern/GHOST_XrException.h index 9f779961e4f..30c33eaf98f 100644 --- a/intern/ghost/intern/GHOST_XrException.h +++ b/intern/ghost/intern/GHOST_XrException.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_XREXCEPTION_H__ -#define __GHOST_XREXCEPTION_H__ +#pragma once #include <exception> @@ -41,5 +40,3 @@ class GHOST_XrException : public std::exception { const char *m_msg; int m_result; }; - -#endif // __GHOST_XREXCEPTION_H__ diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h index da0128b2851..74555c0c170 100644 --- a/intern/ghost/intern/GHOST_XrSession.h +++ b/intern/ghost/intern/GHOST_XrSession.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_XRSESSION_H__ -#define __GHOST_XRSESSION_H__ +#pragma once #include <map> #include <memory> @@ -84,5 +83,3 @@ class GHOST_XrSession { void beginFrameDrawing(); void endFrameDrawing(std::vector<XrCompositionLayerBaseHeader *> *layers); }; - -#endif /* GHOST_XRSESSION_H__ */ diff --git a/intern/ghost/intern/GHOST_XrSwapchain.h b/intern/ghost/intern/GHOST_XrSwapchain.h index 7a3e7fcea68..33a1c17b993 100644 --- a/intern/ghost/intern/GHOST_XrSwapchain.h +++ b/intern/ghost/intern/GHOST_XrSwapchain.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_XRSWAPCHAIN_H__ -#define __GHOST_XRSWAPCHAIN_H__ +#pragma once #include <memory> @@ -45,5 +44,3 @@ class GHOST_XrSwapchain { int32_t m_image_width, m_image_height; bool m_is_srgb_buffer = false; }; - -#endif // GHOST_XRSWAPCHAIN_H diff --git a/intern/ghost/intern/GHOST_Xr_intern.h b/intern/ghost/intern/GHOST_Xr_intern.h index d59ffd31940..137541c4528 100644 --- a/intern/ghost/intern/GHOST_Xr_intern.h +++ b/intern/ghost/intern/GHOST_Xr_intern.h @@ -18,8 +18,7 @@ * \ingroup GHOST */ -#ifndef __GHOST_XR_INTERN_H__ -#define __GHOST_XR_INTERN_H__ +#pragma once #include <memory> #include <vector> @@ -46,5 +45,3 @@ (void)_res; \ } \ (void)0 - -#endif /* __GHOST_XR_INTERN_H__ */ diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h index 9cac43b1549..d1deaeb0d1a 100644 --- a/intern/ghost/intern/GHOST_Xr_openxr_includes.h +++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h @@ -22,8 +22,7 @@ * installed. */ -#ifndef __GHOST_XR_SYSTEM_INCLUDES_H__ -#define __GHOST_XR_SYSTEM_INCLUDES_H__ +#pragma once /* Platform headers */ #ifdef XR_USE_PLATFORM_WIN32 @@ -48,5 +47,3 @@ #include <openxr/openxr.h> #include <openxr/openxr_platform.h> - -#endif /* __GHOST_XR_SYSTEM_INCLUDES_H__ */ diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt index cb24df65ba0..1ab365a376a 100644 --- a/intern/guardedalloc/CMakeLists.txt +++ b/intern/guardedalloc/CMakeLists.txt @@ -28,6 +28,7 @@ set(INC_SYS ) set(SRC + ./intern/leak_detector.cc ./intern/mallocn.c ./intern/mallocn_guarded_impl.c ./intern/mallocn_lockfree_impl.c diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index 1318aa10697..604330bd1d3 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -211,6 +211,10 @@ extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT; extern const char *(*MEM_name_ptr)(void *vmemh); #endif +/** This should be called as early as possible in the program. When it has been called, information + * about memory leaks will be printed on exit. */ +void MEM_initialize_memleak_detection(void); + /* Switch allocator to slower but fully guarded mode. */ void MEM_use_guarded_allocator(void); diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc new file mode 100644 index 00000000000..4b2689ee28c --- /dev/null +++ b/intern/guardedalloc/intern/leak_detector.cc @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/** \file + * \ingroup MEM + */ + +#include "MEM_guardedalloc.h" +#include "mallocn_intern.h" + +bool leak_detector_has_run = false; +char free_after_leak_detection_message[] = + "Freeing memory after the leak detector has run. This can happen when using " + "static variables in C++ that are defined outside of functions. To fix this " + "error, use the 'construct on first use' idiom."; + +namespace { +class MemLeakPrinter { + public: + ~MemLeakPrinter() + { + leak_detector_has_run = true; + const uint leaked_blocks = MEM_get_memory_blocks_in_use(); + if (leaked_blocks == 0) { + return; + } + const size_t mem_in_use = MEM_get_memory_in_use(); + printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", + leaked_blocks, + (double)mem_in_use / 1024 / 1024); + MEM_printmemlist(); + } +}; +} // namespace + +void MEM_initialize_memleak_detection(void) +{ + /** + * This variable is constructed when this function is first called. This should happen as soon as + * possible when the program starts. + * + * It is destructed when the program exits. During destruction, it will print information about + * leaked memory blocks. Static variables are destructed in reversed order of their + * construction. Therefore, all static variables that own memory have to be constructed after + * this function has been called. + */ + static MemLeakPrinter printer; +} diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c index 5e523204020..2c207935e43 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.c +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c @@ -898,6 +898,10 @@ void MEM_guarded_freeN(void *vmemh) memt = (MemTail *)(((char *)memh) + sizeof(MemHead) + memh->len); if (memt->tag3 == MEMTAG3) { + if (leak_detector_has_run) { + MemorY_ErroR(memh->name, free_after_leak_detection_message); + } + memh->tag1 = MEMFREE; memh->tag2 = MEMFREE; memt->tag3 = MEMFREE; diff --git a/intern/guardedalloc/intern/mallocn_inline.h b/intern/guardedalloc/intern/mallocn_inline.h index f8bb7861fc9..4e73eb9bad6 100644 --- a/intern/guardedalloc/intern/mallocn_inline.h +++ b/intern/guardedalloc/intern/mallocn_inline.h @@ -33,6 +33,10 @@ #ifndef __MALLOCN_INLINE_H__ #define __MALLOCN_INLINE_H__ +#ifdef __cplusplus +extern "C" { +#endif + MEM_INLINE bool MEM_size_safe_multiply(size_t a, size_t b, size_t *result) { /* A size_t with its high-half bits all set to 1. */ @@ -52,4 +56,8 @@ MEM_INLINE bool MEM_size_safe_multiply(size_t a, size_t b, size_t *result) return ((high_bits & (a | b)) == 0 || (*result / b == a)); } +#ifdef __cplusplus +} +#endif + #endif /* __MALLOCN_INLINE_H__ */ diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h index ef8845a66b3..8fc3e432157 100644 --- a/intern/guardedalloc/intern/mallocn_intern.h +++ b/intern/guardedalloc/intern/mallocn_intern.h @@ -100,11 +100,18 @@ size_t malloc_usable_size(void *ptr); #include "mallocn_inline.h" +#ifdef __cplusplus +extern "C" { +#endif + #define ALIGNED_MALLOC_MINIMUM_ALIGNMENT sizeof(void *) void *aligned_malloc(size_t size, size_t alignment); void aligned_free(void *ptr); +extern bool leak_detector_has_run; +extern char free_after_leak_detection_message[]; + /* Prototypes for counted allocator functions */ size_t MEM_lockfree_allocN_len(const void *vmemh) ATTR_WARN_UNUSED_RESULT; void MEM_lockfree_freeN(void *vmemh); @@ -191,4 +198,8 @@ size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT; const char *MEM_guarded_name_ptr(void *vmemh); #endif +#ifdef __cplusplus +} +#endif + #endif /* __MALLOCN_INTERN_H__ */ diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c index 205cc688d72..b71e2c963eb 100644 --- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c +++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c @@ -101,6 +101,10 @@ size_t MEM_lockfree_allocN_len(const void *vmemh) void MEM_lockfree_freeN(void *vmemh) { + if (leak_detector_has_run) { + print_error("%s\n", free_after_leak_detection_message); + } + MemHead *memh = MEMHEAD_FROM_PTR(vmemh); size_t len = MEM_lockfree_allocN_len(vmemh); diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp index 5438a005d7c..0d2486ceac7 100644 --- a/intern/itasc/Scene.cpp +++ b/intern/itasc/Scene.cpp @@ -16,532 +16,623 @@ namespace iTaSC { class SceneLock : public ControlledObject::JointLockCallback { -private: - Scene* m_scene; - Range m_qrange; - -public: - SceneLock(Scene* scene) : - m_scene(scene), m_qrange(0,0) {} - virtual ~SceneLock() {} - - void setRange(Range& range) - { - m_qrange = range; - } - // lock a joint, no need to update output - virtual void lockJoint(unsigned int q_nr, unsigned int ndof) - { - q_nr += m_qrange.start; - project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); - } - // lock a joint and update output in view of reiteration - virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double* qdot) - { - q_nr += m_qrange.start; - project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); - // update the output vector so that the movement of this joint will be - // taken into account and we can put the joint back in its initial position - // which means that the jacobian doesn't need to be changed - for (unsigned int i=0 ;i<ndof ; ++i, ++q_nr) { - m_scene->m_ydot -= m_scene->m_A.col(q_nr)*qdot[i]; - } - } + private: + Scene *m_scene; + Range m_qrange; + + public: + SceneLock(Scene *scene) : m_scene(scene), m_qrange(0, 0) + { + } + virtual ~SceneLock() + { + } + + void setRange(Range &range) + { + m_qrange = range; + } + // lock a joint, no need to update output + virtual void lockJoint(unsigned int q_nr, unsigned int ndof) + { + q_nr += m_qrange.start; + project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); + } + // lock a joint and update output in view of reiteration + virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double *qdot) + { + q_nr += m_qrange.start; + project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); + // update the output vector so that the movement of this joint will be + // taken into account and we can put the joint back in its initial position + // which means that the jacobian doesn't need to be changed + for (unsigned int i = 0; i < ndof; ++i, ++q_nr) { + m_scene->m_ydot -= m_scene->m_A.col(q_nr) * qdot[i]; + } + } }; -Scene::Scene(): - m_A(), m_B(), m_Atemp(), m_Wq(), m_Jf(), m_Jq(), m_Ju(), m_Cf(), m_Cq(), m_Jf_inv(), - m_Vf(),m_Uf(), m_Wy(), m_ydot(), m_qdot(), m_xdot(), m_Sf(),m_tempf(), - m_ncTotal(0),m_nqTotal(0),m_nuTotal(0),m_nsets(0), - m_solver(NULL),m_cache(NULL) +Scene::Scene() + : m_A(), + m_B(), + m_Atemp(), + m_Wq(), + m_Jf(), + m_Jq(), + m_Ju(), + m_Cf(), + m_Cq(), + m_Jf_inv(), + m_Vf(), + m_Uf(), + m_Wy(), + m_ydot(), + m_qdot(), + m_xdot(), + m_Sf(), + m_tempf(), + m_ncTotal(0), + m_nqTotal(0), + m_nuTotal(0), + m_nsets(0), + m_solver(NULL), + m_cache(NULL) { - m_minstep = 0.01; - m_maxstep = 0.06; + m_minstep = 0.01; + m_maxstep = 0.06; } -Scene::~Scene() +Scene::~Scene() { - ConstraintMap::iterator constraint_it; - while ((constraint_it = constraints.begin()) != constraints.end()) { - delete constraint_it->second; - constraints.erase(constraint_it); - } - ObjectMap::iterator object_it; - while ((object_it = objects.begin()) != objects.end()) { - delete object_it->second; - objects.erase(object_it); - } + ConstraintMap::iterator constraint_it; + while ((constraint_it = constraints.begin()) != constraints.end()) { + delete constraint_it->second; + constraints.erase(constraint_it); + } + ObjectMap::iterator object_it; + while ((object_it = objects.begin()) != objects.end()) { + delete object_it->second; + objects.erase(object_it); + } } bool Scene::setParam(SceneParam paramId, double value) { - switch (paramId) { - case MIN_TIMESTEP: - m_minstep = value; - break; - case MAX_TIMESTEP: - m_maxstep = value; - break; - default: - return false; - } - return true; + switch (paramId) { + case MIN_TIMESTEP: + m_minstep = value; + break; + case MAX_TIMESTEP: + m_maxstep = value; + break; + default: + return false; + } + return true; } -bool Scene::addObject(const std::string& name, Object* object, UncontrolledObject* base, const std::string& baseFrame) +bool Scene::addObject(const std::string &name, + Object *object, + UncontrolledObject *base, + const std::string &baseFrame) { - // finalize the object before adding - if (!object->finalize()) - return false; - //Check if Object is controlled or uncontrolled. - if(object->getType()==Object::Controlled){ - int baseFrameIndex = base->addEndEffector(baseFrame); - if (baseFrameIndex < 0) - return false; - std::pair<ObjectMap::iterator, bool> result; - if (base->getNrOfCoordinates() == 0) { - // base is fixed object, no coordinate range - result = objects.insert(ObjectMap::value_type( - name, new Object_struct(object,base,baseFrameIndex, - Range(m_nqTotal,object->getNrOfCoordinates()), - Range(m_ncTotal,((ControlledObject*)object)->getNrOfConstraints()), - Range(0,0)))); - } else { - // base is a moving object, must be in list already - ObjectMap::iterator base_it; - for (base_it=objects.begin(); base_it != objects.end(); base_it++) { - if (base_it->second->object == base) - break; - } - if (base_it == objects.end()) - return false; - result = objects.insert(ObjectMap::value_type( - name, new Object_struct(object,base,baseFrameIndex, - Range(m_nqTotal,object->getNrOfCoordinates()), - Range(m_ncTotal,((ControlledObject*)object)->getNrOfConstraints()), - base_it->second->coordinaterange))); - } - if (!result.second) { - return false; - } - m_nqTotal+=object->getNrOfCoordinates(); - m_ncTotal+=((ControlledObject*)object)->getNrOfConstraints(); - return true; + // finalize the object before adding + if (!object->finalize()) + return false; + // Check if Object is controlled or uncontrolled. + if (object->getType() == Object::Controlled) { + int baseFrameIndex = base->addEndEffector(baseFrame); + if (baseFrameIndex < 0) + return false; + std::pair<ObjectMap::iterator, bool> result; + if (base->getNrOfCoordinates() == 0) { + // base is fixed object, no coordinate range + result = objects.insert(ObjectMap::value_type( + name, + new Object_struct(object, + base, + baseFrameIndex, + Range(m_nqTotal, object->getNrOfCoordinates()), + Range(m_ncTotal, ((ControlledObject *)object)->getNrOfConstraints()), + Range(0, 0)))); + } + else { + // base is a moving object, must be in list already + ObjectMap::iterator base_it; + for (base_it = objects.begin(); base_it != objects.end(); base_it++) { + if (base_it->second->object == base) + break; + } + if (base_it == objects.end()) + return false; + result = objects.insert(ObjectMap::value_type( + name, + new Object_struct(object, + base, + baseFrameIndex, + Range(m_nqTotal, object->getNrOfCoordinates()), + Range(m_ncTotal, ((ControlledObject *)object)->getNrOfConstraints()), + base_it->second->coordinaterange))); } - if(object->getType()==Object::UnControlled){ - if ((WorldObject*)base != &Object::world) - return false; - std::pair<ObjectMap::iterator,bool> result = objects.insert(ObjectMap::value_type( - name,new Object_struct(object,base,0, - Range(0,0), - Range(0,0), - Range(m_nuTotal,object->getNrOfCoordinates())))); - if(!result.second) - return false; - m_nuTotal+=object->getNrOfCoordinates(); - return true; + if (!result.second) { + return false; } - return false; + m_nqTotal += object->getNrOfCoordinates(); + m_ncTotal += ((ControlledObject *)object)->getNrOfConstraints(); + return true; + } + if (object->getType() == Object::UnControlled) { + if ((WorldObject *)base != &Object::world) + return false; + std::pair<ObjectMap::iterator, bool> result = objects.insert( + ObjectMap::value_type(name, + new Object_struct(object, + base, + 0, + Range(0, 0), + Range(0, 0), + Range(m_nuTotal, object->getNrOfCoordinates())))); + if (!result.second) + return false; + m_nuTotal += object->getNrOfCoordinates(); + return true; + } + return false; } -bool Scene::addConstraintSet(const std::string& name,ConstraintSet* task,const std::string& object1,const std::string& object2, const std::string& ee1, const std::string& ee2) +bool Scene::addConstraintSet(const std::string &name, + ConstraintSet *task, + const std::string &object1, + const std::string &object2, + const std::string &ee1, + const std::string &ee2) { - //Check if objects exist: - ObjectMap::iterator object1_it = objects.find(object1); - ObjectMap::iterator object2_it = objects.find(object2); - if(object1_it==objects.end()||object2_it==objects.end()) - return false; - int ee1_index = object1_it->second->object->addEndEffector(ee1); - int ee2_index = object2_it->second->object->addEndEffector(ee2); - if (ee1_index < 0 || ee2_index < 0) - return false; - std::pair<ConstraintMap::iterator,bool> result = - constraints.insert(ConstraintMap::value_type(name,new ConstraintSet_struct( - task,object1_it,ee1_index,object2_it,ee2_index, - Range(m_ncTotal,task->getNrOfConstraints()),Range(6*m_nsets,6)))); - if(!result.second) - return false; - m_ncTotal+=task->getNrOfConstraints(); - m_nsets+=1; - return true; + // Check if objects exist: + ObjectMap::iterator object1_it = objects.find(object1); + ObjectMap::iterator object2_it = objects.find(object2); + if (object1_it == objects.end() || object2_it == objects.end()) + return false; + int ee1_index = object1_it->second->object->addEndEffector(ee1); + int ee2_index = object2_it->second->object->addEndEffector(ee2); + if (ee1_index < 0 || ee2_index < 0) + return false; + std::pair<ConstraintMap::iterator, bool> result = constraints.insert(ConstraintMap::value_type( + name, + new ConstraintSet_struct(task, + object1_it, + ee1_index, + object2_it, + ee2_index, + Range(m_ncTotal, task->getNrOfConstraints()), + Range(6 * m_nsets, 6)))); + if (!result.second) + return false; + m_ncTotal += task->getNrOfConstraints(); + m_nsets += 1; + return true; } -bool Scene::addSolver(Solver* _solver){ - if(m_solver==NULL){ - m_solver=_solver; - return true; - } - else - return false; +bool Scene::addSolver(Solver *_solver) +{ + if (m_solver == NULL) { + m_solver = _solver; + return true; + } + else + return false; } -bool Scene::addCache(Cache* _cache){ - if(m_cache==NULL){ - m_cache=_cache; - return true; - } - else - return false; +bool Scene::addCache(Cache *_cache) +{ + if (m_cache == NULL) { + m_cache = _cache; + return true; + } + else + return false; } -bool Scene::initialize(){ - - //prepare all matrices: - if (m_ncTotal == 0 || m_nqTotal == 0 || m_nsets == 0) - return false; - - m_A = e_zero_matrix(m_ncTotal,m_nqTotal); - if (m_nuTotal > 0) { - m_B = e_zero_matrix(m_ncTotal,m_nuTotal); - m_xdot = e_zero_vector(m_nuTotal); - m_Ju = e_zero_matrix(6*m_nsets,m_nuTotal); - } - m_Atemp = e_zero_matrix(m_ncTotal,6*m_nsets); - m_ydot = e_zero_vector(m_ncTotal); - m_qdot = e_zero_vector(m_nqTotal); - m_Wq = e_zero_matrix(m_nqTotal,m_nqTotal); - m_Wy = e_zero_vector(m_ncTotal); - m_Jq = e_zero_matrix(6*m_nsets,m_nqTotal); - m_Jf = e_zero_matrix(6*m_nsets,6*m_nsets); - m_Jf_inv = m_Jf; - m_Cf = e_zero_matrix(m_ncTotal,m_Jf.rows()); - m_Cq = e_zero_matrix(m_ncTotal,m_nqTotal); - - bool result=true; - // finalize all objects - for (ObjectMap::iterator it=objects.begin(); it!=objects.end(); ++it) { - Object_struct* os = it->second; - - os->object->initCache(m_cache); - if (os->constraintrange.count > 0) - project(m_Cq,os->constraintrange,os->jointrange) = (((ControlledObject*)(os->object))->getCq()); - } - - m_ytask.resize(m_ncTotal); - bool toggle=true; - int cnt = 0; - //Initialize all ConstraintSets: - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - //Calculate the external pose: - ConstraintSet_struct* cs = it->second; - Frame external_pose; - getConstraintPose(cs->task, cs, external_pose); - result&=cs->task->initialise(external_pose); - cs->task->initCache(m_cache); - for (int i=0; i<cs->constraintrange.count; i++, cnt++) { - m_ytask[cnt] = toggle; - } - toggle = !toggle; - project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf(); - } +bool Scene::initialize() +{ - if(m_solver!=NULL) - m_solver->init(m_nqTotal,m_ncTotal,m_ytask); - else - return false; + // prepare all matrices: + if (m_ncTotal == 0 || m_nqTotal == 0 || m_nsets == 0) + return false; + m_A = e_zero_matrix(m_ncTotal, m_nqTotal); + if (m_nuTotal > 0) { + m_B = e_zero_matrix(m_ncTotal, m_nuTotal); + m_xdot = e_zero_vector(m_nuTotal); + m_Ju = e_zero_matrix(6 * m_nsets, m_nuTotal); + } + m_Atemp = e_zero_matrix(m_ncTotal, 6 * m_nsets); + m_ydot = e_zero_vector(m_ncTotal); + m_qdot = e_zero_vector(m_nqTotal); + m_Wq = e_zero_matrix(m_nqTotal, m_nqTotal); + m_Wy = e_zero_vector(m_ncTotal); + m_Jq = e_zero_matrix(6 * m_nsets, m_nqTotal); + m_Jf = e_zero_matrix(6 * m_nsets, 6 * m_nsets); + m_Jf_inv = m_Jf; + m_Cf = e_zero_matrix(m_ncTotal, m_Jf.rows()); + m_Cq = e_zero_matrix(m_ncTotal, m_nqTotal); + + bool result = true; + // finalize all objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + + os->object->initCache(m_cache); + if (os->constraintrange.count > 0) + project(m_Cq, + os->constraintrange, + os->jointrange) = (((ControlledObject *)(os->object))->getCq()); + } + + m_ytask.resize(m_ncTotal); + bool toggle = true; + int cnt = 0; + // Initialize all ConstraintSets: + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + // Calculate the external pose: + ConstraintSet_struct *cs = it->second; + Frame external_pose; + getConstraintPose(cs->task, cs, external_pose); + result &= cs->task->initialise(external_pose); + cs->task->initCache(m_cache); + for (int i = 0; i < cs->constraintrange.count; i++, cnt++) { + m_ytask[cnt] = toggle; + } + toggle = !toggle; + project(m_Cf, cs->constraintrange, cs->featurerange) = cs->task->getCf(); + } - return result; + if (m_solver != NULL) + m_solver->init(m_nqTotal, m_ncTotal, m_ytask); + else + return false; + + return result; } -bool Scene::getConstraintPose(ConstraintSet* constraint, void *_param, KDL::Frame& _pose) +bool Scene::getConstraintPose(ConstraintSet *constraint, void *_param, KDL::Frame &_pose) { - // function called from constraint when they need to get the external pose - ConstraintSet_struct* cs = (ConstraintSet_struct*)_param; - // verification, the pointer MUST match - assert (constraint == cs->task); - Object_struct* ob1 = cs->object1->second; - Object_struct* ob2 = cs->object2->second; - //Calculate the external pose: - _pose=(ob1->base->getPose(ob1->baseFrameIndex)*ob1->object->getPose(cs->ee1index)).Inverse()*(ob2->base->getPose(ob2->baseFrameIndex)*ob2->object->getPose(cs->ee2index)); - return true; + // function called from constraint when they need to get the external pose + ConstraintSet_struct *cs = (ConstraintSet_struct *)_param; + // verification, the pointer MUST match + assert(constraint == cs->task); + Object_struct *ob1 = cs->object1->second; + Object_struct *ob2 = cs->object2->second; + // Calculate the external pose: + _pose = + (ob1->base->getPose(ob1->baseFrameIndex) * ob1->object->getPose(cs->ee1index)).Inverse() * + (ob2->base->getPose(ob2->baseFrameIndex) * ob2->object->getPose(cs->ee2index)); + return true; } -bool Scene::update(double timestamp, double timestep, unsigned int numsubstep, bool reiterate, bool cache, bool interpolate) +bool Scene::update(double timestamp, + double timestep, + unsigned int numsubstep, + bool reiterate, + bool cache, + bool interpolate) { - // we must have valid timestep and timestamp - if (timestamp < KDL::epsilon || timestep < 0.0) - return false; - Timestamp ts; - ts.realTimestamp = timestamp; - // initially we start with the full timestep to allow velocity estimation over the full interval - ts.realTimestep = timestep; - setCacheTimestamp(ts); - ts.substep = 0; - // for reiteration don't load cache - // reiteration=additional iteration with same timestamp if application finds the convergence not good enough - ts.reiterate = (reiterate) ? 1 : 0; - ts.interpolate = (interpolate) ? 1 : 0; - ts.cache = (cache) ? 1 : 0; - ts.update = 1; - ts.numstep = (numsubstep & 0xFF); - bool autosubstep = (numsubstep == 0) ? true : false; - if (numsubstep < 1) - numsubstep = 1; - double timesubstep = timestep/numsubstep; - double timeleft = timestep; - - if (timeleft == 0.0) { - // this special case correspond to a request to cache data - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){ - it->second->object->pushCache(ts); - } - //Update the Constraints - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - it->second->task->pushCache(ts); - } - return true; - } - - // double maxqdot; // UNUSED - e_scalar nlcoef; - SceneLock lockCallback(this); - Frame external_pose; - bool locked; - - // initially we keep timestep unchanged so that update function compute the velocity over - while (numsubstep > 0) { - // get objects - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it) { - Object_struct* os = it->second; - if (os->object->getType()==Object::Controlled) { - ((ControlledObject*)(os->object))->updateControlOutput(ts); - if (os->constraintrange.count > 0) { - project(m_ydot, os->constraintrange) = ((ControlledObject*)(os->object))->getControlOutput(); - project(m_Wy, os->constraintrange) = ((ControlledObject*)(os->object))->getWy(); - // project(m_Cq,os->constraintrange,os->jointrange) = (((ControlledObject*)(os->object))->getCq()); - } - if (os->jointrange.count > 0) { - project(m_Wq,os->jointrange,os->jointrange) = ((ControlledObject*)(os->object))->getWq(); - } - } - if (os->object->getType()==Object::UnControlled && ((UncontrolledObject*)os->object)->getNrOfCoordinates() != 0) { - ((UncontrolledObject*)(os->object))->updateCoordinates(ts); - if (!ts.substep) { - // velocity of uncontrolled object remains constant during substepping - project(m_xdot,os->coordinaterange) = ((UncontrolledObject*)(os->object))->getXudot(); - } - } - } - - //get new Constraints values - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it) { - ConstraintSet_struct* cs = it->second; - Object_struct* ob1 = cs->object1->second; - Object_struct* ob2 = cs->object2->second; - - if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() || ob2->object->updated()) { - // the object from which the constraint depends have changed position - // recompute the constraint pose - getConstraintPose(cs->task, cs, external_pose); - cs->task->initialise(external_pose); - } - cs->task->updateControlOutput(ts); - project(m_ydot,cs->constraintrange)=cs->task->getControlOutput(); - if (!ts.substep || cs->task->substep()) { - project(m_Wy,cs->constraintrange)=(cs->task)->getWy(); - //project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf(); - } - - project(m_Jf,cs->featurerange,cs->featurerange)=cs->task->getJf(); - //std::cout << "Jf = " << Jf << std::endl; - //Transform the reference frame of this jacobian to the world reference frame - Eigen::Block<e_matrix> Jf_part = project(m_Jf,cs->featurerange,cs->featurerange); - changeBase(Jf_part,ob1->base->getPose(ob1->baseFrameIndex)*ob1->object->getPose(cs->ee1index)); - //std::cout << "Jf_w = " << Jf << std::endl; - - //calculate the inverse of Jf - KDL::svd_eigen_HH(project(m_Jf,cs->featurerange,cs->featurerange),m_Uf,m_Sf,m_Vf,m_tempf); - for(unsigned int i=0;i<6;++i) - if(m_Sf(i)<KDL::epsilon) - m_Uf.col(i).setConstant(0.0); - else - m_Uf.col(i)*=(1/m_Sf(i)); - project(m_Jf_inv,cs->featurerange,cs->featurerange).noalias()=m_Vf*m_Uf.transpose(); - - //Get the robotjacobian associated with this constraintset - //Each jacobian is expressed in robot base frame => convert to world reference - //and negate second robot because it is taken reversed when closing the loop: - if(ob1->object->getType()==Object::Controlled){ - project(m_Jq,cs->featurerange,ob1->jointrange) = (((ControlledObject*)(ob1->object))->getJq(cs->ee1index)); - //Transform the reference frame of this jacobian to the world reference frame: - Eigen::Block<e_matrix> Jq_part = project(m_Jq,cs->featurerange,ob1->jointrange); - changeBase(Jq_part,ob1->base->getPose(ob1->baseFrameIndex)); - // if the base of this object is moving, get the Ju part - if (ob1->base->getNrOfCoordinates() != 0) { - // Ju is already computed for world reference frame - project(m_Ju,cs->featurerange,ob1->coordinaterange)=ob1->base->getJu(ob1->baseFrameIndex); - } - } else if (ob1->object->getType() == Object::UnControlled && ((UncontrolledObject*)ob1->object)->getNrOfCoordinates() != 0) { - // object1 is uncontrolled moving object - project(m_Ju,cs->featurerange,ob1->coordinaterange)=((UncontrolledObject*)ob1->object)->getJu(cs->ee1index); - } - if(ob2->object->getType()==Object::Controlled){ - //Get the robotjacobian associated with this constraintset - // process a special case where object2 and object1 are equal but using different end effector - if (ob1->object == ob2->object) { - // we must create a temporary matrix - e_matrix JqTemp(((ControlledObject*)(ob2->object))->getJq(cs->ee2index)); - //Transform the reference frame of this jacobian to the world reference frame: - changeBase(JqTemp,ob2->base->getPose(ob2->baseFrameIndex)); - // substract in place - project(m_Jq,cs->featurerange,ob2->jointrange) -= JqTemp; - } else { - project(m_Jq,cs->featurerange,ob2->jointrange) = -(((ControlledObject*)(ob2->object))->getJq(cs->ee2index)); - //Transform the reference frame of this jacobian to the world reference frame: - Eigen::Block<e_matrix> Jq_part = project(m_Jq,cs->featurerange,ob2->jointrange); - changeBase(Jq_part,ob2->base->getPose(ob2->baseFrameIndex)); - } - if (ob2->base->getNrOfCoordinates() != 0) { - // if base is the same as first object or first object base, - // that portion of m_Ju has been set already => substract inplace - if (ob2->base == ob1->base || ob2->base == ob1->object) { - project(m_Ju,cs->featurerange,ob2->coordinaterange) -= ob2->base->getJu(ob2->baseFrameIndex); - } else { - project(m_Ju,cs->featurerange,ob2->coordinaterange) = -ob2->base->getJu(ob2->baseFrameIndex); - } - } - } else if (ob2->object->getType() == Object::UnControlled && ((UncontrolledObject*)ob2->object)->getNrOfCoordinates() != 0) { - if (ob2->object == ob1->base || ob2->object == ob1->object) { - project(m_Ju,cs->featurerange,ob2->coordinaterange) -= ((UncontrolledObject*)ob2->object)->getJu(cs->ee2index); - } else { - project(m_Ju,cs->featurerange,ob2->coordinaterange) = -((UncontrolledObject*)ob2->object)->getJu(cs->ee2index); - } - } - } - - //Calculate A - m_Atemp.noalias()=m_Cf*m_Jf_inv; - m_A.noalias() = m_Cq-(m_Atemp*m_Jq); - if (m_nuTotal > 0) { - m_B.noalias()=m_Atemp*m_Ju; - m_ydot.noalias() += m_B*m_xdot; - } - - //Call the solver with A, Wq, Wy, ydot to solver qdot: - if(!m_solver->solve(m_A,m_Wy,m_ydot,m_Wq,m_qdot,nlcoef)) - // this should never happen - return false; - //send result to the objects - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it) { - Object_struct* os = it->second; - if(os->object->getType()==Object::Controlled) - ((ControlledObject*)(os->object))->setJointVelocity(project(m_qdot,os->jointrange)); - } - // compute the constraint velocity - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - ConstraintSet_struct* cs = it->second; - Object_struct* ob1 = cs->object1->second; - Object_struct* ob2 = cs->object2->second; - //Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot): - e_vector6 external_vel = e_zero_vector(6); - if (ob1->jointrange.count > 0) - external_vel.noalias() += (project(m_Jq,cs->featurerange,ob1->jointrange)*project(m_qdot,ob1->jointrange)); - if (ob2->jointrange.count > 0) - external_vel.noalias() += (project(m_Jq,cs->featurerange,ob2->jointrange)*project(m_qdot,ob2->jointrange)); - if (ob1->coordinaterange.count > 0) - external_vel.noalias() += (project(m_Ju,cs->featurerange,ob1->coordinaterange)*project(m_xdot,ob1->coordinaterange)); - if (ob2->coordinaterange.count > 0) - external_vel.noalias() += (project(m_Ju,cs->featurerange,ob2->coordinaterange)*project(m_xdot,ob2->coordinaterange)); - //the twist caused by the constraint must be opposite because of the closed loop - //estimate the velocity of the joints using the inverse jacobian - e_vector6 estimated_chidot = project(m_Jf_inv,cs->featurerange,cs->featurerange)*(-external_vel); - cs->task->setJointVelocity(estimated_chidot); - } - - if (autosubstep) { - // automatic computing of substep based on maximum joint change - // and joint limit gain variation - // We will pass the joint velocity to each object and they will recommend a maximum timestep - timesubstep = timeleft; - // get armature max joint velocity to estimate the maximum duration of integration - // maxqdot = m_qdot.cwise().abs().maxCoeff(); // UNUSED - double maxsubstep = nlcoef*m_maxstep; - if (maxsubstep < m_minstep) - maxsubstep = m_minstep; - if (timesubstep > maxsubstep) - timesubstep = maxsubstep; - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){ - Object_struct* os = it->second; - if(os->object->getType()==Object::Controlled) - ((ControlledObject*)(os->object))->getMaxTimestep(timesubstep); - } - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - ConstraintSet_struct* cs = it->second; - cs->task->getMaxTimestep(timesubstep); - } - // use substep that are even dividers of timestep for more regularity - maxsubstep = 2.0*floor(timestep/2.0/timesubstep-0.66666); - timesubstep = (maxsubstep < 0.0) ? timestep : timestep/(2.0+maxsubstep); - if (timesubstep >= timeleft-(m_minstep/2.0)) { - timesubstep = timeleft; - numsubstep = 1; - timeleft = 0.; - } else { - numsubstep = 2; - timeleft -= timesubstep; - } - } - if (numsubstep > 1) { - ts.substep = 1; - } else { - // set substep to false for last iteration so that controlled output - // can be updated in updateKinematics() and model_update)() before next call to Secne::update() - ts.substep = 0; - } - // change timestep so that integration is done correctly - ts.realTimestep = timesubstep; - - do { - ObjectMap::iterator it; - Object_struct* os; - locked = false; - for(it=objects.begin();it!=objects.end();++it){ - os = it->second; - if (os->object->getType()==Object::Controlled) { - lockCallback.setRange(os->jointrange); - if (((ControlledObject*)os->object)->updateJoint(ts, lockCallback)) { - // this means one of the joint was locked and we must rerun - // the solver to update the remaining joints - locked = true; - break; - } - } - } - if (locked) { - // Some rows of m_Wq have been cleared so that the corresponding joint will not move - if(!m_solver->solve(m_A,m_Wy,m_ydot,m_Wq,m_qdot,nlcoef)) - // this should never happen - return false; - - //send result to the objects - for(it=objects.begin();it!=objects.end();++it) { - os = it->second; - if(os->object->getType()==Object::Controlled) - ((ControlledObject*)(os->object))->setJointVelocity(project(m_qdot,os->jointrange)); - } - } - } while (locked); - - //Update the Objects - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){ - it->second->object->updateKinematics(ts); - // mark this object not updated since the constraint will be updated anyway - // this flag is only useful to detect external updates - it->second->object->updated(false); - } - //Update the Constraints - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - ConstraintSet_struct* cs = it->second; - //Calculate the external pose: - getConstraintPose(cs->task, cs, external_pose); - cs->task->modelUpdate(external_pose,ts); - // update the constraint output and cache - cs->task->updateKinematics(ts); - } - numsubstep--; - } - return true; -} + // we must have valid timestep and timestamp + if (timestamp < KDL::epsilon || timestep < 0.0) + return false; + Timestamp ts; + ts.realTimestamp = timestamp; + // initially we start with the full timestep to allow velocity estimation over the full interval + ts.realTimestep = timestep; + setCacheTimestamp(ts); + ts.substep = 0; + // for reiteration don't load cache + // reiteration=additional iteration with same timestamp if application finds the convergence not + // good enough + ts.reiterate = (reiterate) ? 1 : 0; + ts.interpolate = (interpolate) ? 1 : 0; + ts.cache = (cache) ? 1 : 0; + ts.update = 1; + ts.numstep = (numsubstep & 0xFF); + bool autosubstep = (numsubstep == 0) ? true : false; + if (numsubstep < 1) + numsubstep = 1; + double timesubstep = timestep / numsubstep; + double timeleft = timestep; + + if (timeleft == 0.0) { + // this special case correspond to a request to cache data + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + it->second->object->pushCache(ts); + } + // Update the Constraints + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + it->second->task->pushCache(ts); + } + return true; + } + + // double maxqdot; // UNUSED + e_scalar nlcoef; + SceneLock lockCallback(this); + Frame external_pose; + bool locked; + + // initially we keep timestep unchanged so that update function compute the velocity over + while (numsubstep > 0) { + // get objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + if (os->object->getType() == Object::Controlled) { + ((ControlledObject *)(os->object))->updateControlOutput(ts); + if (os->constraintrange.count > 0) { + project(m_ydot, + os->constraintrange) = ((ControlledObject *)(os->object))->getControlOutput(); + project(m_Wy, os->constraintrange) = ((ControlledObject *)(os->object))->getWy(); + // project(m_Cq,os->constraintrange,os->jointrange) = + // (((ControlledObject*)(os->object))->getCq()); + } + if (os->jointrange.count > 0) { + project( + m_Wq, os->jointrange, os->jointrange) = ((ControlledObject *)(os->object))->getWq(); + } + } + if (os->object->getType() == Object::UnControlled && + ((UncontrolledObject *)os->object)->getNrOfCoordinates() != 0) { + ((UncontrolledObject *)(os->object))->updateCoordinates(ts); + if (!ts.substep) { + // velocity of uncontrolled object remains constant during substepping + project(m_xdot, os->coordinaterange) = ((UncontrolledObject *)(os->object))->getXudot(); + } + } + } + + // get new Constraints values + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + Object_struct *ob1 = cs->object1->second; + Object_struct *ob2 = cs->object2->second; + + if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() || + ob2->object->updated()) { + // the object from which the constraint depends have changed position + // recompute the constraint pose + getConstraintPose(cs->task, cs, external_pose); + cs->task->initialise(external_pose); + } + cs->task->updateControlOutput(ts); + project(m_ydot, cs->constraintrange) = cs->task->getControlOutput(); + if (!ts.substep || cs->task->substep()) { + project(m_Wy, cs->constraintrange) = (cs->task)->getWy(); + // project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf(); + } + + project(m_Jf, cs->featurerange, cs->featurerange) = cs->task->getJf(); + // std::cout << "Jf = " << Jf << std::endl; + // Transform the reference frame of this jacobian to the world reference frame + Eigen::Block<e_matrix> Jf_part = project(m_Jf, cs->featurerange, cs->featurerange); + changeBase(Jf_part, + ob1->base->getPose(ob1->baseFrameIndex) * ob1->object->getPose(cs->ee1index)); + // std::cout << "Jf_w = " << Jf << std::endl; + + // calculate the inverse of Jf + KDL::svd_eigen_HH( + project(m_Jf, cs->featurerange, cs->featurerange), m_Uf, m_Sf, m_Vf, m_tempf); + for (unsigned int i = 0; i < 6; ++i) + if (m_Sf(i) < KDL::epsilon) + m_Uf.col(i).setConstant(0.0); + else + m_Uf.col(i) *= (1 / m_Sf(i)); + project(m_Jf_inv, cs->featurerange, cs->featurerange).noalias() = m_Vf * m_Uf.transpose(); + + // Get the robotjacobian associated with this constraintset + // Each jacobian is expressed in robot base frame => convert to world reference + // and negate second robot because it is taken reversed when closing the loop: + if (ob1->object->getType() == Object::Controlled) { + project(m_Jq, + cs->featurerange, + ob1->jointrange) = (((ControlledObject *)(ob1->object))->getJq(cs->ee1index)); + // Transform the reference frame of this jacobian to the world reference frame: + Eigen::Block<e_matrix> Jq_part = project(m_Jq, cs->featurerange, ob1->jointrange); + changeBase(Jq_part, ob1->base->getPose(ob1->baseFrameIndex)); + // if the base of this object is moving, get the Ju part + if (ob1->base->getNrOfCoordinates() != 0) { + // Ju is already computed for world reference frame + project(m_Ju, cs->featurerange, ob1->coordinaterange) = ob1->base->getJu( + ob1->baseFrameIndex); + } + } + else if (ob1->object->getType() == Object::UnControlled && + ((UncontrolledObject *)ob1->object)->getNrOfCoordinates() != 0) { + // object1 is uncontrolled moving object + project(m_Ju, + cs->featurerange, + ob1->coordinaterange) = ((UncontrolledObject *)ob1->object)->getJu(cs->ee1index); + } + if (ob2->object->getType() == Object::Controlled) { + // Get the robotjacobian associated with this constraintset + // process a special case where object2 and object1 are equal but using different end + // effector + if (ob1->object == ob2->object) { + // we must create a temporary matrix + e_matrix JqTemp(((ControlledObject *)(ob2->object))->getJq(cs->ee2index)); + // Transform the reference frame of this jacobian to the world reference frame: + changeBase(JqTemp, ob2->base->getPose(ob2->baseFrameIndex)); + // subtract in place + project(m_Jq, cs->featurerange, ob2->jointrange) -= JqTemp; + } + else { + project(m_Jq, cs->featurerange, ob2->jointrange) = -( + ((ControlledObject *)(ob2->object))->getJq(cs->ee2index)); + // Transform the reference frame of this jacobian to the world reference frame: + Eigen::Block<e_matrix> Jq_part = project(m_Jq, cs->featurerange, ob2->jointrange); + changeBase(Jq_part, ob2->base->getPose(ob2->baseFrameIndex)); + } + if (ob2->base->getNrOfCoordinates() != 0) { + // if base is the same as first object or first object base, + // that portion of m_Ju has been set already => subtract inplace + if (ob2->base == ob1->base || ob2->base == ob1->object) { + project(m_Ju, cs->featurerange, ob2->coordinaterange) -= ob2->base->getJu( + ob2->baseFrameIndex); + } + else { + project(m_Ju, cs->featurerange, ob2->coordinaterange) = -ob2->base->getJu( + ob2->baseFrameIndex); + } + } + } + else if (ob2->object->getType() == Object::UnControlled && + ((UncontrolledObject *)ob2->object)->getNrOfCoordinates() != 0) { + if (ob2->object == ob1->base || ob2->object == ob1->object) { + project(m_Ju, cs->featurerange, ob2->coordinaterange) -= + ((UncontrolledObject *)ob2->object)->getJu(cs->ee2index); + } + else { + project(m_Ju, cs->featurerange, ob2->coordinaterange) = + -((UncontrolledObject *)ob2->object)->getJu(cs->ee2index); + } + } + } + + // Calculate A + m_Atemp.noalias() = m_Cf * m_Jf_inv; + m_A.noalias() = m_Cq - (m_Atemp * m_Jq); + if (m_nuTotal > 0) { + m_B.noalias() = m_Atemp * m_Ju; + m_ydot.noalias() += m_B * m_xdot; + } + // Call the solver with A, Wq, Wy, ydot to solver qdot: + if (!m_solver->solve(m_A, m_Wy, m_ydot, m_Wq, m_qdot, nlcoef)) + // this should never happen + return false; + // send result to the objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + if (os->object->getType() == Object::Controlled) + ((ControlledObject *)(os->object))->setJointVelocity(project(m_qdot, os->jointrange)); + } + // compute the constraint velocity + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + Object_struct *ob1 = cs->object1->second; + Object_struct *ob2 = cs->object2->second; + // Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot): + e_vector6 external_vel = e_zero_vector(6); + if (ob1->jointrange.count > 0) + external_vel.noalias() += (project(m_Jq, cs->featurerange, ob1->jointrange) * + project(m_qdot, ob1->jointrange)); + if (ob2->jointrange.count > 0) + external_vel.noalias() += (project(m_Jq, cs->featurerange, ob2->jointrange) * + project(m_qdot, ob2->jointrange)); + if (ob1->coordinaterange.count > 0) + external_vel.noalias() += (project(m_Ju, cs->featurerange, ob1->coordinaterange) * + project(m_xdot, ob1->coordinaterange)); + if (ob2->coordinaterange.count > 0) + external_vel.noalias() += (project(m_Ju, cs->featurerange, ob2->coordinaterange) * + project(m_xdot, ob2->coordinaterange)); + // the twist caused by the constraint must be opposite because of the closed loop + // estimate the velocity of the joints using the inverse jacobian + e_vector6 estimated_chidot = project(m_Jf_inv, cs->featurerange, cs->featurerange) * + (-external_vel); + cs->task->setJointVelocity(estimated_chidot); + } + + if (autosubstep) { + // automatic computing of substep based on maximum joint change + // and joint limit gain variation + // We will pass the joint velocity to each object and they will recommend a maximum timestep + timesubstep = timeleft; + // get armature max joint velocity to estimate the maximum duration of integration + // maxqdot = m_qdot.cwise().abs().maxCoeff(); // UNUSED + double maxsubstep = nlcoef * m_maxstep; + if (maxsubstep < m_minstep) + maxsubstep = m_minstep; + if (timesubstep > maxsubstep) + timesubstep = maxsubstep; + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + if (os->object->getType() == Object::Controlled) + ((ControlledObject *)(os->object))->getMaxTimestep(timesubstep); + } + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + cs->task->getMaxTimestep(timesubstep); + } + // use substep that are even dividers of timestep for more regularity + maxsubstep = 2.0 * floor(timestep / 2.0 / timesubstep - 0.66666); + timesubstep = (maxsubstep < 0.0) ? timestep : timestep / (2.0 + maxsubstep); + if (timesubstep >= timeleft - (m_minstep / 2.0)) { + timesubstep = timeleft; + numsubstep = 1; + timeleft = 0.; + } + else { + numsubstep = 2; + timeleft -= timesubstep; + } + } + if (numsubstep > 1) { + ts.substep = 1; + } + else { + // set substep to false for last iteration so that controlled output + // can be updated in updateKinematics() and model_update)() before next call to + // Secne::update() + ts.substep = 0; + } + // change timestep so that integration is done correctly + ts.realTimestep = timesubstep; + + do { + ObjectMap::iterator it; + Object_struct *os; + locked = false; + for (it = objects.begin(); it != objects.end(); ++it) { + os = it->second; + if (os->object->getType() == Object::Controlled) { + lockCallback.setRange(os->jointrange); + if (((ControlledObject *)os->object)->updateJoint(ts, lockCallback)) { + // this means one of the joint was locked and we must rerun + // the solver to update the remaining joints + locked = true; + break; + } + } + } + if (locked) { + // Some rows of m_Wq have been cleared so that the corresponding joint will not move + if (!m_solver->solve(m_A, m_Wy, m_ydot, m_Wq, m_qdot, nlcoef)) + // this should never happen + return false; + + // send result to the objects + for (it = objects.begin(); it != objects.end(); ++it) { + os = it->second; + if (os->object->getType() == Object::Controlled) + ((ControlledObject *)(os->object))->setJointVelocity(project(m_qdot, os->jointrange)); + } + } + } while (locked); + + // Update the Objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + it->second->object->updateKinematics(ts); + // mark this object not updated since the constraint will be updated anyway + // this flag is only useful to detect external updates + it->second->object->updated(false); + } + // Update the Constraints + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + // Calculate the external pose: + getConstraintPose(cs->task, cs, external_pose); + cs->task->modelUpdate(external_pose, ts); + // update the constraint output and cache + cs->task->updateKinematics(ts); + } + numsubstep--; + } + return true; } + +} // namespace iTaSC diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index 676a2fd785e..6e6451be725 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -876,6 +876,7 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd) mRNAMap["CACHE_DIR"] = cacheDirectory; mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod; mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf; + mRNAMap["PP_PARTICLE_MAXIMUM"] = to_string(fds->sys_particle_maximum); /* Fluid object names. */ mRNAMap["NAME_FLAGS"] = FLUID_NAME_FLAGS; @@ -1013,7 +1014,7 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd) mRNAMap["NAME_GUIDEVEL_X"] = FLUID_NAME_GUIDEVEL_X; mRNAMap["NAME_GUIDEVEL_Y"] = FLUID_NAME_GUIDEVEL_Y; mRNAMap["NAME_GUIDEVEL_Z"] = FLUID_NAME_GUIDEVEL_Z; - mRNAMap["NAME_GUIDEVEL"] = FLUID_NAME_GUIDEVEL; + mRNAMap["NAME_VELOCITY_GUIDE"] = FLUID_NAME_VELOCITY_GUIDE; /* Cache file names. */ mRNAMap["NAME_CONFIG"] = FLUID_NAME_CONFIG; @@ -1538,6 +1539,7 @@ bool MANTA::bakeGuiding(FluidModifierData *fmd, int framenr) cacheDirGuiding[0] = '\0'; string volume_format = getCacheFileEnding(fds->cache_data_format); + string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True"; BLI_path_join(cacheDirGuiding, sizeof(cacheDirGuiding), @@ -1548,7 +1550,7 @@ bool MANTA::bakeGuiding(FluidModifierData *fmd, int framenr) ss.str(""); ss << "bake_guiding_" << mCurrentID << "('" << escapeSlashes(cacheDirGuiding) << "', " << framenr - << ", '" << volume_format << "')"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -2189,9 +2191,16 @@ bool MANTA::hasParticles(FluidModifierData *fmd, int framenr) bool MANTA::hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain) { string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE; - string filename = (sourceDomain) ? FLUID_NAME_VELOCITY : FLUID_NAME_GUIDEVEL; + string filename = (sourceDomain) ? FLUID_NAME_DATA : FLUID_NAME_GUIDING; string extension = getCacheFileEnding(fmd->domain->cache_data_format); bool exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str()); + + /* Check old file naming. */ + if (!exists) { + filename = (sourceDomain) ? FLUID_NAME_VEL : FLUID_NAME_GUIDEVEL; + exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str()); + } + if (with_debug) cout << "Fluid: Has Guiding: " << exists << endl; diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index 4ee3ae59957..83ad201fcbd 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -329,7 +329,7 @@ y_guidevel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_GUIDEVEL_Y$')\n\ z_guidevel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_GUIDEVEL_Z$')\n\ \n\ # Final guide vel grid needs to have independent size\n\ -guidevel_sg$ID$ = sg$ID$.create(MACGrid, name='$NAME_GUIDEVEL$')\n\ +guidevel_sg$ID$ = sg$ID$.create(MACGrid, name='$NAME_VELOCITY_GUIDE$')\n\ \n\ # Keep track of important objects in dict to load them later on\n\ fluid_guiding_dict_s$ID$ = { 'guidevel' : guidevel_sg$ID$ }\n"; @@ -700,14 +700,16 @@ const std::string fluid_load_guiding = "\n\ def fluid_load_guiding_$ID$(path, framenr, file_format):\n\ mantaMsg('Fluid load guiding, frame ' + str(framenr))\n\ + guidevel_sg$ID$.setName('$NAME_VELOCITY_GUIDE$')\n\ fluid_file_import_s$ID$(dict=fluid_guiding_dict_s$ID$, path=path, framenr=framenr, file_format=file_format, file_name=file_guiding_s$ID$)\n"; const std::string fluid_load_vel = "\n\ def fluid_load_vel_$ID$(path, framenr, file_format):\n\ mantaMsg('Fluid load vel, frame ' + str(framenr))\n\ + guidevel_sg$ID$.setName('$NAME_VELOCITY$') # for loading data the guidevel grid will pretend to be the vel grid\n\ fluid_vel_dict_s$ID$ = { 'vel' : guidevel_sg$ID$ }\n\ - fluid_file_import_s$ID$(dict=fluid_vel_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; + fluid_file_import_s$ID$(dict=fluid_vel_dict_s$ID$, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n"; ////////////////////////////////////////////////////////////////////// // EXPORT @@ -748,12 +750,13 @@ def fluid_file_export_s$ID$(framenr, file_format, path, dict, file_name=None, mo const std::string fluid_save_guiding = "\n\ -def fluid_save_guiding_$ID$(path, framenr, file_format):\n\ +def fluid_save_guiding_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Fluid save guiding, frame ' + str(framenr))\n\ + dict = fluid_guiding_dict_s$ID$\n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=fluid_guiding_dict_s$ID$, framenr=framenr, file_format=file_format, path=path, file_name=file_guiding_s$ID$)\n\ + fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_guiding_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_guiding_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=fluid_guiding_dict_s$ID$, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_guiding_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n"; ////////////////////////////////////////////////////////////////////// // STANDALONE MODE @@ -770,8 +773,6 @@ if (GUI):\n\ cache_resumable = $CACHE_RESUMABLE$\n\ cache_dir = '$CACHE_DIR$'\n\ file_format_data = '$CACHE_DATA_FORMAT$'\n\ -file_format_noise = '$CACHE_NOISE_FORMAT$'\n\ -file_format_particles = '$CACHE_PARTICLE_FORMAT$'\n\ file_format_mesh = '$CACHE_MESH_FORMAT$'\n\ \n\ # How many frame to load from cache\n\ diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h index 04505206601..08d8dcd7de3 100644 --- a/intern/mantaflow/intern/strings/liquid_script.h +++ b/intern/mantaflow/intern/strings/liquid_script.h @@ -48,7 +48,8 @@ meshRadiusFactor_s$ID$ = $MESH_PARTICLE_RADIUS$\n\ smoothenPos_s$ID$ = $MESH_SMOOTHEN_POS$\n\ smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\ randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\ -surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n"; +surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\ +maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n"; const std::string liquid_variables_particles = "\n\ @@ -216,6 +217,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\ else:\n\ pVel_pp$ID$.setSource(grid=None, isMAC=False)\n\ \n\ + pp_s$ID$.maxParticles = maxSysParticles_s$ID$ # remember, 0 means no particle cap\n\ sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\ flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\ \n\ @@ -477,7 +479,7 @@ const std::string liquid_standalone = def load(frame, cache_resumable):\n\ liquid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\ if using_sndparts_s$ID$:\n\ - liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_particles, cache_resumable)\n\ + liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_data, cache_resumable)\n\ if using_mesh_s$ID$:\n\ liquid_load_mesh_$ID$(os.path.join(cache_dir, 'mesh'), frame, file_format_mesh)\n\ if using_guiding_s$ID$:\n\ diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h index 332aa2342ee..f81259115c5 100644 --- a/intern/mantaflow/intern/strings/smoke_script.h +++ b/intern/mantaflow/intern/strings/smoke_script.h @@ -601,7 +601,7 @@ const std::string smoke_standalone = def load(frame, cache_resumable):\n\ smoke_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\ if using_noise_s$ID$:\n\ - smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_noise, cache_resumable)\n\ + smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_data, cache_resumable)\n\ if using_guiding_s$ID$:\n\ fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\ \n\ diff --git a/intern/sky/source/sky_model.cpp b/intern/sky/source/sky_model.cpp index 64cf14ec030..e835e04d164 100644 --- a/intern/sky/source/sky_model.cpp +++ b/intern/sky/source/sky_model.cpp @@ -178,8 +178,9 @@ static void ArHosekSkyModel_CookConfiguration(ArHosekSkyModel_Dataset dataset, pow(solar_elevation, 5.0) * elev_matrix[i + 45]); } - if (int_turbidity == 10) + if (int_turbidity == 10) { return; + } // alb 0 high turb elev_matrix = dataset + (9 * 6 * (int_turbidity)); @@ -243,8 +244,9 @@ static double ArHosekSkyModel_CookRadianceConfiguration(ArHosekSkyModel_Radiance 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] + pow(solar_elevation, 5.0) * elev_matrix[5]); - if (int_turbidity == 10) + if (int_turbidity == 10) { return res; + } // alb 0 high turb elev_matrix = dataset + (6 * (int_turbidity)); @@ -298,16 +300,18 @@ double SKY_arhosekskymodel_radiance(SKY_ArHosekSkyModelState *state, { int low_wl = (int)((wavelength - 320.0) / 40.0); - if (low_wl < 0 || low_wl >= 11) + if (low_wl < 0 || low_wl >= 11) { return 0.0; + } double interp = fmod((wavelength - 320.0) / 40.0, 1.0); double val_low = ArHosekSkyModel_GetRadianceInternal(state->configs[low_wl], theta, gamma) * state->radiances[low_wl] * state->emission_correction_factor_sky[low_wl]; - if (interp < 1e-6) + if (interp < 1e-6) { return val_low; + } double result = (1.0 - interp) * val_low; |