{"id":29799859,"url":"https://github.com/mysterypancake/houdini-vbd","last_synced_at":"2025-07-28T08:47:25.378Z","repository":{"id":300905550,"uuid":"1007534973","full_name":"MysteryPancake/Houdini-VBD","owner":"MysteryPancake","description":"Vertex Block Descent for Houdini","archived":false,"fork":false,"pushed_at":"2025-07-24T17:18:55.000Z","size":13228,"stargazers_count":35,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-24T22:15:07.945Z","etag":null,"topics":["avbd","cgi","houdini","opencl","vbd","vex","vfx"],"latest_commit_sha":null,"homepage":"https://youtu.be/I8SaqJsK3TI","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/MysteryPancake.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,"zenodo":null}},"created_at":"2025-06-24T06:37:24.000Z","updated_at":"2025-07-24T17:18:59.000Z","dependencies_parsed_at":"2025-07-09T13:25:52.822Z","dependency_job_id":"5a889f4a-70d7-4c25-9748-acae0abdbcf4","html_url":"https://github.com/MysteryPancake/Houdini-VBD","commit_stats":null,"previous_names":["mysterypancake/houdini-vbd"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/MysteryPancake/Houdini-VBD","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FHoudini-VBD","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FHoudini-VBD/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FHoudini-VBD/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FHoudini-VBD/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MysteryPancake","download_url":"https://codeload.github.com/MysteryPancake/Houdini-VBD/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MysteryPancake%2FHoudini-VBD/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267488491,"owners_count":24095783,"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","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["avbd","cgi","houdini","opencl","vbd","vex","vfx"],"created_at":"2025-07-28T08:47:20.800Z","updated_at":"2025-07-28T08:47:25.359Z","avatar_url":"https://github.com/MysteryPancake.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Houdini Vertex Block Descent\n\n| \u003cimg src=\"./images/demo.webp\"\u003e | \u003cimg src=\"./images/demo2.webp\"\u003e |\n| --- | --- |\n| \u003cimg src=\"./images/massspring.png\"\u003e | \u003cimg src=\"./images/neohookean.png\"\u003e |\n\n\nWIP of Vertex Block Descent (VBD) in Houdini. It runs natively without plugins, as god intended.\n\nThere's an OpenCL version for performance, and an old VEX version to show how it works. Both are included in the HIP files.\n\nI ported everything from [TinyVBD](https://github.com/AnkaChan/TinyVBD), some bits from [AVBD](https://github.com/savant117/avbd-demo2d), [Gaia](https://github.com/AnkaChan/Gaia) and some ideas from the papers.\n\nThanks to Anka He Chen and Chris Giles for making these open source with permissive licenses!\n\n| [Download the HIP file!](../../releases/latest) |\n| --- |\n\n## Todo\n- [x] Steal from [TinyVBD](https://github.com/AnkaChan/TinyVBD)\n  - [x] [Mass-spring energy definition](https://github.com/AnkaChan/TinyVBD/blob/main/main.cpp#L381) (for strings)\n  - [x] [Accelerated convergence method (section 3.8)](https://graphics.cs.utah.edu/research/projects/vbd/vbd-siggraph2024.pdf)\n- [ ] Steal from [NVIDIA Warp](https://github.com/NVIDIA/warp)\n  - [ ] [StVK energy definition](https://github.com/NVIDIA/warp/blob/main/warp/sim/integrator_vbd.py) (for cloth)\n- [ ] Steal from [Gaia](https://github.com/AnkaChan/Gaia)\n  - [x] [Neo-hookean energy definition](https://github.com/AnkaChan/Gaia/blob/main/Simulator/Modules/VBD/VBD_NeoHookean.cpp) (for tetrahedrons)\n  - [x] Damping\n  - [x] Boundary collisions\n  - [ ] Self collisions\n  - [ ] External collisions\n  - [x] Friction\n- [ ] Steal from [AVBD](https://graphics.cs.utah.edu/research/projects/avbd/)\n  - [x] [LDLT decomposition](https://graphics.cs.utah.edu/research/projects/avbd/Augmented_VBD-SIGGRAPH25.pdf) to improve speed\n  - [x] [SPD hessian approximation (section 3.5)](https://graphics.cs.utah.edu/research/projects/avbd/Augmented_VBD-SIGGRAPH25.pdf) to improve stability\n  - [ ] [Hard constraints](https://graphics.cs.utah.edu/research/projects/avbd/Augmented_VBD-SIGGRAPH25.pdf)\n- [ ] Touch grass\n\n## What's Vertex Block Descent?\n\nVBD is very similar to Vellum. You might call it Vellum 2.\n\nVellum uses a technique called [XPBD (Extended Position-Based Dynamics)](https://matthias-research.github.io/pages/publications/XPBD.pdf). XPBD uses constraints to simulate soft body behaviour. Constraints are solved in parallel workgroups (colors) in OpenCL for better performance. Colors are groups of constraints that aren't directly connected.\n\nCloth is a good example of a soft body. It's easy to bend but hard to stretch. In XPBD this is simulated with distance constraints. Distance constraints try to preserve their rest length. When you stretch or squash a distance constraint, it pulls the points towards the middle until they reach their rest length again. Since shortening one constraint makes others longer, it's an iterative process. It propagates over several iterations until everything converges to the target length.\n\n\u003cimg src=\"./images/edging.png\" width=\"700\"\u003e\n\nVBD constraints are similar, but they're defined in terms of energy instead. The goal is reducing overall variational energy by reducing local energy per point. VBD constraints run over each point rather than each primitive, meaning less workgroups (colors) overall. However, each point typically has to loop over its neighbours to compute the energy, so the performance isn't necessarily better. The Graph Color node allows workgroups for points as well as prims, so it works both for VBD and XPBD.\n\n\u003cimg src=\"./images/energyreduction.png\" width=\"700\"\u003e\n\nThe diagram above is for mass-spring energy, based on the rest length of each edge. In this case it's not so different to XPBD, but the idea of minimizing energy is different to minimizing distance.\n\nHere's a quick comparison between VBD and XPBD:\n\n|  | VBD | Vellum (XPBD) | Advantage | Disadvantage |\n| --- | --- | --- | --- | --- |\n| **Runs over** | \u003cp align=\"center\"\u003ePoint colors\u003cbr\u003e\u003cimg src=\"./images/color_points.png\"\u003e\u003c/p\u003e | \u003cp align=\"center\"\u003eColors per constraint\u003cbr\u003e\u003cimg src=\"./images/color_prims.png\"\u003e\u003c/p\u003e | Less colors/workgroups, faster for parallel processing | Takes longer to converge for stiff objects, partly because it updates 1 point per iteration instead of 2 (one on each side of the constraint). Not necessarily faster, since each point typically loops over its neighbours |\n| **Constraints** | Energy based (eg mass-spring energy or neo-hookean energy) | XPBD based (eg distance constraints) | Better for larger mass ratios | Randomly explodes due to hessian matrix inversion |\n| **Iterations** | Gauss-Seidel | Gauss-Seidel (for constraint iterations) and Jacobi (for smoothing iterations) | Reaches a global solution faster | Might be less stable |\n\nThe most important part of VBD is the energy definition, but no one seems to agree on this.\n\nI've seen many different energy definitions, including mass-spring (used by [TinyVBD](https://github.com/AnkaChan/Gaia/blob/main/Simulator/Modules/VBD/VBD_MassSpring.cpp) and [AVBD](https://github.com/savant117/avbd-demo2d/blob/main/source/spring.cpp#L40), but [removed from Gaia](https://github.com/AnkaChan/Gaia/blob/main/Simulator/Modules/VBD/VBD_MassSpring.cpp)), StVK (used by [NVIDIA Warp](https://github.com/AnkaChan/Gaia/blob/main/Simulator/Modules/VBD/VBD_MassSpring.cpp)) and neo-hookean (used by [Gaia](https://github.com/AnkaChan/Gaia/blob/main/Simulator/Modules/VBD/VBD_NeoHookean.cpp)).\n\nCurrently mass-spring and neo-hookean are supported, StVK is coming soon.\n\n## How does Vertex Block Descent run?\n\nIgnoring collisions, VBD is really just 3 steps. These steps are nearly identical to XPBD apart from the constraints.\n\n### 1. Integrate the positions\n\nAdd the velocity to the position (same as Vellum). VBD uses a warmstarting strategy to scale the gravity term below.\n\n```c\n// First-order integration\nv@pprevious = v@P;\nv@P += v@v * f@TimeInc * v@gravity * f@TimeInc * f@TimeInc;\n```\n\n| [OpenCL version](./ocl/forwardStep.cl) | [VEX version (outdated)](./vex/forwardStep.c) |\n| --- | --- |\n\n### 2. Apply the constraints\n\nThe core idea of VBD is updating the position based on force elements and a hessian matrix.\n\nIf these are correct, moving the position should reduce the overall variational energy.\n\n\u003e [!CAUTION]\n\u003e **This should be run in workgroups based on graph coloring!**\n\u003e\n\u003e If points move while their neighbours access them (like if running in sequential order), it breaks the assumption used by VBD:\n\u003e \n\u003e  \u003e We adjust each vertex separately, assuming the others remain fixed\n\u003e \n\u003e This causes growing error each iteration, leading VBD to explode much more than usual.\n\n```c\nvector force = 0;\nmatrix3 hessian = 0;\n\n// Add influences to force elements and hessian\naccumulateInertiaForceAndHessian(force, hessian); // Influences due to mass and inertia\naccumulateMaterialForceAndHessian(force, hessian); // Influences due to constraints (eg mass-spring or neo-hookean)\naccumulateDampingForceAndHessian(force, hessian); // Influences due to damping\naccumulateBoundaryForceAndHessian(force, hessian); // Influences due to boundaries (eg floor planes)\naccumulateCollisionForceAndHessian(force, hessian); // Influences due to collisions\n\nv@P += force * invert(hessian); // Reduce the variational energy of the system\n```\n\n| [OpenCL version](./ocl/solveConstraints.cl) | [VEX version (outdated)](./vex/solveConstraints.c) |\n| --- | --- |\n\n### 3. Update the velocities\n\nUpdate the velocities based on the change in position (same as Vellum).\n\n```c\n// First-order velocities\nv@v = (v@P - v@pprevious) / f@TimeInc;\n```\n\n| [OpenCL version](./ocl/updateVelocity.cl) | [VEX version (outdated)](./vex/updateVelocity.c) |\n| --- | --- |\n\n## Why does stiffness have a limit?\n\nLike with Vellum (XPBD), stiff objects are limited by the number of constraint iterations and substeps.\n\nThe more constraint iterations and substeps, the more accurately stiff objects are resolved.\n\nVBD also has accelerated convergence method meant to improve convergence for stiff constraints.\n\nIt's named \"Improve Convergence\" in the Advanced tab and disabled by default, as it tends to explode with high values.\n\nAVBD adds hard constraints which should resolve much faster, but I haven't implemented this yet.\n\n## Why do collisions not work sometimes?\n\nVBD solves collisions as soft constraints, meaning collisions get added onto the force and hessian like everything else.\n\nIn practice this means other forces can overpower collisions. For example, stiffer materials than the ground can penetrate it.\n\nThis can be fixed by increasing the stiffness of the ground, or reducing the stiffness of everything else.\n\nAVBD adds hard constraints which should prevent this from happening, but I haven't implemented this yet.\n\n## Why does it explode randomly?\n\nThis solver used to explode every 5 seconds, but now it's much better. Explosions are a common issue with VBD.\n\nAs mentioned, VBD involves updating the position based on force elements and a hessian matrix:\n\n```c\nv@P += force * invert(hessian); // force and hessian depend on the energy definition, eg mass-spring or neo-hookean\n```\n\n`invert(hessian)` is very unstable, so everyone tries to bandaid it in various ways. The [VBD paper](https://graphics.cs.utah.edu/research/projects/vbd/vbd-siggraph2024.pdf) uses the determinant of the matrix:\n\n```c\nif (abs(determinant(hessian)) \u003e 1e-7) { // if |det(H𝑖)| \u003e 𝜖 for some small threshold 𝜖\n  v@P += force * invert(hessian);\n}\n```\n\nThis helps, but it also explodes when the values gets too large (for example with very stiff constraints).\n\nThe new [AVBD paper](https://graphics.cs.utah.edu/research/projects/avbd/Augmented_VBD-SIGGRAPH25.pdf) uses an approximation to make the hessian positive semi-definite. This massively improves the stability and is enabled by default. It's named \"Improve Hessian Stability\" in the Advanced tab.\n\n## AVBD Q\u0026A\n\nThere's a new paper called [Augmented Vertex Block Descent (AVBD)](https://graphics.cs.utah.edu/research/projects/avbd/Augmented_VBD-SIGGRAPH25.pdf). It adds many improvements to VBD.\n\nI asked the authors about some differences I noticed. They responded with lots of useful information. Thanks guys!\n\n### Missing accelerated convergence\n\nHi Chris, In the original VBD paper and in TinyVBD, they used an acceleration method to improve convergence (Section 3.8). I noticed in AVBD there's no mention of this method. Was it causing too much instability? Thanks!\n\n\u003e Hi,\n\u003e Yeah we ended up not using the acceleration from VBD as it was in general kind of unstable and difficult to tune, even with the original VBD method. It would be interesting to explore other acceleration methods as future work though.\n\u003e -Chris\n\n\u003e No, we haven't looked into acceleration for AVBD.\n\u003e -Cem\n\n### Energy definition used\n\nHi Chris, I was wondering what type energy you used for constraints? There were multiple used in the VBD paper, including mass-spring, StVK and neo-hookean. It looks like you used mass-spring energy. Is this correct, or did you use neo-hookean? Thanks!\n\n\u003e Hello,\n\u003e So you are correct, in our demos we only used a simple spring energy for the deformable examples, as we weren't focused on rehashing what the original VBD paper showed. However, in AVBD, you can use any energy that works in VBD, such as the ones you mentioned. This is because AVBD is purely an extension of VBD. The only thing to keep in mind with those more complex energy types, is that you need to be careful about how you solve each block since their hessians can be indefinite. In general, you can follow the same pattern that AVBD uses for constraint energies. That is, decompose the hessian into an SPD part and a non-SPD part, then use the diagonal lumped approximation proposed in the paper for the non-SPD part.\n\u003e Hope that helps!\n\u003e -Chris\n\n\u003e No. The AVBD tests we have are for contacts and joints. VBD already covers soft bodies. AVBD makes no changes to that.\n\u003e -Cem\n\n### [Previous velocity definition](https://github.com/savant117/avbd-demo2d/issues/4)\n\n\u003e [!NOTE]\n\u003e I noticed this while looking into Vellum. Vellum uses 4 variables to track the previous 2 values of position and velocity:\n\u003e\n\u003e - `@pprevious` (`@P` 1 substep ago)\n\u003e - `@plast` (`@P` 2 substeps ago)\n\u003e - `@vprevious` (`@v` 1 substep ago)\n\u003e - `@vlast` (`@v` 2 substeps ago)\n\u003e\n\u003e Vellum sets all of these at the start of each substep. They're needed for 1st and 2nd order integration.\n\u003e\n\u003e However, TinyVBD and AVBD set `@vprevious` in a different place. I thought this was a typo, but turns out it's not.\n\nHi Chris, I was wondering if the order of these 2 lines is correct?\n\n```cpp\nbody-\u003eprevVelocity = body-\u003evelocity; \nif (body-\u003emass \u003e 0) \n   body-\u003evelocity = (body-\u003eposition - body-\u003einitial) / dt;\n```\n\nIt seems like the previous velocity should be set after it gets recalculated, instead of before.\n\nI saw the [same code in TinyVBD](https://github.com/AnkaChan/TinyVBD/blob/main/main.cpp#L349-L350), but I believe it is a mistake. The [opposite code is present in GAIA](https://github.com/AnkaChan/Gaia/blob/main/Simulator/Modules/VBD/VBD_BaseMaterial.h#L256).\n\n\u003e The current code is correct (and probably in TinyVBD as well), since we use prevVelocity to compute an acceleration estimate during the adaptive warmstarting at the beginning of the step:\n\u003e\n\u003e `float3 accel = (body-\u003evelocity - body-\u003eprevVelocity) / dt;`\n\u003e\n\u003e If we switched the order as suggested, then this acceleration would always be zero, and the adaptive warmstart would not help.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmysterypancake%2Fhoudini-vbd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmysterypancake%2Fhoudini-vbd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmysterypancake%2Fhoudini-vbd/lists"}