{"id":21466134,"url":"https://github.com/javidcf/surfmorph","last_synced_at":"2025-03-17T05:46:21.042Z","repository":{"id":79386743,"uuid":"57322443","full_name":"javidcf/surfmorph","owner":"javidcf","description":"Mesh pose interpolation in C++11 with Eigen","archived":false,"fork":false,"pushed_at":"2016-05-05T11:34:17.000Z","size":1032,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-23T15:24:06.199Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/javidcf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-04-28T17:47:58.000Z","updated_at":"2023-03-06T18:59:12.000Z","dependencies_parsed_at":"2023-06-03T23:00:21.346Z","dependency_job_id":null,"html_url":"https://github.com/javidcf/surfmorph","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javidcf%2Fsurfmorph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javidcf%2Fsurfmorph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javidcf%2Fsurfmorph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javidcf%2Fsurfmorph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/javidcf","download_url":"https://codeload.github.com/javidcf/surfmorph/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243982136,"owners_count":20378606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-23T08:13:26.647Z","updated_at":"2025-03-17T05:46:21.037Z","avatar_url":"https://github.com/javidcf.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# surfmorph\nMesh pose interpolation in C++11 with [Eigen](http://eigen.tuxfamily.org).\n\n![Animation demonstration](app/demo.gif)\n\nThis is an implementation of\n[as-rigid-as-possible surface morphing](http://link.springer.com/article/10.1007/s11390-011-1154-3)\nfor 3D meshes. It is designed as a header-only library and it only depends on\n[Eigen](http://eigen.tuxfamily.org). Some bits are parallelized with\n[OpenMP](http://openmp.org), although that can be disabled at compile time.\n\n## What does it do?\n\nIt allows you to create an animation for a 3D mesh based on a sequence of two or\nmore key poses. Intermediate poses can be interpolated with arbitrary precision\nto generate animation frames, and the result shows an animation that is \"as\nrigid as possible\" in the sense that in minimizes the deformation of the\ntriangles along the way.\n\nIn order to keep dependencies at minimum, the library uses exclusively Eigen\nmatrices for its operation, and it does not implement or uses any mesh structure\nas such. However, integrating it with any mesh processing library should be\nrather straightforward. Check the [app](app) directory to see an example that\nintegrates [OpenMesh](http://www.openmesh.org).\n\n## How do I use it?\n\nThe library is quite simple and should be fairly easy to use. To install it,\njust copy the content of the [include](include) directory to your project or\nyour system include path. Then, include the file `surfmorph/surfmorph.h` in your\nsource.\n\nThe library contains just one template class, `surfmorph::SurfaceMorph`, which\nreceives the preferred scalar type as template parameter (generally `float` or\n`double`). The [source code](surfmorph/surfmorph.h) is quite commented and\ndescribes the available operations in the class. The code below is a simple\nexample program demonstrating its usage.\n\n```C++\n//! Generate some triangles data and interpolate it along time.\n\n#include \u003cEigen/Core\u003e\n#include \u003csurfmorph/surfmorph.h\u003e\n\n#include \u003ciostream\u003e\n#include \u003ciomanip\u003e\n#include \u003cvector\u003e\n\nint main()\n{\n    // Define mesh matrices types\n    typedef Eigen::Matrix\u003cunsigned int, 3, Eigen::Dynamic\u003e TrianglesMat;\n    typedef Eigen::Matrix\u003cdouble, 3, Eigen::Dynamic\u003e CoordsMat;\n    // Define interpolator type\n    typedef surfmorph::SurfaceMorph\u003cdouble\u003e SurfaceMorph;\n\n    // Generate some data\n    TrianglesMat triangles(3, 2);\n    CoordsMat pose0(3, 4);\n    CoordsMat pose1(3, 4);\n    CoordsMat pose2(3, 4);\n    // Each triangle is a vector of vertex indices\n    triangles \u003c\u003c 0, 1,\n                 1, 2,\n                 2, 3;\n    // Each pose has the coordinates of every vertex as column vectors\n    pose0 \u003c\u003c 0.0, 1.0, 1.0, 0.0,\n             0.0, 1.0, 0.0, 1.0,\n             0.0, 1.0, 1.0, 1.0;\n    pose1 \u003c\u003c 0.3, 1.5, 1.7, 0.2,\n             0.1, 1.2, 0.2, 1.8,\n             0.2, 1.3, 1.4, 1.5;\n    pose2 \u003c\u003c 0.1, 1.2, 1.4, 0.5,\n             0.8, 1.3, 0.4, 1.8,\n             0.5, 1.9, 1.6, 1.3;\n\n    // Create the interpolator\n    SurfaceMorph sm(triangles, pose0);\n    sm.addPose(pose1);\n    sm.addPose(pose2);\n\n    // Print the triangles matrix\n    std::cout \u003c\u003c \"Triangles:\" \u003c\u003c std::endl;\n    for (int i = 0; i \u003c triangles.rows(); i++) {\n        for (int j = 0; j \u003c triangles.cols(); j++) {\n            std::cout \u003c\u003c triangles(i, j) \u003c\u003c \" \";\n        }\n        std::cout \u003c\u003c std::endl;\n    }\n    std::cout \u003c\u003c std::endl;\n\n    // Each pose is assigned a sequential integer time point; time point 0\n    // is the first pose, time point 1 the second one, and time point 1.5\n    // is an interpolation midway between the first and the second pose.\n    std::cout \u003c\u003c std::setprecision(2);\n    for (double t = 0.0; t \u003c= double(sm.numPoses() - 1); t += .1) {\n        // Compute interpolated pose at time point\n        CoordsMat interp = sm.interpolatePoseAt(t);\n        // Print the pose coordinates\n        std::cout \u003c\u003c \"Interpolated pose at \" \u003c\u003c t \u003c\u003c \":\" \u003c\u003c std::endl;\n        for (int i = 0; i \u003c interp.rows(); i++) {\n            for (int j = 0; j \u003c interp.cols(); j++) {\n                std::cout \u003c\u003c interp(i, j) \u003c\u003c \" \";\n            }\n            std::cout \u003c\u003c std::endl;\n        }\n        std::cout \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nTo compile this program with [GCC](https://gcc.gnu.org) on Unix, save it to a\nfile, say `surfmorph_test.cpp`, and run:\n\n```Shell\n$ gcc -std=gnu++11 -I\u003cpath to Eigen library\u003e -I\u003cpath to this library\u003e -fopenmp -o surfmorph_test surfmorph_test.cpp\n```\n\nOr, if you prefer not to use [OpenMP](http://openmp.org) (more on this\n[later](#multithreading)), then run:\n\n```Shell\n$ gcc -std=gnu++11 -I\u003cpath to Eigen library\u003e -I\u003cpath to this library\u003e -DSURFMORPH_DONT_PARALLELIZE -o surfmorph_test surfmorph_test.cpp\n```\n\nAnd then test it with:\n\n```Shell\n$ ./surfmorph_test.cpp\n```\n\n## Is there some other more interesting example?\n\nThe [app](app) directory contains an application that displays an interactive\nanimation interpolated along the given poses. Besides this library and\n[Eigen](http://eigen.tuxfamily.org), it requires\n[OpenMesh](http://www.openmesh.org), [Qt 5](https://www.qt.io) and\n[libQGLViewer](http://libqglviewer.com). Also, the compilation system has only\nbeen configure for Linux, although it should be straightforward to port to other\nplatforms.\n\n## Multithreading\n\nBy default, the library uses [OpenMP](http://openmp.org) to parallelize some of\nits operations. However, you can disable this by defining the macro\n`SURFMORPH_DONT_PARALLELIZE` at compile time.\n\nPose interpolation, which is the most expensive operation, is not parallelized\nby default; the reason is that, in general, interpolations are computed for a\nsequence of time points, and it is more efficient to parallelize at time-point\nlevel (that is, compute multiple interpolations in parallel). Nonetheless, it is\npossible to parallelize the interpolation operation by defining the macro\n`SURFMORPH_PARALLELIZE_INTERPOLATION` at compile time. Note that this is\ngenerally not recommended unless only a single interpolation is computed.\n\n## What are [Shape interpolation.ipynb](Shape%20interpolation.ipynb) and [surfmorph_codegen.h](include/surfmorph/surfmorph_codegen.h)?\n\nThe implementation of the algorithm requires some complex math derivation that\nis not practical to solve by hand.\n[Shape interpolation.ipynb](Shape%20interpolation.ipynb) is a Python notebook that\nuses [SymPy](http://www.sympy.org) to compute this derivation and generate the\ncode that implements it in\n[surfmorph_codegen.h](include/surfmorph/surfmorph_codegen.h).\n[Shape interpolation.ipynb](Shape%20interpolation.ipynb) is not necessary to use\nthe library, but [surfmorph_codegen.h](include/surfmorph/surfmorph_codegen.h)\nis, although you should not include it directly in your source code.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjavidcf%2Fsurfmorph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjavidcf%2Fsurfmorph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjavidcf%2Fsurfmorph/lists"}