From 0beaff7ddf65b2daab59d13a7f86a58f8b8c9b8c Mon Sep 17 00:00:00 2001 From: Zachary Ferguson Date: Tue, 26 Sep 2023 15:04:56 -0400 Subject: [PATCH] Add convergent formulation docs --- docs/CHANGELOG.md | 307 --------- docs/requirements.txt | 3 + docs/source/Doxyfile | 267 +++++--- docs/source/changelog.rst | 615 +++++++++++++++++- docs/source/conf.py | 12 +- docs/source/cpp.rst | 25 +- docs/source/index.rst | 5 +- docs/source/refs.bib | 60 ++ docs/source/tutorial/getting_started.rst | 352 +++++++++- docs/source/tutorial/references.rst | 4 + docs/source/tutorial/simulation.rst | 68 +- .../src/collisions/collision_constraint.cpp | 3 +- src/ipc/candidates/collision_stencil.hpp | 12 +- src/ipc/collisions/collision_constraint.cpp | 38 +- src/ipc/collisions/collision_constraint.hpp | 2 +- src/ipc/collisions/collision_constraints.cpp | 2 +- src/ipc/collisions/plane_vertex.hpp | 9 + src/ipc/friction/constraints/edge_edge.cpp | 3 +- src/ipc/friction/constraints/edge_vertex.cpp | 3 +- src/ipc/friction/constraints/face_vertex.cpp | 3 +- .../constraints/friction_constraint.hpp | 1 + .../friction/constraints/vertex_vertex.cpp | 3 +- .../friction/constraints/vertex_vertex.hpp | 3 +- src/ipc/implicits/plane.cpp | 2 +- 24 files changed, 1315 insertions(+), 487 deletions(-) delete mode 100644 docs/CHANGELOG.md create mode 100644 docs/source/refs.bib create mode 100644 docs/source/tutorial/references.rst diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md deleted file mode 100644 index ca61ef85c..000000000 --- a/docs/CHANGELOG.md +++ /dev/null @@ -1,307 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -## v1.1.1 (Aug 18, 2023) - -* Logo by @zfergus in [#52](https://github.com/ipc-sim/ipc-toolkit/pull/52) -* Fix vertex-vertex `==` and `<` functions to be order independent - * This allows vertex-vertex constraints merge correctly -* Update Tight Inclusion CCD - -## v1.1.0 (Jul 25, 2023) - -Large refactoring to make the code more object-oriented rather than passing objects to functions. Other changes include the friction potential now being a function of velocity, bug fixes, and a new tutorial. - -### Details - -* Large Refactor in [#25](https://github.com/ipc-sim/ipc-toolkit/pull/25) - * `construct_collision_candidates(..., candidates)` -> `candidates.build(...)` - * `is_step_collision_free(candidates, ...)` -> `candidates.is_step_collision_free(...)` - * `compute_collision_free_stepsize(candidates, ...)` -> `candidates.compute_collision_free_stepsize(...)` - * `compute_barrier_potential*(constraints, ...)` -> `constraints.compute_potential*(...)` - * `compute_shape_derivative(constraints, ...)` -> `constraints.compute_shape_derivative(...)` - * `compute_minimum_distance(constraints, ...)` -> `constraints.compute_minimum_distance(...)` - * `construct_friction_constraint_set(..., friction_constraints)` -> `friction_constraints.build(...)` - * `compute_friction_*(..., friction_constraints, ...)` -> `friction_constraints.compute_*(...)` - * Generic `CollisionStencil` parent class to `Candidates`, `CollisionConstraints`, and `FrictionConstraints`. - * Renamed `Constraints` to `CollisionConstraints` - * Replaced single letter variable names `V`, `E`, `F` with `vertices`/`positions`, `edges`, `faces` - * Renamed `*_index` -> `*_id` - * Replaced `inflation_radius = min_distance / 1.99` with `inflation_radius = min_distance / 2` and use rounding mode to conservativly inflate AABBs - * `CollisionConstraints::use_convergent_formulation` and `are_shape_derivatives_enabled` must now be accessed through getter and setter functions - * Friction potentials are now functions of velocity. Previously `V0` and `V1` were passed and `U = V1-V0`. This limited the integration scheme to implicit Euler. Upstream this means you need to multiply the potential by `1/(dv/dx)` to get the correct friction force. - * Change input $\epsilon_vh$ to $\epsilon_v$ in [#37](https://github.com/ipc-sim/ipc-toolkit/pull/37) to reflect the fact that friction is defined in terms of velocity instead of displacement now. -* Changed default `project_hessian_to_psd` to `false` in [#30](https://github.com/ipc-sim/ipc-toolkit/pull/30) -* Update website with a tutorial ([#31](https://github.com/ipc-sim/ipc-toolkit/pull/31)) and version dropdown list ([#34](https://github.com/ipc-sim/ipc-toolkit/pull/34)) -* Switch from templates to using `Eigen::Ref` in [#28](https://github.com/ipc-sim/ipc-toolkit/pull/28) -* Speed up the CCD by limiting the maximum minimum distance to `1e-4` in [#43](https://github.com/ipc-sim/ipc-toolkit/pull/43) -* Fix the bug pointed out in [#41](https://github.com/ipc-sim/ipc-toolkit/pull/41) in [#42](https://github.com/ipc-sim/ipc-toolkit/pull/42). Namely, to get units of distance in the barrier we should divide the original function by $\hat{d}\cdot(\hat{d} + 2d_{\min})^2$ when using distance squared. Before it was being divided by $2d_{\min} \hat{d} + \hat{d}^2$. -* Fix build for IPC_TOOLKIT_WITH_CORRECT_CCD=OFF in [#44](https://github.com/ipc-sim/ipc-toolkit/pull/44) -* Switched from FetchContent to CPM in [#48](https://github.com/ipc-sim/ipc-toolkit/pull/48). This provides better caching between builds. Additionally, made robin-map and Abseil optional dependencies. -* Add the CFL-Inspired Culling of CCD as described in Section 3 of the Technical Supplement to IPC in [#50](https://github.com/ipc-sim/ipc-toolkit/pull/50) - -## v1.0.0 (Feb 21, 2023) - -This is the first official release. ๐Ÿš€ - -This is a stable release of the toolkit prior to refactoring the code and making updates to the API. - -### Details - -* Added a minimum distance optional parameter to all CCD functions (`const double min_distance = 0.0`) in [#22](https://github.com/ipc-sim/ipc-toolkit/pull/22). This is placed as the first optional argument which can break calling code if optional parameters were previously used. -* Added `CollisionMesh` in [#7](https://github.com/ipc-sim/ipc-toolkit/pull/7) to wrap up face and edges into a single data structure. - * Removes Support for ignoring internal vertices. Instead, users should use the CollisionMesh to map from the full mesh to the surface mesh. - * This also includes a `to_full_dof` function that can map the reduced gradient/hessian to the full mesh's DOF. - -## Pre-v1.0.0 - -### 2021-10-05 ([9e2cc2a](https://github.com/ipc-sim/ipc-toolkit/commit/574f7577daa5e0b51bf5baf20998994b8371216e)) -#### Added -* Added implicits source folder to organize point-plane collisions - -### 2021-09-05 ([9e2cc2a](https://github.com/ipc-sim/ipc-toolkit/commit/9e22cc2a5f7e7ca048a579f2c94d2241782ecf17)) -#### Added -* Added support for point vs. (static) analytical plane contact - -### 2021-08-21 ([acf2a80](https://github.com/ipc-sim/ipc-toolkit/commit/acf2a80544ebe27dc5e440602a3a89243e575e8a)) -#### Changed -* Changed CMake target name to `ipc::toolkit` - -### 2021-07-26 ([1479aae](https://github.com/ipc-sim/ipc-toolkit/commit/1479aaea958daaa4e963529493e4169dc7757913)) -#### Changed -* Updated the CMake system to use modern `FetchContent` to download externals - -### 2021-07-22 ([e24c76d](https://github.com/ipc-sim/ipc-toolkit/commit/e24c76ddc818fb9efc4d522ef72a581a15abf751)) -#### Fixed -* Updated CCD strategy when using Tight Inclusion to only perform `no_zero_toi=true` when there is no minimum distance - -### 2021-07-17 ([a20f7a2](https://github.com/ipc-sim/ipc-toolkit/commit/a20f7a2dfea5a04c67ef71d0cd523f69391f2f54)) -#### Added -* Added `detect_edge_face_collision_candidates_brute_force` for 3D intersection broad-phase -* Added ability to save an obj of collision candidates -* Added tests for has_intersection (all pass after fixes) - -#### Fixed -* Fixed possible numerical rounding problems in HashGrid `AABB::are_overlapping` -* Fixed HashGrid's function for getting edge-face intersection candidates - -### 2021-07-15 ([7301b42](https://github.com/ipc-sim/ipc-toolkit/commit/7301b422a9b9a90c76d9e7abf2f9127bf6d0dbd6)) -#### Fixed -* Use `ignore_codimensional_vertices` in the brute force broad-phase method -* Fixed AABB inflation in brute force and SpatialHash methods - -### 2021-07-08 ([86ae4e5](https://github.com/ipc-sim/ipc-toolkit/commit/86ae4e5f87eb2c65585920ad3ca0bbb3b57702f6)) -#### Changed -* Replaced vertex group ids with more powerful can_collide function. By -default everything can collide with everything (same as before) -* Reordered parameters in `construct_constraint_set()`, -`is_collision_free()`, and `compute_collision_free_stepsize()` -* `update_barrier_stiffness` now requires the `constraint_set` rather -than building it -* `update_barrier_stiffness` dropped dhat parameter - -#### Fixed -* SpatialHash for 2D - -#### Removed -* Verison of `initial_barrier_stiffness` that computes the -constraint set and barrier gradient because there are a lot of -parameters to these functions - -### 2021-07-05 ([4d16954](https://github.com/ipc-sim/ipc-toolkit/commit/4d16954012570b3a15346b99b5aedea77266fe86)) -#### Changed -* Renamed directory `src/spatial_hash/` โ†’ `src/broad_phase/` -* Renamed files `src/ccd/broad_phase.*` โ†’ `src/ccd/aabb.*` - -### 2021-07-05 ([b3808e1](https://github.com/ipc-sim/ipc-toolkit/commit/b3808e15bdbaba9a6efd4b731db3070e85bcc4b7)) -#### Added -* Select the broad-phase method for CCD and distance constraints - * Methods: `HASH_GRID`, `SPATIAL_HASH`, `BRUTE_FORCE` -* CCD parameters for Tight Inclusion's tolerance and maximum iterations - -#### Changed -* `ignore_codimensional_vertices` to `false` by default -* CMake option `TIGHT_INCLUSION_WITH_NO_ZERO_TOI=ON` as default - -### 2021-06-18 ([aa59aeb](https://github.com/ipc-sim/ipc-toolkit/commit/aa59aeb0634af981a8f1cfbb6d2ff2b76a04d610)) -#### Changed -* `construct_friction_constraint_set` now clears the given `friction_constraint_set` - -### 2021-05-18 ([245b13b](https://github.com/ipc-sim/ipc-toolkit/commit/245b13bcc5e99ed52850ae865aaa0ad4e71a43a8)) -#### Changed -* Use TightInclusion degenerate edge-edge for point-point and point-edge CCD - -### 2021-05-11 ([5c34dcd](https://github.com/ipc-sim/ipc-toolkit/commit/5c34dcdf226d46ada962204585fa386eb9b67859)) -#### Changed -* `char*` exceptions to `std::exceptions` - -### 2021-05-06 ([24056cc](https://github.com/ipc-sim/ipc-toolkit/commit/24056ccb2ca0a03bdef8141bc5011c41547f06b5)) -#### Changed -* Gave `dhat_epsilon_scale` a default value of `1e-9` in `update_barrier_stiffness` -* :warning: Changed order of parameters to `update_barrier_stiffness` - * Flipped `bbox_diagonal` and `dhat_epsilon_scale` - -### 2021-05-06 ([81d65f3](https://github.com/ipc-sim/ipc-toolkit/commit/81d65f32e479fea32d0acc29c8a7a532fa55518b)) -#### Fixed -* Bug in output min distance of `update_barrier_stiffness` - -### 2021-05-04 ([59ec167](https://github.com/ipc-sim/ipc-toolkit/commit/59ec167b85eaf56095a2d0333bdd96146d658ebf)) -#### Changed -* Moved eigen_ext functions into ipc namespace -* Renamed max size matrices with `Max` - * `Eigen::VectorX([0-9])` โ†’ `ipc::VectorMax$1` - * `Eigen::MatrixXX([0-9])` โ†’ `ipc::VectorMax$1` - * `Eigen::ArrayMax([0-9])` โ†’ `ipc::ArrayMax$1` - -### 2021-05-03 ([664d65f](https://github.com/ipc-sim/ipc-toolkit/commit/664d65fd70dbd350b6bfe5f8a311a89ff4fef3bd)) -#### Added -* Added utility function to check for edge-edge intersection in 2D and edge-triangle intersection in 3D. -* Optionally: use GMP for exact edge-triangle intersection checks - -### 2021-05-03 ([9b4ebfc](https://github.com/ipc-sim/ipc-toolkit/commit/9b4ebfc0f458645cf33eeebf8211607f45ad9cb4)) -#### Added -* voxel_size_heuristic.cpp which suggests a good voxel size for the SpatialHash and HashGrid - -#### Changed -* Changed HashGrid voxel size to be the average edge length not considering displacement length. This results in better performance, but can result in large memory usage. - -### 2021-04-29 ([293d0ad](https://github.com/ipc-sim/ipc-toolkit/commit/293d0ad992c01df561e25c286043c9ae9b901ff0)) -#### Added -* Added TBB parallel loops to the main function (`compute_potential`, `compute_friction_potential`, `compute_collision_free_stepsize`, etc.) -* Added function `addVerticesFromEdges` that adds the vertices connected to edges in parallel and avoids duplicates - -#### Changed -* Changed the HashGrid to use `ArrayMax3` over `VectorX3` to simplify the code - -#### Fixed -* Fixed some parameters that were not by reference - -### 2021-04-21 ([c8a6d5](https://github.com/ipc-sim/ipc-toolkit/commit/c8a6d56823793e7be5e89238c3793e25bc45ffa0)) -#### Added -* Added the SpatialHash from the original IPC code base with some modification to get all candidates in parallel - * Benchmark results indicate this SpatialHash is faster than the HashGrid with multithreading - * TODO: Improve HashGrid or fully integrate SpatialHash into ipc.hpp - -### 2021-02-11 ([9c7493](https://github.com/ipc-sim/ipc-toolkit/commit/9c74938fefa691db6b79c73489c8c661638019c6)) -#### Changed -* Switched to the correct (conservative) CCD of [[Wang and Ferguson et al. 2020]](https://continuous-collision-detection.github.io/) - * Can select Etienne Vouga's CCD in the CMake (see README.md) - -### 2021-02-01 ([b510253](https://github.com/ipc-sim/ipc-toolkit/commit/b51025310223b487e7c39858265d8d5c3e8b1e8a)) -#### Added -* Added minimum seperation distance (thickness) to distance constraints - * Based on [Codimensional Incremental Potential Contact [Li et al. 2020]](https://arxiv.org/abs/2012.04457) - -### 2021-02-01 ([a395175](https://github.com/ipc-sim/ipc-toolkit/commit/a3951750ca5f167ab1d546ae1dadd87d0a9e2497)) -#### Added -* Added 2D friction model based on the 3D formulation. - * TODO: Test this further - -### 2021-01-12 ([deee6d0](https://github.com/ipc-sim/ipc-toolkit/commit/deee6d0f9802910c5565f800492f9a995e65cf7e)) -#### Added -* Added and optional parameter `F2E` to `construct_constraint_set()`. This is similar to `F` (which maps faces to vertices), but maps faces to edges. This is optional, but recommended for better performance. If not provided a simple linear search will be done per face edge! - * TODO: Add a function to compute this mapping. - -### 2021-01-09 ([deee6d0](https://github.com/ipc-sim/ipc-toolkit/commit/deee6d0f9802910c5565f800492f9a995e65cf7e)) -#### Changed -* Replaced VectorXd and MatrixXd with static size versions for local gradient and hessians - -### 2020-11-20 ([93143ad](https://github.com/ipc-sim/ipc-toolkit/commit/93143ad9b31030cde7324a83354268021e1cb9da)) -#### Changed -* Removed TBB parallelization form the hash grid because we get better performance without it. - * TODO: Improve parallelization in the hash grid or switch to the original IPC spatial hash - -### 2020-11-06 ([4553509](https://github.com/ipc-sim/ipc-toolkit/commit/4553509fe6a4e6b78c041018cd6db3fdf23b4730)) -#### Fixed -* Fixed multiplicity for point-triangle distance computation to avoid duplicate point-point and point-edge pairs. - -### 2020-10-22 ([51f4903](https://github.com/ipc-sim/ipc-toolkit/commit/51f49030dbeec15a6a7544826f5531811a779402)) -#### Fixed -* Projection of the hessian to PSD. This was completely broken as the projected matrix was never used. - -### 2020-10-22 ([9be6c0f](https://github.com/ipc-sim/ipc-toolkit/commit/9be6c0f7e2534e426e3f09f4c547406d50d5cf9c)) -#### Fixed -* Mollification of EE constraints that have a distance type of PP or PE -* If there is no mollification needed then the PP and PE constraints are stored with multiplicity -* Set the parallel EE friction constraint threshold to eps_x like in IPC - * This avoid needing the mollification for the normal force and these forces are small anyways - -### 2020-10-10 ([cb8b53f](https://github.com/ipc-sim/ipc-toolkit/commit/cb8b53fb098598ba5e8c95d4bdb4730e8df9382e)) -#### Fixed -* Assertions in `compute_collision_free_stepsize` - -### 2020-10-10 ([4a5f84f](https://github.com/ipc-sim/ipc-toolkit/commit/4a5f84f1177bdae1a265dc15a84603bbc389936d)) -#### Fixed -* Point-triangle distance type by replacing it with the one used in the original IPC code - -### 2020-10-10 ([1d51a61](https://github.com/ipc-sim/ipc-toolkit/commit/1d51a61d60bb25e08c9937285ff9e44459a2223f)) -#### Added -* Boolean parameter in `compute_friction_potential_hessian` that controls if the hessian is projected to PSD - -### 2020-10-09 ([b737fb0](https://github.com/ipc-sim/ipc-toolkit/commit/b737fb0e708eac5a7775766f162a5d2067db2fa4)) -#### Added -* Parameter for vertex group IDs to exclude some collisions (e.g., self collisions) - -### 2020-10-08 ([6ee60ae](https://github.com/ipc-sim/ipc-toolkit/commit/6ee60aeaef6d7f88013ee2ee3d544e7403282527)) -#### Added -* Second version of `update_barrier_stiffness()` that takes an already computed minimum distance and world bounding box diagonal - -### 2020-10-08 ([cc3947d](https://github.com/ipc-sim/ipc-toolkit/commit/cc3947d48bc069488f6a773424e30fe67eb4b5f1)) -#### Added -* Second version of `initial_barrier_stiffness()` that takes an already computed barrier gradient -* Assertions on `initial_barrier_stiffness()` input - * `average_mass > 0 && min_barrier_stiffness_scale > 0` - -#### Changed -* Fixed typo in `initial_barrier_stiffness()` name (was `intial_barrier_stiffness()`) - -### 2020-10-07 ([5582582](https://github.com/ipc-sim/ipc-toolkit/commit/5582582bc2f54464bfcee4ba0ec2b7e6975f596f)) -#### Added -* `FrictionConstraint` structures to store friction information (i.e., tangent basis, normal force magnitude, closest points, and coefficient of friction) -* Unit test that compares the original IPC code's friction components with the toolkit's - -#### Changed -* `compute_friction_bases()` is now `construct_friction_constraint_set()` - * It now takes the coefficient of friction (`mu`) - * It now puts all information inside of the `FrictionConstraints` (`friction_constraint_set`) - -### 2020-10-06 ([b48ba0e](https://github.com/ipc-sim/ipc-toolkit/commit/b48ba0ec9d60754e7670e28fd1987b0c78cd809f)) - -#### Changed -* During `construct_constraint_set()` the constraints are added based on distance type - * Duplicate vertex-vertex and edge-vertex constraints are handled by a multiplicity multiplier - * Edge-edge constraints are always line-line distances - * Point-triangle constraints are always point-plane distances - -### 2020-10-05 ([9a4576b](https://github.com/ipc-sim/ipc-toolkit/commit/9a4576b209302c79296593ac213ed8ce85510f3b)) - -#### Fixed -* Fixed a bug in the point-triangle closest points and tangent basis computed in `compute_friction_bases()` -* Fixed a bug in `edge_edge_tangent_basis()` used to compute the tangent basis for friction - - -### 2020-09-19 ([31a37e0](https://github.com/ipc-sim/ipc-toolkit/commit/31a37e04abc9ecec325e00be97fd42b89c895b45)) - -#### Added -* spdlog for logging information - -### 2020-09-19 ([acb7664](https://github.com/ipc-sim/ipc-toolkit/commit/acb7664792982685f6de28468ba126f5e531834f)) - -#### Changed -* Headers are now include with the prefix `ipc/` - * E.g., `#include ` โ†’ `#include ` - - -### 2020-09-04 ([7dd2ab7](https://github.com/ipc-sim/ipc-toolkit/commit/7dd2ab7a255ffd23ccdfe5aee08bca6a142f75a7)) - -#### Added -* Collision constraint to store distance constraint pairs - * `EdgeEdgeConstraint` stores the edge-edge mollifier threshold (`eps_x`) - -#### Changed -* Input parameter `dhat_squared` is now `dhat` (i.e., non-squared value) -* Input parameter `epsv_times_h_squared` is now `epsv_times_h` (i.e., non-squared value) -* `Constraints` replaced `Candidates` -* `construct_constraint_set()` now takes the rest vertex position (`V_rest`) -* `compute_barrier_potential*()` no longer take the rest vertex position diff --git a/docs/requirements.txt b/docs/requirements.txt index 2b58d9d7d..3d433741c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -7,3 +7,6 @@ breathe nbsphinx pandoc myst_parser==1.0.0 +sphinxcontrib-bibtex +sphinxemoji +sphinx-last-updated-by-git \ No newline at end of file diff --git a/docs/source/Doxyfile b/docs/source/Doxyfile index 6ae641990..ca30f3033 100644 --- a/docs/source/Doxyfile +++ b/docs/source/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.9.2 +# Doxyfile 1.9.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -12,6 +12,16 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -60,16 +70,28 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = ../build/doxyoutput -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes -# performance problems for the file system. +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode @@ -81,14 +103,14 @@ ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English @@ -452,7 +474,7 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 -# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing @@ -546,7 +568,8 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO @@ -577,14 +600,15 @@ INTERNAL_DOCS = NO # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that -# are not case sensitive the option should be be set to NO to properly deal with +# are not case sensitive the option should be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. -# The default value is: system dependent. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = NO @@ -836,6 +860,14 @@ WARN_IF_INCOMPLETE_DOC = YES WARN_NO_PARAMDOC = NO +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but @@ -851,13 +883,27 @@ WARN_AS_ERROR = NO # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = @@ -878,10 +924,21 @@ INPUT = ../../src # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. @@ -984,7 +1041,7 @@ EXCLUDE_PATTERNS = # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test +# ANamespace::AClass, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* @@ -1032,6 +1089,11 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. @@ -1073,6 +1135,15 @@ FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1170,10 +1241,11 @@ VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1220,7 +1292,6 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -# HTML_HEADER = ../_doxygen/header.html HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each @@ -1231,7 +1302,6 @@ HTML_HEADER = # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -# HTML_FOOTER = ../_doxygen/footer.html HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style @@ -1254,13 +1324,14 @@ HTML_STYLESHEET = # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -# HTML_EXTRA_STYLESHEET = ../_doxygen/doxygen-awesome.css \ -# ../_doxygen/doxygen-awesome-sidebar-only.css \ -# ../_doxygen/doxygen-awesome-sidebar-only-darkmode-toggle.css \ -# ../_doxygen/custom.css HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or @@ -1271,12 +1342,21 @@ HTML_EXTRA_STYLESHEET = # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -# HTML_EXTRA_FILES = ../_doxygen/doxygen-awesome-darkmode-toggle.js \ -# ../_doxygen/doxygen-awesome-fragment-copy-button.js \ -# ../_doxygen/doxygen-awesome-paragraph-link.js \ -# ../_doxygen/favicon.ico HTML_EXTRA_FILES = +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a color-wheel, see @@ -1371,6 +1451,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1575,7 +1662,7 @@ GENERATE_TREEVIEW = YES # area (value NO) or if it should extend to the full height of the window (value # YES). Setting this to YES gives a layout similar to # https://docs.readthedocs.io with more room for contents, but less room for the -# project logo, title, and description. If either GENERATOR_TREEVIEW or +# project logo, title, and description. If either GENERATE_TREEVIEW or # DISABLE_INDEX is set to NO, this option has no effect. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1606,6 +1693,13 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for @@ -1626,17 +1720,6 @@ HTML_FORMULA_FORMAT = png FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. @@ -1698,8 +1781,8 @@ MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example -# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7-latest/tex.html -# #tex-and-latex-extensions): +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # For example for MathJax version 3 (see # http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): @@ -2227,7 +2310,8 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2319,15 +2403,6 @@ EXTERNAL_PAGES = YES # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2360,35 +2435,50 @@ HAVE_DOT = YES DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" + +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = Helvetica +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a +# graph for each documented class showing the direct and indirect inheritance +# relations. In case HAVE_DOT is set as well dot will be used to draw the graph, +# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set +# to TEXT the direct and indirect inheritance relations will be shown as texts / +# links. +# Possible values are: NO, YES, TEXT and GRAPH. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES @@ -2402,7 +2492,8 @@ CLASS_GRAPH = YES COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# groups, showing the direct groups dependencies. See also the chapter Grouping +# in the manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2577,10 +2668,10 @@ MSCFILE_DIRS = DIAFILE_DIRS = # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = @@ -2618,18 +2709,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = YES - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2642,6 +2721,8 @@ DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 4156c14bd..3e3e0b5c1 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -1,2 +1,613 @@ -.. include:: ../CHANGELOG.md - :parser: myst_parser.sphinx_ \ No newline at end of file +Changelog +========= + +.. role:: cpp(code) + :language: c++ +.. role:: cmake(code) + :language: cmake + +v1.1.1 (Aug 18, 2023) +--------------------- + +* Logo by @zfergus in `#52 `__ +* Fix vertex-vertex :cpp:`==` and :cpp:`<` functions to be order independent + + * This allows vertex-vertex constraints merge correctly + +* Update Tight Inclusion CCD + +v1.1.0 (Jul 25, 2023) +--------------------- + +Large refactoring to make the code more object-oriented rather than passing objects to functions. Other changes include the friction potential now being a function of velocity, bug fixes, and a new tutorial. + +Details +~~~~~~~ + +* Large Refactor in `#25 `__ + + * :cpp:`construct_collision_candidates(..., candidates)` โ†’ :cpp:`candidates.build(...)` + * :cpp:`is_step_collision_free(candidates, ...)` โ†’ :cpp:`candidates.is_step_collision_free(...)` + * :cpp:`compute_collision_free_stepsize(candidates, ...)` โ†’ :cpp:`candidates.compute_collision_free_stepsize(...)` + * :cpp:`compute_barrier_potential*(constraints, ...)` โ†’ :cpp:`constraints.compute_potential*(...)` + * :cpp:`compute_shape_derivative(constraints, ...)` โ†’ :cpp:`constraints.compute_shape_derivative(...)` + * :cpp:`compute_minimum_distance(constraints, ...)` โ†’ :cpp:`constraints.compute_minimum_distance(...)` + * :cpp:`construct_friction_constraint_set(..., friction_constraints)` โ†’ :cpp:`friction_constraints.build(...)` + * :cpp:`compute_friction_*(..., friction_constraints, ...)` โ†’ :cpp:`friction_constraints.compute_*(...)` + * Generic :cpp:`CollisionStencil` parent class to :cpp:`Candidates`, :cpp:`CollisionConstraints`, and :cpp:`FrictionConstraints`. + * Renamed :cpp:`Constraints` to :cpp:`CollisionConstraints` + * Replaced single letter variable names :cpp:`V`, :cpp:`E`, :cpp:`F` with :cpp:`vertices`/:cpp:`positions`, :cpp:`edges`, :cpp:`faces` + * Renamed ``*_index`` โ†’ ``*_id`` + * Replaced :cpp:`inflation_radius = min_distance / 1.99` with :cpp:`inflation_radius = min_distance / 2` and use rounding mode to conservativly inflate AABBs + * :cpp:`CollisionConstraints::use_convergent_formulation` and :cpp:`are_shape_derivatives_enabled` must now be accessed through getter and setter functions + * Friction potentials are now functions of velocity. Previously :cpp:`V0` and :cpp:`V1` were passed and :cpp:`U = V1-V0`. This limited the integration scheme to implicit Euler. Upstream this means you need to multiply the potential by :math:`1/(dv/dx)` to get the correct friction force. + + * Change input :math:`\epsilon_vh` to :math:`\epsilon_v` in `#37 `__ to reflect the fact that friction is defined in terms of velocity instead of displacement now. + +* Changed default :cpp:`project_hessian_to_psd` to :cpp:`false` in `#30 `__ +* Update website with a tutorial (`#31 `__) and version dropdown list (`#34 `__) +* Switch from templates to using :cpp:`Eigen::Ref` in `#28 `__ +* Speed up the CCD by limiting the maximum minimum distance to :cpp:`1e-4` in `#43 `__ +* Fix the bug pointed out in `#41 `__ in `#42 `__. Namely, to get units of distance in the barrier we should divide the original function by :math:`\hat{d}\cdot(\hat{d} + 2d_{\min})^2` when using distance squared. Before it was being divided by :math:`2d_{\min} \hat{d} + \hat{d}^2`. +* Fix build for IPC_TOOLKIT_WITH_CORRECT_CCD=OFF in `#44 `__ +* Switched from FetchContent to CPM in `#48 `__. This provides better caching between builds. Additionally, made robin-map and Abseil optional dependencies. +* Add the CFL-Inspired Culling of CCD as described in Section 3 of the Technical Supplement to IPC in `#50 `__ + +v1.0.0 (Feb 21, 2023) +--------------------- + +This is the first official release. |:rocket:| + +This is a stable release of the toolkit prior to refactoring the code and making updates to the API. + +.. _details-1: + +Details +~~~~~~~ + +* Added a minimum distance optional parameter to all CCD functions (:cpp:`const double min_distance = 0.0`) in `#22 `__. This is placed as the first optional argument which can break calling code if optional parameters were previously used. +* Added :cpp:`CollisionMesh` in `#7 `__ to wrap up face and edges into a single data structure. + + * Removes Support for ignoring internal vertices. Instead, users should use the CollisionMesh to map from the full mesh to the surface mesh. + * This also includes a :cpp:`to_full_dof` function that can map the reduced gradient/hessian to the full mesh's DOF. + +Pre-v1.0.0 +---------- + +2021-10-05 (`9e2cc2a `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Added +^^^^^ + +* Added implicits source folder to organize point-plane collisions + +.. _e2cc2a-1: + +2021-09-05 (`9e2cc2a `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-1: + +Added +^^^^^ + +* Added support for point vs. (static) analytical plane contact + +2021-08-21 (`acf2a80 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Changed +^^^^^^^ + +* Changed CMake target name to :cmake:`ipc::toolkit` + +2021-07-26 (`1479aae `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-1: + +Changed +^^^^^^^ + +* Updated the CMake system to use modern :cpp:`FetchContent` to download externals + +2021-07-22 (`e24c76d `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Fixed +^^^^^ + +* Updated CCD strategy when using Tight Inclusion to only perform :cpp:`no_zero_toi=true` when there is no minimum distance + +2021-07-17 (`a20f7a2 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-2: + +Added +^^^^^ + +* Added :cpp:`detect_edge_face_collision_candidates_brute_force` for 3D intersection broad-phase +* Added ability to save an obj of collision candidates +* Added tests for has_intersection (all pass after fixes) + +.. _fixed-1: + +Fixed +^^^^^ + +* Fixed possible numerical rounding problems in HashGrid :cpp:`AABB::are_overlapping` +* Fixed HashGrid's function for getting edge-face intersection candidates + +2021-07-15 (`7301b42 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-2: + +Fixed +^^^^^ + +* Use :cpp:`ignore_codimensional_vertices` in the brute force broad-phase method +* Fixed AABB inflation in brute force and SpatialHash methods + +2021-07-08 (`86ae4e5 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-2: + +Changed +^^^^^^^ + +* Replaced vertex group ids with more powerful can_collide function. By default everything can collide with everything (same as before) +* Reordered parameters in :cpp:`construct_constraint_set()`, :cpp:`is_collision_free()`, and :cpp:`compute_collision_free_stepsize()` +* :cpp:`update_barrier_stiffness` now requires the :cpp:`constraint_set` rather than building it +* :cpp:`update_barrier_stiffness` dropped dhat parameter + +.. _fixed-3: + +Fixed +^^^^^ + +* SpatialHash for 2D + +Removed +^^^^^^^ + +* Verison of :cpp:`initial_barrier_stiffness` that computes the constraint set and barrier gradient because there are a lot of parameters to these functions + +2021-07-05 (`4d16954 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-3: + +Changed +^^^^^^^ + +* Renamed directory ``src/spatial_hash/`` โ†’ ``src/broad_phase/`` +* Renamed files ``src/ccd/broad_phase.*`` โ†’ ``src/ccd/aabb.*`` + +2021-07-05 (`b3808e1 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-3: + +Added +^^^^^ + +* Select the broad-phase method for CCD and distance constraints + + * Methods: :cpp:`HASH_GRID`, :cpp:`SPATIAL_HASH`, :cpp:`BRUTE_FORCE` + +* CCD parameters for Tight Inclusion's tolerance and maximum iterations + +.. _changed-4: + +Changed +^^^^^^^ + +* :cpp:`ignore_codimensional_vertices` to :cpp:`false` by default +* CMake option :cmake:`TIGHT_INCLUSION_WITH_NO_ZERO_TOI=ON` as default + +2021-06-18 (`aa59aeb `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-5: + +Changed +^^^^^^^ + +* :cpp:`construct_friction_constraint_set` now clears the given :cpp:`friction_constraint_set` + +2021-05-18 (`245b13b `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-6: + +Changed +^^^^^^^ + +* Use TightInclusion degenerate edge-edge for point-point and point-edge CCD + +2021-05-11 (`5c34dcd `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-7: + +Changed +^^^^^^^ + +* :cpp:`char*` exceptions to :cpp:`std::exceptions` + +2021-05-06 (`24056cc `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-8: + +Changed +^^^^^^^ + +* Gave :cpp:`dhat_epsilon_scale` a default value of :cpp:`1e-9` in :cpp:`update_barrier_stiffness` +* :warning: Changed order of parameters to :cpp:`update_barrier_stiffness` + + * Flipped :cpp:`bbox_diagonal` and :cpp:`dhat_epsilon_scale` + +2021-05-06 (`81d65f3 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-4: + +Fixed +^^^^^ + +* Bug in output min distance of :cpp:`update_barrier_stiffness` + +2021-05-04 (`59ec167 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-9: + +Changed +^^^^^^^ + +* Moved eigen_ext functions into ipc namespace +* Renamed max size matrices with ``Max`` + + * ``Eigen::VectorX([0-9])`` โ†’ ``ipc::VectorMax$1`` + * ``Eigen::MatrixXX([0-9])`` โ†’ ``ipc::VectorMax$1`` + * ``Eigen::ArrayMax([0-9])`` โ†’ ``ipc::ArrayMax$1`` + +2021-05-03 (`664d65f `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-4: + +Added +^^^^^ + +* Added utility function to check for edge-edge intersection in 2D and edge-triangle intersection in 3D. +* Optionally: use GMP for exact edge-triangle intersection checks + +2021-05-03 (`9b4ebfc `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-5: + +Added +^^^^^ + +* voxel_size_heuristic.cpp which suggests a good voxel size for the :cpp:`SpatialHash` and :cpp:`HashGrid` + +.. _changed-10: + +Changed +^^^^^^^ + +* Changed HashGrid voxel size to be the average edge length not considering displacement length. This results in better performance, but can result in large memory usage. + +2021-04-29 (`293d0ad `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-6: + +Added +^^^^^ + +* Added TBB parallel loops to the main function (:cpp:`compute_potential`, :cpp:`compute_friction_potential`, :cpp:`compute_collision_free_stepsize`, etc.) +* Added function :cpp:`addVerticesFromEdges` that adds the vertices connected to edges in parallel and avoids duplicates + +.. _changed-11: + +Changed +^^^^^^^ + +* Changed the HashGrid to use :cpp:`ArrayMax3` over :cpp:`VectorX3` to simplify the code + +.. _fixed-5: + +Fixed +^^^^^ + +* Fixed some parameters that were not by reference + +2021-04-21 (`c8a6d5 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-7: + +Added +^^^^^ + +* Added the SpatialHash from the original IPC code base with some modification to get all candidates in parallel + + * Benchmark results indicate this SpatialHash is faster than the HashGrid with multithreading + * TODO: Improve HashGrid or fully integrate SpatialHash into ipc.hpp + +2021-02-11 (`9c7493 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-12: + +Changed +^^^^^^^ + +* Switched to the correct (conservative) CCD of :cite:t:`Wang2021TightInclusion` + + * Can select Etienne Vouga's CCD in the CMake (see README.md) + +2021-02-01 (`b510253 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-8: + +Added +^^^^^ + +* Added minimum seperation distance (thickness) to distance constraints + + * Based on "Codimensional Incremental Potential Contact" :cite:p:`Li2021CIPC` + +2021-02-01 (`a395175 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-9: + +Added +^^^^^ + +* Added 2D friction model based on the 3D formulation. + + * TODO: Test this further + +2021-01-12 (`deee6d0 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-10: + +Added +^^^^^ + +* Added and optional parameter :cpp:`F2E` to :cpp:`construct_constraint_set()`. This is similar to :cpp:`F` (which maps faces to vertices), but maps faces to edges. This is optional, but recommended for better performance. If not provided a simple linear search will be done per face edge! + + * TODO: Add a function to compute this mapping. + +.. _deee6d0-1: + +2021-01-09 (`deee6d0 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-13: + +Changed +^^^^^^^ + +* Replaced VectorXd and MatrixXd with static size versions for local gradient and hessians + +2020-11-20 (`93143ad `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-14: + +Changed +^^^^^^^ + +* Removed TBB parallelization form the hash grid because we get better performance without it. + + * TODO: Improve parallelization in the hash grid or switch to the original IPC spatial hash + +2020-11-06 (`4553509 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-6: + +Fixed +^^^^^ + +* Fixed multiplicity for point-triangle distance computation to avoid duplicate point-point and point-edge pairs. + +2020-10-22 (`51f4903 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-7: + +Fixed +^^^^^ + +* Projection of the hessian to PSD. This was completely broken as the projected matrix was never used. + +2020-10-22 (`9be6c0f `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-8: + +Fixed +^^^^^ + +* Mollification of EE constraints that have a distance type of PP or PE +* If there is no mollification needed then the PP and PE constraints are stored with multiplicity +* Set the parallel EE friction constraint threshold to eps_x like in IPC + + * This avoid needing the mollification for the normal force and these forces are small anyways + +2020-10-10 (`cb8b53f `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-9: + +Fixed +^^^^^ + +* Assertions in :cpp:`compute_collision_free_stepsize` + +2020-10-10 (`4a5f84f `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-10: + +Fixed +^^^^^ + +* Point-triangle distance type by replacing it with the one used in the original IPC code + +2020-10-10 (`1d51a61 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-11: + +Added +^^^^^ + +* Boolean parameter in :cpp:`compute_friction_potential_hessian` that controls if the hessian is projected to PSD + +2020-10-09 (`b737fb0 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-12: + +Added +^^^^^ + +* Parameter for vertex group IDs to exclude some collisions (e.g., self collisions) + +2020-10-08 (`6ee60ae `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-13: + +Added +^^^^^ + +* Second version of :cpp:`update_barrier_stiffness()` that takes an already computed minimum distance and world bounding box diagonal + +2020-10-08 (`cc3947d `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-14: + +Added +^^^^^ + +* Second version of :cpp:`initial_barrier_stiffness()` that takes an already computed barrier gradient +* Assertions on :cpp:`initial_barrier_stiffness()` input + + * :cpp:`average_mass > 0 && min_barrier_stiffness_scale > 0` + +.. _changed-15: + +Changed +^^^^^^^ + +* Fixed typo in :cpp:`initial_barrier_stiffness()` name (was :cpp:`intial_barrier_stiffness()`) + +.. _section-1: + +2020-10-07 (`5582582 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-15: + +Added +^^^^^ + +* :cpp:`FrictionConstraint` structures to store friction information (i.e., tangent basis, normal force magnitude, closest points, and coefficient of friction) +* Unit test that compares the original IPC code's friction components with the toolkit's + +.. _changed-16: + +Changed +^^^^^^^ + +* :cpp:`compute_friction_bases()` is now :cpp:`construct_friction_constraint_set()` + + * It now takes the coefficient of friction (:cpp:`mu`) + * It now puts all information inside of the :cpp:`FrictionConstraints` (:cpp:`friction_constraint_set`) + +2020-10-06 (`b48ba0e `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-17: + +Changed +^^^^^^^ + +* During :cpp:`construct_constraint_set()` the constraints are added based on distance type + + * Duplicate vertex-vertex and edge-vertex constraints are handled by a multiplicity multiplier + * Edge-edge constraints are always line-line distances + * Point-triangle constraints are always point-plane distances + +2020-10-05 (`9a4576b `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _fixed-11: + +Fixed +^^^^^ + +* Fixed a bug in the point-triangle closest points and tangent basis computed in :cpp:`compute_friction_bases()` +* Fixed a bug in :cpp:`edge_edge_tangent_basis()` used to compute the tangent basis for friction + +2020-09-19 (`31a37e0 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-16: + +Added +^^^^^ + +* spdlog for logging information + +2020-09-19 (`acb7664 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _changed-18: + +Changed +^^^^^^^ + +* Headers are now include with the prefix ``ipc/`` + + * E.g., :cpp:`#include ` โ†’ :cpp:`#include ` + +2020-09-04 (`7dd2ab7 `__) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _added-17: + +Added +^^^^^ + +* Collision constraint to store distance constraint pairs + + * :cpp:`EdgeEdgeConstraint` stores the edge-edge mollifier threshold (:cpp:`eps_x`) + +.. _changed-19: + +Changed +^^^^^^^ + +* Input parameter :cpp:`dhat_squared` is now :cpp:`dhat` (i.e., non-squared value) +* Input parameter :cpp:`epsv_times_h_squared` is now :cpp:`epsv_times_h` (i.e., non-squared value) +* :cpp:`Constraints` replaced :cpp:`Candidates` +* :cpp:`construct_constraint_set()` now takes the rest vertex position (:cpp:`V_rest`) +* :cpp:`compute_barrier_potential*()` no longer take the rest vertex position diff --git a/docs/source/conf.py b/docs/source/conf.py index 243757741..332b002ba 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -42,7 +42,7 @@ "sphinx.ext.autosummary", "sphinx.ext.napoleon", "sphinx.ext.intersphinx", - "sphinx.ext.autosectionlabel", + # "sphinx.ext.autosectionlabel", "sphinx.ext.todo", "sphinx.ext.mathjax", "sphinx.ext.ifconfig", @@ -56,8 +56,15 @@ "sphinx_immaterial.apidoc.python.apigen", "sphinx_immaterial.apidoc.format_signatures", # 'sphinx_autodoc_toolbox.collapse', + "sphinxcontrib.bibtex", + "sphinxemoji.sphinxemoji", + "sphinx_last_updated_by_git", ] +bibtex_bibfiles = ['refs.bib'] +bibtex_reference_style = 'author_year' +bibtex_default_style = 'plain' + myst_enable_extensions = [ "dollarmath", ] @@ -178,7 +185,6 @@ # Set the repo location to get a badge with stats "repo_url": "https://github.com/ipc-sim/ipc-toolkit", "repo_name": "ipc-sim/ipc-toolkit", - "repo_type": "github", "icon": {"repo": "fontawesome/brands/github"}, "edit_uri": "blob/main/docs/source", @@ -219,4 +225,4 @@ # or fully qualified paths (eg. https://...) html_css_files = ["css/custom.css"] -html_last_updated_fmt = "%B %d, %Y" +# html_last_updated_fmt = "%B %d, %Y" diff --git a/docs/source/cpp.rst b/docs/source/cpp.rst index 1e72a3eb1..ad6a56c5a 100644 --- a/docs/source/cpp.rst +++ b/docs/source/cpp.rst @@ -64,18 +64,25 @@ Optional -------- * `robin-map `__: faster hash set/map than :cpp:`std::unordered_set`/:cpp:`std::unordered_map` - * Enable by using the CMake option :cmake:`IPC_TOOLKIT_WITH_ROBIN_MAP` - * Enabled by default + + * Enable by using the CMake option :cmake:`IPC_TOOLKIT_WITH_ROBIN_MAP` + * Enabled by default + * `Abseil `__: hashing utilities - * Enable by using the CMake option :cmake:`IPC_TOOLKIT_WITH_ABSEIL` - * Enabled by default + + * Enable by using the CMake option :cmake:`IPC_TOOLKIT_WITH_ABSEIL` + * Enabled by default + * `GMP `__: rational arithmetic used for exact intersection checks - * Enable by using the CMake option :cmake:`IPC_TOOLKIT_WITH_RATIONAL_INTERSECTION` - * GMP must be installed at a system level + + * Enable by using the CMake option :cmake:`IPC_TOOLKIT_WITH_RATIONAL_INTERSECTION` + * GMP must be installed at a system level + * `Etienne Vouga's Collision Detection Library `__: inexact CCD - * Included for comparison with the original IPC library - * Enable by disabling the CMake option :cmake:`IPC_TOOLKIT_WITH_CORRECT_CCD` - * Replaces the default Tight-Inclusion CCD + + * Included for comparison with the original IPC library + * Enable by disabling the CMake option :cmake:`IPC_TOOLKIT_WITH_CORRECT_CCD` + * Replaces the default Tight-Inclusion CCD Usage ----- diff --git a/docs/source/index.rst b/docs/source/index.rst index ef5d627f5..f0e6fe43b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ tutorial/getting_started.rst tutorial/simulation.rst tutorial/misc.rst + tutorial/references.rst .. toctree:: :caption: C++ @@ -20,9 +21,9 @@ Getting Started cpp-api/collision_mesh.rst + cpp-api/candidates.rst cpp-api/collision_constraints.rst cpp-api/friction.rst - cpp-api/candidates.rst cpp-api/broad_phase.rst cpp-api/ccd.rst cpp-api/distance.rst @@ -35,9 +36,9 @@ Getting Started python-api/collision_mesh.rst + python-api/candidates.rst python-api/collision_constraints.rst python-api/friction.rst - python-api/candidates.rst python-api/broad_phase.rst python-api/ccd.rst python-api/distance.rst diff --git a/docs/source/refs.bib b/docs/source/refs.bib new file mode 100644 index 000000000..eafbe4ddd --- /dev/null +++ b/docs/source/refs.bib @@ -0,0 +1,60 @@ +@article{Li2020IPC, + title = {Incremental Potential Contact: Intersection- and Inversion-free Large Deformation Dynamics}, + author = {Minchen Li and Zachary Ferguson and Teseo Schneider and Timothy Langlois and Denis Zorin and Daniele Panozzo and Chenfanfu Jiang and Danny M. Kaufman}, + year = 2020, + journal = {ACM Transactions on Graphics (SIGGRAPH)}, + volume = 39, + number = 4, + articleno = 49, + note = {\url{https://ipc-sim.github.io}} +} +@article{Li2021CIPC, + title = {Codimensional Incremental Potential Contact}, + author = {Minchen Li and Danny M. Kaufman and Chenfanfu Jiang}, + year = 2021, + journal = {ACM Transactions on Graphics (SIGGRAPH)}, + volume = 40, + number = 4, + articleno = 170, + note = {\url{https://ipc-sim.github.io/C-IPC}} +} +@misc{Li2023Convergent, + title = {Convergent Incremental Potential Contact}, + author = {Minchen Li and Zachary Ferguson and Teseo Schneider and Timothy Langlois and Denis Zorin and Daniele Panozzo and Chenfanfu Jiang and Danny M. Kaufman}, + year = 2023, + eprint = {2307.15908}, + archiveprefix = {arXiv}, + primaryclass = {math.NA} +} +@article{Wang2021TightInclusion, + title = {A Large Scale Benchmark and an Inclusion-Based Algorithm for Continuous Collision Detection}, + author = {Bolun Wang and Zachary Ferguson and Teseo Schneider and Xin Jiang and Marco Attene and Daniele Panozzo}, + year = 2021, + month = oct, + journal = {ACM Transactions on Graphics}, + volume = 40, + number = 5, + articleno = 188, + numpages = 16, + note = {\url{https://continuous-collision-detection.github.io/tight_inclusion/}} +} +@misc{Belgrod2023Time, + title = {Time of Impact Dataset for Continuous Collision Detection and a Scalable Conservative Algorithm}, + author = {David Belgrod and Bolun Wang and Zachary Ferguson and Xin Zhao and Marco Attene and Daniele Panozzo and Teseo Schneider}, + year = 2023, + eprint = {2112.06300}, + archiveprefix = {arXiv}, + primaryclass = {cs.GR} +} +@inproceedings{Ferguson2023HighOrderIPC, + title = {High-Order Incremental Potential Contact for Elastodynamic Simulation on Curved Meshes}, + author = {Zachary Ferguson and Pranav Jain and Denis Zorin and Teseo Schneider and Daniele Panozzo}, + year = 2023, + booktitle = {{ACM} {SIGGRAPH} 2023 Conference Proceedings}, + location = {Los Angeles, CA, USA}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + series = {SIGGRAPH '23}, + numpages = 11, + note = {\url{https://zferg.us/research/high-order-ipc/}} +} \ No newline at end of file diff --git a/docs/source/tutorial/getting_started.rst b/docs/source/tutorial/getting_started.rst index 2797b5f96..afec07452 100644 --- a/docs/source/tutorial/getting_started.rst +++ b/docs/source/tutorial/getting_started.rst @@ -42,14 +42,14 @@ We will start by creating a collision mesh from a ``bunny.obj`` mesh file (you c mesh = meshio.read("bunny.obj") rest_positions = mesh.points - faces = mesh.cells[0].data + faces = mesh.cells_dict["triangles"] edges = ipctk.edges(faces) collision_mesh = ipctk.CollisionMesh(rest_positions, edges, faces) The matrix ``rest_positions`` contains the undeformed positions of the vertices. It should be :math:`|V| \times d` where :math:`|V|` is the number of vertices and :math:`d \in \{2, 3\}` is the dimension. -Each row of the ``edges`` and ``faces`` matrices contain the vertex IDs (row number in ``rest_positions``) of the edge or face's vertices. -The size of ``edges`` and ``faces`` are ``#E x 2`` and ``#F x 3`` respectively (``#E`` and ``#F`` are the number of edges and faces). +Each row of the ``edges`` and ``faces`` matrices contains the vertex IDs (row number in ``rest_positions``) of the edge or face's vertices. +The sizes of ``edges`` and ``faces`` are ``#E x 2`` and ``#F x 3`` respectively (``#E`` and ``#F`` are the number of edges and faces). .. note:: Only linear triangular faces are supported. If your mesh has nonlinear or non-triangular faces, you will need to triangulate them. @@ -127,20 +127,20 @@ Now we can compute the contact potential using the ``CollisionConstraints``. contact_potential = collision_constraints.compute_potential( collision_mesh, vertices, dhat) -This returns a scalar value ``contact_potential`` which is the sum of the contact potential for each active constraint. +This returns a scalar value ``contact_potential`` which is the sum of the contact potentials for each active constraint. Mathematically this is defined as .. math:: - B(x) = \sum_{k \in C} b\left(d_k(x)\right), + B(x) = \sum_{k \in C} b(d_k(x), \hat{d}), -where :math:`C` is the active collision constraints, :math:`d_k` is the distance (squared) of the :math:`k`-th active constraint, and :math:`b` is IPC's C2-clamped log-barrier function. +where :math:`x` is our deformed vertex positions, :math:`C` is the active collision constraints, :math:`d_k` is the distance (squared) of the :math:`k`-th active constraint, and :math:`b` is IPC's C2-clamped log-barrier function. .. note:: - This is not premultiplied by the barrier stiffness :math:`\kappa`. + This is **not** premultiplied by the barrier stiffness :math:`\kappa`. -Contact Potential Derivative -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Contact Potential Derivatives +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ We can also compute the first and second derivatives of the contact potential with respect to the vertex positions. @@ -253,7 +253,7 @@ Adaptive Barrier Stiffness The last piece of the contact potential is the barrier stiffness. This is a weight that is multiplied by the barrier potential to better scale it relative to the energy potential. This can be a fixed value or adaptive. -To compute the adaptive barrier stiffness, we can use two functions: ``initial_barrier_stiffness`` and ``update_barrier_stiffness``. The function ``initial_barrier_stiffness`` compute the initial value from the current energy and contact potential gradients. This function also provides a minimum and maximum value for the barrier stiffness. The function ``update_barrier_stiffness`` updates the barrier stiffness if the minimum distance has become too small. +To compute the adaptive barrier stiffness, we can use two functions: ``initial_barrier_stiffness`` and ``update_barrier_stiffness``. The function ``initial_barrier_stiffness``computes the initial value from the current energy and contact potential gradients. This function also provides a minimum and maximum value for the barrier stiffness. The function ``update_barrier_stiffness`` updates the barrier stiffness if the minimum distance has become too small. .. md-tab-set:: @@ -327,6 +327,145 @@ To compute the adaptive barrier stiffness, we can use two functions: ``initial_b # (next iteration) +.. _convergent-contact-formulation: + +Convergent Formulation +^^^^^^^^^^^^^^^^^^^^^^ + +In addition to the original implementation of :cite:t:`Li2020IPC`, we also implement the convergent formulation of :cite:t:`Li2023Convergent`. + +To enable the convergent formulation, we need to set ``use_convergent_formulation``: + +.. md-tab-set:: + + .. md-tab-item:: C++ + + .. code-block:: c++ + + collision_constraints.set_use_convergent_formulation(true); + collision_constraints.build(collision_mesh, vertices, dhat); + + .. md-tab-item:: Python + + .. code-block:: python + + collision_constraints.use_convergent_formulation = True + collision_constraints.build(collision_mesh, vertices, dhat) + +.. important:: + The variable ``use_convergent_formulation`` should be set before calling ``CollisionConstraints::build`` for it to take effect. By default, it is ``false``. + +Technical Details +''''''''''''''''' + +*We breifly summarize the convergent formulation here for convenience.* + +In order to derive a convergent formulation, we first define a continous form of our barrier potential :math:`P`. For a surface :math:`\mathcal{S}` embeded in 3D space, we parameterize the surfaces by common (possibly discontinuous) coordinates :math:`u \in \tilde{M} \subset \mathbb{R}^2`, so that :math:`\mathcal{S}(u)` traverses the material points across all surfaces contiguously. The total contact potential is then + +.. math:: + P(\mathcal{S})=\frac{1}{2} \int_{u \in \tilde{M}} \max _{v \in \tilde{M} \setminus{ }_r u} b(d(\mathcal{S}(u), \mathcal{S}(v)), \hat{d})~\mathrm{d} u, + +where we define the operator :math:`\setminus_r: \mathcal{P}(\mathbb{R}^2) \times \mathbb{R} \times \mathbb{R}^2 \mapsto \mathcal{P}(\mathbb{R}^2)` to be + +.. math:: + \tilde{M} \setminus_r u:=\left\{v \in \tilde{M} \mid\|u-v\|_2>r\right\} + +with :math:`r \rightarrow 0`. + +We then define our surface discretization with a triangulated boundary mesh geometry. As in the smooth case we can parameterize the domain across all polylines with :math:`u \in \tilde{M}` so that :math:`p(u): \tilde{M} \mapsto \mathbb{R}^3` traverses all material points, across all triangles :math:`t โˆˆ T` in the triangle mesh contiguously. The corresponding surface contact potential is then + +.. math:: + \frac{1}{2} \int_{u \in \tilde{M}} \max_{t \in T \backslash p(u)} b(d(p(u), t), \hat{d})~\mathrm{d} u, + +where :math:`T \setminus p` is the set of boundary faces that do not contain the point p. + +Applying mesh vertices as nodes (and quadrature points), we numerically integrate the surface contact potential. For each nodal position :math:`x \in V` we then have a corresponding material space coordinate :math:`\bar{x} \in \bar{V}`. Piecewise linear integration of the surface barrier is then + +.. math:: + \frac{1}{2} \sum_{\bar{x} \in \bar{V}} w_{\bar{x}} \max _{t \in T \backslash x(\bar{x})} b(d(x(\bar{x}), t), \hat{d}), + +where :math:`w_{\bar{x}}` are the quadrature weights, each given by one third of the sum of the areas (in material space) of the boundary triangles incident to :math:`\bar{x}`. + +We next need to smoothly approximate the max operator in the contact potentials. However, common approaches such as an :math:`L^p`-norm or LogSumExp would decrease sparsity in subsequent numerical solves by increasing stencil-size per contact evaluation. We instead leverage the locality of our barrier function to approximate the max operator by removing duplicate distance pairs. Our resulting approximators for a trianglated surfaces is + +.. math:: + \begin{aligned} + \Psi_s(x) & =\sum_{t \in T \backslash x} b(d(x, t), \hat{d})-\sum_{e \in E_{\text {int }} \backslash x} b(d(x, e), \hat{d})+\sum_{x_2 \in V_{i n t} \backslash x} b\left(d\left(x, x_2\right), \hat{d}\right) \\ + & \approx \max _{t \in T \backslash x} b(d(x, t), \hat{d}), + \end{aligned} + +where :math:`V_{\text{int}} \subseteq V` is the subset of internal surface nodes and :math:`E_{\text{int}} \subseteq E` is the subset of internal surface edges (i.e., edges incident to two triangles). For locally convex regions this estimator is tight while remaining smooth. In turn, for nonconvex regions it improves over direct summation. + +The corresponding discrete barrier potential is then simply + +.. math:: + P_s(V)= \frac{1}{2} \sum_{x \in V} w_x \Psi_s(x). + +Please, see the `paper `_ for more details (including the formulation for 2D curves and edge-edge contact) and evaluation. + +The key difference between the original and the convergent formulations is that we (1) include area weights in the barrier potential and (2) include additional (negative) terms to cancel out the duplicate distance pairs. While this requires minor algorithmic changes, it produces considerably better results. + +Physical Barrier +'''''''''''''''' + +We want our barrier potential to have the same units of as our elastic potential (e.g., :math:`\text{J}`). Together with the area weighting (discussed above) this means the barrier should has units of pressure times distance (e.g., :math:`\text{Pa} \cdot \text{m}`). That is, + +.. math:: + \text{Pa} \cdot \text{m} \cdot \text{m}^2 = \frac{\text{N}}{\text{m}^2} \cdot \text{m} \cdot \text{m}^2 = \text{N} \cdot \text{m} = \text{J}. + +To achieve this, (when using the convergent formulation) we modify the barrier function to have units of distance: + +.. math:: + b(d, \hat{d})=\left\{\begin{array}{lr} + -\hat{d}\left(\frac{d}{\hat{d}}-1\right)^2 \ln \left(\frac{d}{\hat{d}}\right), & 0`). + Friction -------- @@ -339,7 +478,7 @@ Computing the friction dissipative potential is similar to the contact potential .. code-block:: c++ ipc::FrictionConstraints friction_constraints; - collision_constraints.build( + friction_constraints.build( collision_mesh, vertices, contact_constraints, dhat, barrier_stiffness, mu); .. md-tab-item:: Python @@ -379,16 +518,16 @@ Here ``epsv`` (:math:`\epsilon_v`) is the static friction threshold (in units of The friction potential is a function of the velocities rather than the positions. We can compute the velocities directly from the current and previous position(s) based on our time-integration scheme. For example, if we are using backward Euler integration, then the velocity is .. math:: - v = \frac{x - x_{n-1}}{h}, + v = \frac{x - x^t}{h}, - where :math:`x` is the current position, :math:`x_{n-1}` is the previous position, and :math:`h` is the time step size. + where :math:`x` is the current position, :math:`x^t` is the previous position, and :math:`h` is the time step size. This returns a scalar value ``friction_potential`` which is the sum of the individual friction potentials. Mathematically this is defined as .. math:: - D(x) = \sum_{k \in C} \mu\lambda_k^nf_0\left(\|T_k^Tv\|; \epsilon_v\right), + D(x) = \sum_{k \in C} \mu\lambda_k^nf_0\left(\|T_k^Tv\|, \epsilon_v\right), where :math:`C` is the lagged collision constraints, :math:`\lambda_k^n` is the normal force magnitude for the :math:`k`-th contact, :math:`T_k` is the tangential basis for the :math:`k`-th contact, and :math:`f_0` is the smooth friction function used to approximate the non-smooth transition from dynamic to static friction. @@ -421,6 +560,15 @@ We can also compute the first and second derivatives of the friction dissipative friction_potential_hess = friction_constraints.compute_potential_hessian( collision_mesh, velocity, epsv) +.. _convergent-friction-formulation: + +Convergent Formulation +^^^^^^^^^^^^^^^^^^^^^^ + +Just as with the :ref:`collision constraints `, we implement both the original friction formulation of :cite:t:`Li2020IPC` and the convergent formulation of :cite:t:`Li2023Convergent`. + +The choice of formulation is dependent on how the fixed set of ``contact_constraints`` given to ``FrictionConstraints::build`` was built. If the ``contact_constraints`` were built using the convergent formulation, then the friction constraints will also use the convergent formulation. Otherwise, the original formulation will be used. + Continuous Collision Detection ------------------------------ @@ -436,9 +584,9 @@ The following example determines the maximum step size allowable between the res .. code-block:: c++ - Eigen::MatrixXd vertices_t0 = collision_mesh.rest_positions(); - Eigen::MatrixXd vertices_t1 = vertices_t0; - vertices_t1.col(1) *= 0.01; + Eigen::MatrixXd vertices_t0 = collision_mesh.rest_positions(); // vertices at t=0 + Eigen::MatrixXd vertices_t1 = vertices_t0; // vertices at t=1 + vertices_t1.col(1) *= 0.01; // squash the mesh in the y-direction double max_step_size = compute_collision_free_stepsize( collision_mesh, vertices_t0, vertices_t1); @@ -451,13 +599,175 @@ The following example determines the maximum step size allowable between the res .. code-block:: python - vertices_t0 = collision_mesh.rest_positions() - vertices_t1 = vertices_t0 - vertices_t1[:, 1] *= 0.01 + vertices_t0 = collision_mesh.rest_positions() # vertices at t=0 + vertices_t1 = vertices_t0.copy() # vertices at t=1 + vertices_t1[:, 1] *= 0.01 # squash the mesh in the y-direction max_step_size = compute_collision_free_stepsize( collision_mesh, vertices_t0, vertices_t1) collision_free_vertices = (vertices_t1 - vertices_t0) * max_step_size + vertices_t0 - assert(is_step_collision_free(mesh, vertices_t0, collision_free_vertices)) \ No newline at end of file + assert(is_step_collision_free(mesh, vertices_t0, collision_free_vertices)) + +CCD is comprised of two parts (phases): broad-phase and narrow-phase. + +Broad-Phase +^^^^^^^^^^^ + +The broad-phase takes all possible pairings (quadratic in size) and eliminates (culls) pairs whose bounding boxes do not overlap. This is done using a spatial data structure (e.g., a hash grid or spatial hash). + +The ``Candidates`` class represents the culled set of candidate pairs and is built by using a broad-phase method. The following example shows how to use the broad-phase to determine the candidate pairs between the rest_positions and the squashed bunny. + +.. md-tab-set:: + + .. md-tab-item:: C++ + + .. code-block:: c++ + + #include + + ipc::Candidates candidates; + candidates.build( + mesh, vertices_t0, vertices_t1, + /*inflation_radius=*/0.0, + /*broad_phase_method=*/ipc::BroadPhaseMethod::HASH_GRID); + + .. md-tab-item:: Python + + .. code-block:: python + + candidates = ipctk.Candidates() + candidates.build( + mesh, vertices_t0, vertices_t1, + broad_phase_method=ipctk.BroadPhaseMethod.HASH_GRID) + +Possible values for ``broad_phase_method`` are: ``BRUTE_FORCE`` (parallel brute force culling), ``HASH_GRID`` (default), ``SPATIAL_HASH`` (implementation from the original IPC codebase), ``SWEEP_AND_TINIEST_QUEUE`` (method of :cite:t:`Belgrod2023Time`), or ``SWEEP_AND_TINIEST_QUEUE_GPU`` (requires CUDA). + +Narrow-Phase +^^^^^^^^^^^^ + +The narrow-phase computes the time of impact between two primitives (e.g., a point and a triangle or two edges in 3D). To do this we utilize the Tight Inclusion CCD method of :cite:t:`Wang2021TightInclusion` for the narrow-phase as it is provably conservative (i.e., never misses collisions), accurate (i.e., rarely reports false positives), and efficient. + +The following example shows how to use the narrow-phase to determine if a point is colliding with a triangle (static in this case). + +.. md-tab-set:: + + .. md-tab-item:: C++ + + .. code-block:: c++ + + #include + + // ... + + Eigen::Vector3d p_t0(0.0, -1.0, 0.0); // point at t=0 + Eigen::Vector3d p_t1(0.0, 1.0, 0.0); // point at t=1 + + Eigen::Vector3d t0_t0(-1.0, 0.0, 1.0); // triangle vertex 0 at t=0 + Eigen::Vector3d t1_t0( 1.0, 0.0, 1.0); // triangle vertex 1 at t=0 + Eigen::Vector3d t2_t0( 0.0, 0.0, -1.0); // triangle vertex 2 at t=0 + + // static triangle + Eigen::Vector3d t0_t1 = t0_t0; // triangle vertex 0 at t=1 + Eigen::Vector3d t1_t1 = t1_t0; // triangle vertex 1 at t=1 + Eigen::Vector3d t2_t1 = t2_t0; // triangle vertex 2 at t=1 + + double toi; // output time of impact + bool is_colliding = ipc::point_triangle_ccd( + p_t0, t0_t0, t1_t0, t2_t0, p_t1, t0_t1, t1_t1, t2_t1, toi); + assert(is_colliding); + assert(abs(toi - 0.5) < 1e-8); + + .. md-tab-item:: Python + + .. code-block:: python + + import numpy as np + import ipctk + + p_t0 = np.array([0.0, -1.0, 0.0]) # point at t=0 + p_t1 = np.array([0.0, 1.0, 0.0]) # point at t=1 + + t0_t0 = np.array([-1.0, 0.0, 1.0]) # triangle vertex 0 at t=0 + t1_t0 = np.array([ 1.0, 0.0, 1.0]) # triangle vertex 1 at t=0 + t2_t0 = np.array([ 0.0, 0.0, -1.0]) # triangle vertex 2 at t=0 + + # static triangle + t0_t1 = t0_t0 # triangle vertex 0 at t=1 + t1_t1 = t1_t0 # triangle vertex 1 at t=1 + t2_t1 = t2_t0 # triangle vertex 2 at t=1 + + # returns a boolean indicating if the point is colliding with the triangle + # and the time of impact (TOI) + is_colliding, toi = ipctk.point_triangle_ccd( + p_t0, t0_t0, t1_t0, t2_t0, p_t1, t0_t1, t1_t1, t2_t1) + assert(is_colliding) + assert(abs(toi - 0.5) < 1e-8) + +Alternatively, the ``FaceVertexCandidate`` class contains a ``ccd`` function that can be used to determine if the face-vertex pairing are colliding: + +.. md-tab-set:: + + .. md-tab-item:: C++ + + .. code-block:: c++ + + ipc::FaceVertexCandidate candidate = ...; // face-vertex candidate + + double toi; // output time of impact + bool is_colliding = candidate.ccd( + vertices_t0, vertices_t1, collision_mesh.edges(), collision_mesh.faces(), toi); + + .. md-tab-item:: Python + + .. code-block:: python + + candidate = ... # face-vertex candidate + + # returns a boolean indicating if the point is colliding with the triangle + # and the time of impact (TOI) + is_colliding, toi = candidate.ccd( + vertices_t0, vertices_t1, collision_mesh.edges, collision_mesh.faces) + +The same can be done for point-edge collisions using the ``point_edge_ccd`` function or ``EdgeVertexCandidate`` class and for edge-edge collisions using the ``edge_edge_ccd`` function or ``EdgeEdgeCandidate`` class. + +.. _minimum-separation-ccd: + +Minimum Separation +^^^^^^^^^^^^^^^^^^ + +We can also perform CCD with a minimum separation distance. This is useful when modeling thickness (see, e.g., :ref:`Modeling Thickness `). + +To do this, we need to set the ``min_distance`` parameter when calling ``is_step_collision_free`` and ``compute_collision_free_stepsize``. For example, we can set the minimum separation distance to :math:`d_\min=10^{-4}`: + +.. md-tab-set:: + + .. md-tab-item:: C++ + + .. code-block:: c++ + + double max_step_size = compute_collision_free_stepsize( + collision_mesh, vertices_t0, vertices_t1, + /*broad_phase_method=*/ipc::DEFAULT_BROAD_PHASE_METHOD, + /*min_distance=*/1e-4); + + Eigen::MatrixXd collision_free_vertices = + (vertices_t1 - vertices_t0) * max_step_size + vertices_t0; + assert(is_step_collision_free( + mesh, vertices_t0, collision_free_vertices, + /*broad_phase_method=*/ipc::DEFAULT_BROAD_PHASE_METHOD, + /*min_distance=*/1e-4 + )); + + .. md-tab-item:: Python + + .. code-block:: python + + max_step_size = compute_collision_free_stepsize( + collision_mesh, vertices_t0, vertices_t1, min_distance=1e-4) + + collision_free_vertices = + (vertices_t1 - vertices_t0) * max_step_size + vertices_t0 + assert(is_step_collision_free( + mesh, vertices_t0, collision_free_vertices, min_distance=1e-4)) \ No newline at end of file diff --git a/docs/source/tutorial/references.rst b/docs/source/tutorial/references.rst new file mode 100644 index 000000000..7a02493ba --- /dev/null +++ b/docs/source/tutorial/references.rst @@ -0,0 +1,4 @@ +References +========== + +.. bibliography:: \ No newline at end of file diff --git a/docs/source/tutorial/simulation.rst b/docs/source/tutorial/simulation.rst index e9732a09a..8ec10653f 100644 --- a/docs/source/tutorial/simulation.rst +++ b/docs/source/tutorial/simulation.rst @@ -41,13 +41,13 @@ From the full (volumetric) mesh vertices and surface edges/faces which index int mesh = meshio.read("bunny.msh") full_rest_positions = mesh.points - tets = mesh.cells[0].data + tets = mesh.cells_dict["tetra"] faces = igl.boundary_facets(tets) # pip install libigl edges = ipctk.edges(faces) # same as igl.edges collision_mesh = ipctk.CollisionMesh.build_from_full_mesh( - rest_positions, edges, faces) + full_rest_positions, edges, faces) This ``CollisionMesh`` can then be used just as any other ``CollisionMesh``. However, when computing the gradient and Hessian of the potentials, the derivatives will be with respect to the surface DOF. If you want the derivatives with respect to the full mesh DOF, then we need to apply the chain rule. Fortunately, the ``CollisionMesh`` class provides a function to do this (``CollisionMesh::to_full_dof``): @@ -77,13 +77,65 @@ This ``CollisionMesh`` can then be used just as any other ``CollisionMesh``. How collision_mesh, vertices, dhat); hess_full = collision_mesh.to_full_dof(hess); -Positive Semi-Definite Projection ---------------------------------- +Nonlinear Bases and Curved Meshes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While IPC cannot directly handle nonlinear finite element bases and/or curved meshes, :cite:t:`Ferguson2023HighOrderIPC` show that displacements and forces can be transfered between a finite element mesh and a collision proxy through the use of a linear map. Given this linear map as a matrix, we can use the ``CollisionMesh`` class to map between the full and surface DOF. + +.. md-tab-set:: + + .. md-tab-item:: C++ + + .. code-block:: c++ + + // Finite element mesh + Eigen::MatrixXd fe_rest_positions; + Eigen::MatrixXi tets; + // TODO: Show how to load a volumetric mesh from a file (e.g., using MshIO) + + // Collision proxy mesh + Eigen::MatrixXd proxy_rest_positions; + Eigen::MatrixXi proxy_edges, proxy_faces; + // Load the proxy mesh from a file + igl::readOBJ("proxy.obj", rest_positions, faces); + igl::edges(faces, edges); + // Or build it from the volumetric mesh + + // Linear map from the finite element mesh to the collision proxy + Eigen::SparseMatrix displacement_map = ...; // build or load the displacement map + + ipc::CollisionMesh collision_mesh( + proxy_rest_positions, proxy_edges, proxy_faces, displacement_map); + + .. md-tab-item:: Python + + .. code-block:: python -As described in [IPC]_ the Hessian of the potentials can be indefinite. This is problematic when using the Hessian in a Newton step [IPC]_. To remedy this, we can project the Hessian onto the positive semidefinite (PSD) cone. To do this set the optional parameter ``project_hessian_to_psd`` of ``compute_potential_hessian`` to true. + # Finite element mesh + fe_mesh = meshio.read("mesh.msh") + fe_rest_positions = mesh.points + tets = mesh.cells_dict["tetra"] ------------- + # Collision proxy mesh + # Load the proxy mesh from a file + proxy_mesh = meshio.read("proxy.msh") + proxy_rest_positions = proxy_mesh.points + proxy_faces = proxy_mesh.cells_dict["triangles"] + proxy_edges = igl.edges(proxy_faces) + # Or build it from the volumetric mesh -.. rubric:: References + # Linear map from the finite element mesh to the collision proxy + displacement_map = ... # build or load the displacement map + + collision_mesh = CollisionMesh( + proxy_rest_positions, proxy_edges, proxy_faces, displacement_map) + +We can then map the displacements using ``collision_mesh.map_displacement(fe_displacements)`` or directly get the displaced proxy mesh vertices using ``collision_mesh.displace_vertices(fe_displacements)``. Similarly, we can map forces/gradients using ``collision_mesh.to_full_dof(contact_forces)`` or force jacobians/potential hessians using ``collision_mesh.to_full_dof(potential_hessian)``. + +.. warning:: + The function ``CollisionMesh::vertices(full_positions)`` should not be used in this case because the rest positions used to construct the ``CollisionMesh`` are not the same as the finite element mesh's rest positions. Instead, use ``CollisionMesh::displace_vertices(fe_displacements)`` where ``fe_displacements`` is already the solution of the PDE or can be computed as ``fe_displacements = fe_positions - fe_rest_positions`` from deformed and rest positions. + +Positive Semi-Definite Projection +--------------------------------- -.. [IPC] Minchen Li, Zachary Ferguson, Teseo Schneider, Timothy Langlois, Denis Zorin, Daniele Panozzo, Chenfanfu Jiang, Danny M. Kaufman. 2020. Incremental Potential Contact: Intersection- and Inversion-free Large Deformation Dynamics. *ACM Transactions on Graphics (SIGGRAPH).* \ No newline at end of file +As described by :cite:t:`Li2020IPC`, the Hessian of the potentials can be indefinite. This is problematic when using the Hessian in a Newton step :cite:p:`Li2020IPC`. To remedy this, we can project the Hessian onto the positive semidefinite (PSD) cone. To do this set the optional parameter ``project_hessian_to_psd`` of ``compute_potential_hessian`` to true. \ No newline at end of file diff --git a/python/src/collisions/collision_constraint.cpp b/python/src/collisions/collision_constraint.cpp index dd409f83c..5155e6dd5 100644 --- a/python/src/collisions/collision_constraint.cpp +++ b/python/src/collisions/collision_constraint.cpp @@ -22,8 +22,7 @@ void define_collision_constraint(py::module_& m) &CollisionConstraint::compute_potential_hessian, "", py::arg("vertices"), py::arg("edges"), py::arg("faces"), py::arg("dhat"), py::arg("project_hessian_to_psd")) - .def_readwrite( - "minimum_distance", &CollisionConstraint::minimum_distance, "") + .def_readwrite("dmin", &CollisionConstraint::dmin, "") .def_readwrite("weight", &CollisionConstraint::weight, "") .def_property( "weight_gradient", diff --git a/src/ipc/candidates/collision_stencil.hpp b/src/ipc/candidates/collision_stencil.hpp index b385c1788..cf10533ef 100644 --- a/src/ipc/candidates/collision_stencil.hpp +++ b/src/ipc/candidates/collision_stencil.hpp @@ -103,21 +103,21 @@ class CollisionStencil { protected: /// @brief Compute the distance of the stencil. - /// @param vertices Stencil's vertex positions. + /// @param positions Stencil's vertex positions. /// @return Distance of the stencil. - virtual double compute_distance(const VectorMax12d& vertices) const = 0; + virtual double compute_distance(const VectorMax12d& positions) const = 0; /// @brief Compute the distance gradient of the stencil w.r.t. the stencil's vertex positions. - /// @param vertices Stencil's vertex positions. + /// @param positions Stencil's vertex positions. /// @return Distance gradient of the stencil w.r.t. the stencil's vertex positions. virtual VectorMax12d - compute_distance_gradient(const VectorMax12d& vertices) const = 0; + compute_distance_gradient(const VectorMax12d& positions) const = 0; /// @brief Compute the distance Hessian of the stencil w.r.t. the stencil's vertex positions. - /// @param vertices Stencil's vertex positions. + /// @param positions Stencil's vertex positions. /// @return Distance Hessian of the stencil w.r.t. the stencil's vertex positions. virtual MatrixMax12d - compute_distance_hessian(const VectorMax12d& vertices) const = 0; + compute_distance_hessian(const VectorMax12d& positions) const = 0; }; } // namespace ipc \ No newline at end of file diff --git a/src/ipc/collisions/collision_constraint.cpp b/src/ipc/collisions/collision_constraint.cpp index 18aacf9ab..18e6b24a7 100644 --- a/src/ipc/collisions/collision_constraint.cpp +++ b/src/ipc/collisions/collision_constraint.cpp @@ -18,11 +18,8 @@ double CollisionConstraint::compute_potential( const double dhat) const { // Squared distance - const double distance = compute_distance(vertices, edges, faces); - return weight - * barrier( - distance - minimum_distance * minimum_distance, - 2 * minimum_distance * dhat + dhat * dhat); + const double d = compute_distance(vertices, edges, faces); + return weight * barrier(d - dmin * dmin, 2 * dmin * dhat + dhat * dhat); } VectorMax12d CollisionConstraint::compute_potential_gradient( @@ -33,13 +30,12 @@ VectorMax12d CollisionConstraint::compute_potential_gradient( { // โˆ‡b(d(x)) = b'(d(x)) * โˆ‡d(x) const VectorMax12d positions = dof(vertices, edges, faces); - const double distance = compute_distance(positions); - const VectorMax12d distance_grad = compute_distance_gradient(positions); + const double d = compute_distance(positions); + const VectorMax12d grad_d = compute_distance_gradient(positions); - const double grad_b = barrier_gradient( - distance - minimum_distance * minimum_distance, - 2 * minimum_distance * dhat + dhat * dhat); - return weight * grad_b * distance_grad; + const double grad_b = + barrier_gradient(d - dmin * dmin, 2 * dmin * dhat + dhat * dhat); + return weight * grad_b * grad_d; } MatrixMax12d CollisionConstraint::compute_potential_hessian( @@ -49,26 +45,24 @@ MatrixMax12d CollisionConstraint::compute_potential_hessian( const double dhat, const bool project_hessian_to_psd) const { - const double adjusted_dhat = 2 * minimum_distance * dhat + dhat * dhat; - const double min_dist_squared = minimum_distance * minimum_distance; + const double adjusted_dhat = 2 * dmin * dhat + dhat * dhat; + const double dmin_sq = dmin * dmin; // โˆ‡ยฒ[b(d(x))] = โˆ‡(b'(d(x)) * โˆ‡d(x)) // = b"(d(x)) * โˆ‡d(x) * โˆ‡d(x)แต€ + b'(d(x)) * โˆ‡ยฒd(x) const VectorMax12d positions = dof(vertices, edges, faces); - const double distance = compute_distance(positions); - const VectorMax12d distance_grad = compute_distance_gradient(positions); - const MatrixMax12d distance_hess = compute_distance_hessian(positions); + const double d = compute_distance(positions); + const VectorMax12d grad_d = compute_distance_gradient(positions); + const MatrixMax12d hess_d = compute_distance_hessian(positions); - const double grad_b = - barrier_gradient(distance - min_dist_squared, adjusted_dhat); - const double hess_b = - barrier_hessian(distance - min_dist_squared, adjusted_dhat); + const double grad_b = barrier_gradient(d - dmin_sq, adjusted_dhat); + const double hess_b = barrier_hessian(d - dmin_sq, adjusted_dhat); // b"(x) โ‰ฅ 0 โŸน b"(x) * โˆ‡d(x) * โˆ‡d(x)แต€ is PSD assert(hess_b >= 0); - MatrixMax12d term1 = hess_b * distance_grad * distance_grad.transpose(); - MatrixMax12d term2 = grad_b * distance_hess; + MatrixMax12d term1 = hess_b * grad_d * grad_d.transpose(); + MatrixMax12d term2 = grad_b * hess_d; if (project_hessian_to_psd) { term2 = project_to_psd(term2); } diff --git a/src/ipc/collisions/collision_constraint.hpp b/src/ipc/collisions/collision_constraint.hpp index 36c2812c7..708ce181c 100644 --- a/src/ipc/collisions/collision_constraint.hpp +++ b/src/ipc/collisions/collision_constraint.hpp @@ -38,7 +38,7 @@ class CollisionConstraint : virtual public CollisionStencil { const double dhat, const bool project_hessian_to_psd) const; - double minimum_distance = 0; + double dmin = 0; double weight = 1; Eigen::SparseVector weight_gradient; }; diff --git a/src/ipc/collisions/collision_constraints.cpp b/src/ipc/collisions/collision_constraints.cpp index fc5dd7fdf..3257c48ba 100644 --- a/src/ipc/collisions/collision_constraints.cpp +++ b/src/ipc/collisions/collision_constraints.cpp @@ -266,7 +266,7 @@ void CollisionConstraints::build( for (size_t ci = 0; ci < size(); ci++) { CollisionConstraint& constraint = (*this)[ci]; - constraint.minimum_distance = dmin; + constraint.dmin = dmin; } if (use_convergent_formulation()) { diff --git a/src/ipc/collisions/plane_vertex.hpp b/src/ipc/collisions/plane_vertex.hpp index 9aa66f88d..1a34e0a9e 100644 --- a/src/ipc/collisions/plane_vertex.hpp +++ b/src/ipc/collisions/plane_vertex.hpp @@ -26,11 +26,20 @@ class PlaneVertexConstraint : public CollisionConstraint { long vertex_id; protected: + /// @brief Compute the distance between the point and plane. + /// @param point Point's position. + /// @return Distance of the stencil. double compute_distance(const VectorMax12d& point) const override; + /// @brief Compute the gradient of the distance w.r.t. the point's positions. + /// @param point Point's position. + /// @return Distance gradient w.r.t. the point's positions. VectorMax12d compute_distance_gradient(const VectorMax12d& point) const override; + /// @brief Compute the distance Hessian of the stencil w.r.t. the stencil's vertex positions. + /// @param point Point's position. + /// @return Distance Hessian w.r.t. the point's positions. MatrixMax12d compute_distance_hessian(const VectorMax12d& point) const override; }; diff --git a/src/ipc/friction/constraints/edge_edge.cpp b/src/ipc/friction/constraints/edge_edge.cpp index 9ccd83b64..d36e356d5 100644 --- a/src/ipc/friction/constraints/edge_edge.cpp +++ b/src/ipc/friction/constraints/edge_edge.cpp @@ -25,8 +25,7 @@ EdgeEdgeFrictionConstraint::EdgeEdgeFrictionConstraint( : EdgeEdgeFrictionConstraint(constraint) { FrictionConstraint::init( - vertices, edges, faces, dhat, barrier_stiffness, - constraint.minimum_distance); + vertices, edges, faces, dhat, barrier_stiffness, constraint.dmin); } // ============================================================================ diff --git a/src/ipc/friction/constraints/edge_vertex.cpp b/src/ipc/friction/constraints/edge_vertex.cpp index 3908f715b..3a2a4632a 100644 --- a/src/ipc/friction/constraints/edge_vertex.cpp +++ b/src/ipc/friction/constraints/edge_vertex.cpp @@ -25,8 +25,7 @@ EdgeVertexFrictionConstraint::EdgeVertexFrictionConstraint( : EdgeVertexFrictionConstraint(constraint) { FrictionConstraint::init( - vertices, edges, faces, dhat, barrier_stiffness, - constraint.minimum_distance); + vertices, edges, faces, dhat, barrier_stiffness, constraint.dmin); } // ============================================================================ diff --git a/src/ipc/friction/constraints/face_vertex.cpp b/src/ipc/friction/constraints/face_vertex.cpp index b2213063f..b79da218c 100644 --- a/src/ipc/friction/constraints/face_vertex.cpp +++ b/src/ipc/friction/constraints/face_vertex.cpp @@ -25,8 +25,7 @@ FaceVertexFrictionConstraint::FaceVertexFrictionConstraint( : FaceVertexFrictionConstraint(constraint) { FrictionConstraint::init( - vertices, edges, faces, dhat, barrier_stiffness, - constraint.minimum_distance); + vertices, edges, faces, dhat, barrier_stiffness, constraint.dmin); } // ============================================================================ diff --git a/src/ipc/friction/constraints/friction_constraint.hpp b/src/ipc/friction/constraints/friction_constraint.hpp index fd3864282..c5315679c 100644 --- a/src/ipc/friction/constraints/friction_constraint.hpp +++ b/src/ipc/friction/constraints/friction_constraint.hpp @@ -183,6 +183,7 @@ class FrictionConstraint : virtual public CollisionStencil { /// @brief Compute the relative velocity of the constraint. /// @param velocities Constraint's vertex velocities. + /// @return Relative velocity of the constraint. virtual VectorMax3d relative_velocity(const VectorMax12d& velocities) const = 0; diff --git a/src/ipc/friction/constraints/vertex_vertex.cpp b/src/ipc/friction/constraints/vertex_vertex.cpp index b8234ca05..632254097 100644 --- a/src/ipc/friction/constraints/vertex_vertex.cpp +++ b/src/ipc/friction/constraints/vertex_vertex.cpp @@ -25,8 +25,7 @@ VertexVertexFrictionConstraint::VertexVertexFrictionConstraint( : VertexVertexFrictionConstraint(constraint) { FrictionConstraint::init( - vertices, edges, faces, dhat, barrier_stiffness, - constraint.minimum_distance); + vertices, edges, faces, dhat, barrier_stiffness, constraint.dmin); } // ============================================================================ diff --git a/src/ipc/friction/constraints/vertex_vertex.hpp b/src/ipc/friction/constraints/vertex_vertex.hpp index 33d69cf9e..42c3ed63c 100644 --- a/src/ipc/friction/constraints/vertex_vertex.hpp +++ b/src/ipc/friction/constraints/vertex_vertex.hpp @@ -34,7 +34,8 @@ class VertexVertexFrictionConstraint : public VertexVertexCandidate, MatrixMax compute_closest_point_jacobian( const VectorMax12d& positions) const override; - VectorMax3d relative_velocity(const VectorMax12d& velocity) const override; + VectorMax3d + relative_velocity(const VectorMax12d& velocities) const override; using FrictionConstraint::relative_velocity_matrix; diff --git a/src/ipc/implicits/plane.cpp b/src/ipc/implicits/plane.cpp index c7a349e76..080ea338c 100644 --- a/src/ipc/implicits/plane.cpp +++ b/src/ipc/implicits/plane.cpp @@ -43,7 +43,7 @@ void construct_point_plane_constraint_set( if (distance_sqr - dmin_squared < 2 * dmin * dhat + dhat_squared) { pv_constraints.emplace_back(plane_origin, plane_normal, vi); - pv_constraints.back().minimum_distance = dmin; + pv_constraints.back().dmin = dmin; } } }