The code can be directly run without any arguments.
To change the loaded mesh, change the file path in ARAP::init
function. Other minor changes such as enabling or disabling parallelization are directlyt marked in code.
One Anchor
Anchoring exactly one point, then moving that point, results in perfectly rigid motion (mostly translation, though some rotation for smaller meshes is acceptable).
one_point.mov
Two Anchors
Anchoring exactly two points, then rotating one point around the other at a fixed distance, results in perfectly rigid rotation.
two_point.mov
Permanant Deformation
Deformations are "permanent"; i.e. un-anchoring previously moved points leaves the mesh in its deformed state, and further deformations can be made on the deformed mesh.
permanent.mov
Armadillo
You should be able to make the armadillo wave.
armadillo.mov
Single Tetradedron
Attempting to deform tetrahedron.obj should not cause it to collapse or behave erratically.
tetrahedron.mov
Large Mesh
Attempting to deform a (large) mesh like bunny.obj or peter.obj should not cause your code to crash.
peter.mov
Build L Matrix: The L matrix is built by assigning corresponding edge weights into positions where i != j and assigning the diagonal positions by summing up the weights around each vertex.
L is computed and pre-factored once during the initialisation.
Build RHS: The RHS is built by summing up the surrounding weights timed by R and movements of each vertex.
RHS is being updated during iterative solving.
Apply Constraints:
- For L matrix:
Detailed implementation can be found in
void ARAP::assembleL(const std::unordered_set<int>& anchors)
- The diagonal position (i = j) on the corresponding row is set to 1.
- All other positions on the corresponding row is set to 0.
- For RHS:
Detailed implementation can be found in
void ARAP::assenbleRHS(const std::unordered_set<int>& anchors)
- The corresponding row is set to the exact known (fixed) positions.
- Other rows (j != i) are added by the weights times the corresponding vertices positions.
Iterative Solving:
- I use
Eigen::SimplicialLDLT
to solve the linear system. - The default number of iterations per simulation step is
10
. - Both directly solving RHS of size n by 3 and separatly solving RHS for each axis (parallel) are implemented.
The linear system is solved by separatly solving RHS for each axis (parallel). I tried both the Openmp and QtConcurrent for parallelization. There are minor improvements when using peter.obj
in testing.
-
No Parallelization
no_parallel.mov
-
OpenMP
openmp.mov
-
QtConcurrent
qtconcurrent.mov
I clarify that there is no collaboration include when I do this project.
References for mathematical formulas are coming from the original paper.
The main bug is the non-obvious efficiency improvement in Parallelize your code part. The main reason could be that the overhead introduced by managing threads is large.