<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Dimforge Blog</title>
        <link>https://dimforge.com/blog</link>
        <description>Dimforge Blog</description>
        <lastBuildDate>Fri, 25 Sep 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>Copyright © 2026 Dimforge, EURL.</copyright>
        <item>
            <title><![CDATA[Advanced soft-bodies for games with the Rapier physics engine]]></title>
            <link>https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine</link>
            <guid>https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine</guid>
            <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[In Rapier v0.36.0, we added extensive support for soft-body simulations.]]></description>
            <content:encoded><![CDATA[<p>In Rapier v0.36.0, we added extensive support for soft-body simulations.
Surprisingly, we didn’t find a lot of documentation and precedent from existing game physics engines on that topic. So
we would like to share the techniques we implemented in Rapier as we believe it results in a uniquely powerful
feature set. Hopefully, this will help game developers create more exciting gameplay leveraging deformable physics, and
inspire other physics engine developers to further research and improve the support of soft-body physics within the
industry.</p>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-1" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-1.mp4" width="250" title="Pressurized blobs (2D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Pressurized blobs (2D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-2" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-2.mp4" width="250" title="Pile of ropes (2D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Pile of ropes (2D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-3" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-3.mp4" width="250" title="Soft bar under a pile (2D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Soft bar under a pile (2D)</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-4" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-4.mp4" width="250" title="Soft letters (2D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Soft letters (2D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-5" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-5.mp4" width="250" title="Tearing (2D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Tearing (2D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-joints" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-joints.mp4" width="250" title="Impulse joints (2D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Impulse joints (2D)</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-6" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-6.mp4" width="250" title="Pile of ropes (3D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Pile of ropes (3D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-7" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-7.mp4" width="250" title="Tearing (3D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Tearing (3D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-8" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-8.mp4" width="250" title="Skinned meshes and sensor (3D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Skinned meshes and sensor (3D)</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-9" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-9.mp4" width="250" title="Thin objects (3D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Thin objects (3D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-10" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-10.mp4" width="250" title="Cloths (3D)" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Cloths (3D)</div></div><div style="padding:4px;text-align:center;width:258px"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#lightbox-soft-plasticity" style="cursor:pointer;display:block"><video src="/img/blog/2026-09-25/demo-plasticity.mp4" width="250" title="Plastic car chassis (3D)**" autoplay="" loop="" muted="" playsinline="" style="display:block"></video></a><div style="margin-top:4px;margin-bottom:12px">Plastic car chassis (3D)**</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="lightbox-soft-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-1.mp4" title="Pressurized blobs (2D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-2.mp4" title="Pile of ropes (2D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-3" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-3.mp4" title="Soft bar under a pile (2D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-4" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-4.mp4" title="Soft letters (2D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-5" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-5.mp4" title="Tearing (2D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-joints" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-joints.mp4" title="Impulse joints (2D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-6" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-6.mp4" title="Pile of ropes (3D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-7" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-7.mp4" title="Tearing (3D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-8" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-8.mp4" title="Skinned meshes and sensor (3D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-9" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-9.mp4" title="Thin objects (3D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-10" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-10.mp4" title="Cloths (3D)" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-soft-plasticity" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><video src="/img/blog/2026-09-25/demo-plasticity.mp4" title="Plastic car chassis (3D)**" controls="" loop="" muted="" playsinline="" preload="metadata" style="max-width:90%;max-height:90%;position:relative;z-index:1"></video><a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<p><em>🤖 AI disclaimer: the text of this entire blog-post is hand-written. Only the schematics were created with AI assistance.</em></p>
<p><strong>Rapier</strong> is a Free and Open Source physics engine for games, animation, robotics, written with the Rust programming language.
For years, we focused on rigid-body physics only: objects that cannot deform in any way. Due to
popular requests from the community, we finally integrated deformable bodies: cloth, jelly, ropes, etc.
Rapier’s implementation of deformable objects is very versatile, and interacts with all the other engine
features with little to no restrictions. For example, you can:</p>
<ul>
<li><strong>Attach any type of <code>ImpulseJoint</code></strong> (revolute, prismatic, fixed, generic 6-dofs, etc.) to soft-bodies. Meaning
that you can attach two soft-bodies by joints, one soft-body and one rigid-body, as well as attach
a soft-body to a multibody. It all works seamlessly and with the same API as you are used to.</li>
<li>Attach <strong>deformable and non-deformable colliders</strong> to soft-bodies. Sensor colliders can be deformable too.</li>
<li><strong>Skinning</strong>: use a deformation lattice that is different (often lower-resolution) from the collision-detection or
visual mesh while having the collision/visual mesh follow the deformations.</li>
<li><strong>Control</strong> parts of the soft-body kinematically.</li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_v1XZ alert alert--success"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_nS2X"><p>Our soft-bodies implementation works on the web too! You can play with them on our <a href="https://rapier.rs/demos#2d" target="_blank" rel="noopener noreferrer">online demos</a>.
Soft-body demos can be selected from the demo list:</p><center><p><img decoding="async" loading="lazy" alt="Shape-matching steps" src="https://dimforge.com/assets/images/online-demos-772c8975752ddca885677bd125f1df7d.png" width="2306" height="1286" class="img_XsDP"></p></center></div></div>
<p>In this article, we won’t dive into API details (refer to the <a href="https://rapier.rs/docs/user_guides/rust/soft_bodies" target="_blank" rel="noopener noreferrer">user-guide</a> for that).
We will focus on the core modeling choices, challenges we faced, and literature we recommend looking at if you are interested in
implementing your own soft-bodies system. Our technological choices were guided by the following priorities:</p>
<ol>
<li><strong>Ergonomics:</strong> the API should integrate nicely with what we already have.</li>
<li><strong>Stability:</strong> the simulation should, as much as possible, never break down. Meaning that it should not suddenly explode,
or start making objects fly away uncontrollably. This is actually surprisingly difficult to achieve with deformable physics.</li>
<li><strong>Control:</strong> games need control over the objects they are working with to fit gameplay that does not necessarily agree
with real-life physics.</li>
<li><strong>Performance:</strong> the simulation should be fast, not perfect. Some very advanced algorithms and solvers can eliminate whole
classes of difficulties we will discuss (e.g. penetrations of deformable meshes), but are too computationally
expensive to be actually usable in games.</li>
</ol>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>This is the first time soft-bodies are released in <strong>Rapier</strong>. So, we wouldn’t be surprised if you encounter
edge-cases we haven’t thought of. Feel free to share your experience on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">Discord</a> and to open issues on
the <a href="https://github.com/dimforge/rapier" target="_blank" rel="noopener noreferrer">Rapier repository</a>.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="definition-of-a-soft-body">Definition of a soft-body<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#definition-of-a-soft-body" class="hash-link" aria-label="Direct link to Definition of a soft-body" title="Direct link to Definition of a soft-body">​</a></h2>
<p>Let’s start with the definition of a <em>rigid-body</em>: it is a moving point in space (x,y,z) and an orientation
(rotation matrix/quaternion), totaling 6 Degrees Of Freedom (DOFs) in 3D and only 3 DOFs in 2D. No matter how complex a
rigid-body shape (its colliders) is, from the dynamics perspective it can entirely be represented as a single oriented
point in space. In other words, a rigid-body is a moving coordinate frame: the location and movement of any
point of the rigid-body can be expressed implicitly from the location and movement of that frame. This is what makes it
so cheap and easy to implement and control.</p>
<p>A <em>soft-body</em> is more complex because a single moving frame isn’t enough: deformations require parts of the
body to be capable of moving (somewhat) independently of the other parts. Instead, a soft-body is made of several <em>mass points</em>
(aka. <em>particles</em>) where each mass point is a point (x,y,z) in space without any orientation. Each particle has 3 DOFs in 3D
(or 2 DOFs in 2D), so the more particles a soft-body is made of, the more degrees of freedom it has, the more
detailed and smooth the deformations can be.</p>
<p>A soft-body also needs a way of keeping these particles together to form a single cohesive object. In Rapier, you can
define a lattice made of points (the mass points), edges (connecting two points), and cells (connecting 3 or 4 points).
The only mandatory elements are the mass points; the rest can be added optionally depending on how you want the
deformations to behave.</p>
<center><p><img decoding="async" loading="lazy" alt="Soft-body lattice: mass points, edges, and cells" src="https://dimforge.com/assets/images/lattice-fb11ad3121188ce8d380afdbb4b4e077.svg" width="800" height="251" class="img_XsDP"></p></center>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>Note this is just <em>a</em> choice of soft-body representation we made for Rapier. Other physics engines might model soft-bodies
differently depending on the mathematical methods they implement and the performance/realism compromises they choose.</p></div></div>
<p>Rapier supports three ways of modeling forces preserving the cohesion of the soft-body: shape-matching, constraints,
and the Finite Elements Method (FEM).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="shape-matching">Shape-matching<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#shape-matching" class="hash-link" aria-label="Direct link to Shape-matching" title="Direct link to Shape-matching">​</a></h3>
<p><em>Main reference: <a href="https://dl.acm.org/doi/10.1145/1073204.1073216" target="_blank" rel="noopener noreferrer">Meshless deformations based on shape matching (Müller, et al.)</a></em></p>
<p>Shape-matching is the simplest approach that only needs the soft-body mass points to work (no need for edges or cells).
It is good for sets of unstructured points or if the ability of the point-cloud to always recover its original shape
after absurdly massive deformations is important. It is cheap to calculate but deformations might feel too local since
pressing on one particle will not necessarily affect its neighbors (but this can be improved by enabling both
shape-matching and <a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#spring-constraints">spring constraints</a> simultaneously).</p>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>For a very good introduction to the shape-matching method, we recommend checking out the fantastic
<a href="https://www.youtube.com/watch?v=3OmkehAJoyo&amp;t=563s" target="_blank" rel="noopener noreferrer">Physics of JellyCar</a> video at 9:23.</p></div></div>
<p>Shape-matching roughly works the following way:</p>
<ol>
<li>Calculate the centers of the deformed and rest (undeformed) shape.</li>
<li>Align the rest shape on top of the deformed shape so both centers coincide.</li>
<li>Then calculate the best orientation that makes the deformed points the closest to their
undeformed version.</li>
</ol>
<center><p><img decoding="async" loading="lazy" alt="Shape-matching steps" src="https://dimforge.com/assets/images/shape-matching-601467f070f7133fb6b94e6b7d86b6d8.svg" width="1070" height="344" class="img_XsDP"></p></center>
<p>Once the matched pose is found and applied to the undeformed soft-body so it aligns roughly with the current deformed
version, a virtual spring is inserted between each deformed point and its undeformed twin. The constraints solver then
calculates the spring forces on each deformed point individually, making it eventually recover its undeformed shape.
As you can see, each point is considered individually, there is no constraint between two mass points of the same
deformed soft-body.</p>
<div class="theme-admonition theme-admonition-tip admonition_v1XZ alert alert--success"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_nS2X"><p>Use shape-matching for low-detail or degenerate deformations, or for situations where calculating a topology (edges,
cells, etc.) is not desired. Shape-matching performs very poorly for ropes, cloth, or any highly deformable
non-closed shapes.</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="spring-constraints">Spring constraints<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#spring-constraints" class="hash-link" aria-label="Direct link to Spring constraints" title="Direct link to Spring constraints">​</a></h3>
<p><em>Main reference: <a href="https://dl.acm.org/doi/10.1145/3487983.3488289" target="_blank" rel="noopener noreferrer">A Constraint-based Formulation of Stable Neo-Hookean Materials (Macklin &amp; Müller)</a></em></p>
<p>Constraints-based deformations are likely the most common and versatile approach. It offers a good compromise between
realism and performance. Its main limitation compared to FEM is that the apparent stiffness of the soft-body is dependent
on the constraints solver convergence: low iteration count results in softer material even at high stiffness
coefficient.</p>
<p>Spring constraints work with both edges and cells. For edges, springs are modeled as a simple spring-damper system. For
cells, they can either use a constraints-based Neo-Hookean or Corotated linear elastic model (which you can interpret
as Hooke’s law but on a volumetric element instead of a segment), or a volume constraint (the deformed cell aims
to match the rest volume).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="finite-elements-method-fem">Finite Elements Method (FEM)<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#finite-elements-method-fem" class="hash-link" aria-label="Direct link to Finite Elements Method (FEM)" title="Direct link to Finite Elements Method (FEM)">​</a></h3>
<p><em>Main reference: <a href="https://dl.acm.org/doi/10.1145/280814.280821" target="_blank" rel="noopener noreferrer">Large steps in cloth simulation</a></em></p>
<p>The FEM solver offers the most realism but is also significantly more computationally expensive. It will resolve
deformations semi-implicitly, making it capable of simulating very stiff materials. The FEM solver requires cells to
operate, meaning that you need some sort of triangulation (in 2D) or tetrahedrization (in 3D) of your model.
Rapier provides some triangulation and tetrahedrization functions through <code>SoftBodyBuilder::volumetric</code>, which fills
a closed boundary mesh with cells:</p>
<ul>
<li>In 2D, the interior of the boundary polyline is triangulated with Delaunay and refinement to insert
internal mass points.</li>
<li>In 3D, the shape is enclosed with tetrahedrons using the
<a href="https://doi.org/10.1145/1276377.1276448" target="_blank" rel="noopener noreferrer">Isosurface Stuffing (Labelle &amp; Shewchuk)</a> method.</li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_v1XZ alert alert--success"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_nS2X"><p>Use FEM for stiffer materials where you want its simulated stiffness to be independent of the solver iteration count.
This also results in more realistic plasticity and failures (tearing).</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="handling-penetrations-and-self-intersections">Handling penetrations and self-intersections<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#handling-penetrations-and-self-intersections" class="hash-link" aria-label="Direct link to Handling penetrations and self-intersections" title="Direct link to Handling penetrations and self-intersections">​</a></h2>
<p>Because deformable bodies will almost always end up having a non-convex shape, collision-detection
and collision resolution immediately become an order of magnitude more difficult than with rigid-bodies. In fact, game
physics engines generally try very hard to avoid non-convex colliders for dynamic rigid-bodies; this is why you
will almost always see concave shapes approximated with convex primitives using Compound Shapes or (Approximate)
Convex Decomposition. Some physics engines entirely forbid using meshes as the collision shapes for dynamic
rigid-bodies.</p>
<p>But why do physics engines try to avoid non-convex colliders on dynamic bodies so much? Two main reasons:</p>
<ol>
<li><strong>Performance:</strong> for example detecting collisions between two cubes through the SAT algorithm is much
cheaper than colliding their 12-triangle mesh representations.</li>
<li><strong>Collision response:</strong> because meshes (polylines in 2D) do not have an explicit representation of their
interiors, they are generally seen as triangle soups. And each triangle/triangle collision is seen
individually. So if two meshes (or polylines) are penetrating, some contacts will actually actively try to keep them
in this penetration state instead of resolving the penetration.</li>
</ol>
<center><p><img decoding="async" loading="lazy" alt="Local contacts between penetrating meshes" src="https://dimforge.com/assets/images/mesh-penetration-84fca47890cf1c7f43a0623070df8562.svg" width="560" height="287" class="img_XsDP"></p></center>
<p>The performance issue isn’t a huge deal: as long as the game developer is aware of the cost, they can decide on when
and how soft-bodies are relevant to their gameplay. The collision response issue on the other hand is out of the game
developer’s hands since this is core physics engine behavior.</p>
<p>And of course, deformations make it even worse: not only can two meshes penetrate, but a single mesh can also deform
and intersect itself, getting tangled with itself:</p>
<center><p><img decoding="async" loading="lazy" alt="Self-intersecting soft blobs: overlapping ends, crumpled boundary, and a twisted inside-out lobe" src="https://dimforge.com/assets/images/self-intersection-bb348db86f248d798e59dd5e7b138406.svg" width="920" height="236" class="img_XsDP"></p></center>
<p>The mesh/mesh intersection and self-intersection problems are not new. While the collision-detection itself is a
somewhat well-solved problem (as long as we keep it feature-local), the modeling and resolution of the contacts is a
very difficult problem for physics simulation, resulting in decades of still-ongoing research. Here are the main
families of approaches we identified from the literature:</p>
<ol>
<li><strong>Guarantee no penetrations/self-intersections</strong>: the idea is that if you can guarantee that the physics solver behaves in
such a way that two meshes never penetrate or self-intersect no matter how hard you push on them or how folded they are,
then you completely eliminate the penetration/self-intersection problem. This is arguably the most true-to-reality approach,
but it comes at a heavy cost from the constraint solver. This generally involves mesh CCD (Continuous Collision Detection),
barrier potentials (contact models that get infinitely strong as the distance gets close to zero), and an implicit
solver iterated to convergence to satisfy the constraints. <a href="https://dl.acm.org/doi/epdf/10.1145/3386569.3392425" target="_blank" rel="noopener noreferrer">IPC</a>
and <a href="https://arxiv.org/pdf/2201.10022" target="_blank" rel="noopener noreferrer">ABD</a> are two major publications in that domain. Methods falling in that category
often leverage the GPU to achieve interactive rates.</li>
<li>Let penetrations happen, and use <strong>global analysis</strong> to fix them. Since a simple triangle/triangle local collision
response cannot work, the idea is to identify patches of penetrating mesh elements that need to be pushed globally.
We recommend the paper <a href="https://dl.acm.org/doi/epdf/10.1145/1201775.882357" target="_blank" rel="noopener noreferrer">Untangling Cloth (Baraff, et al.)</a>.</li>
<li>Consider penetrations as a normal occurrence and rely on the <strong>intersection volume</strong> for the contact model. We are thinking in
particular of the paper <a href="https://inria.hal.science/inria-00502446/en" target="_blank" rel="noopener noreferrer">Volume Contact Constraints at Arbitrary Resolution (Allard, et al.)</a>.
The idea is to let the shapes penetrate and
define a contact model that pushes the deformable objects in the direction opposite to the volume gradient (i.e.
push them to minimize the volume overlap). This has the benefit of being independent of the actual triangle/triangle
contact points/normals that are at the core of our collision-resolution issues.</li>
</ol>
<p>For Rapier, we experimented with (2) and (3) as they both felt reasonable performance-wise on paper. (1) felt clearly out
of our performance budget.</p>
<p>The approach (2) was reasonably good, but can suffer from occasional glitches due to floating-point inaccuracies during the global
search/flooding. This can occasionally result in a suddenly incorrect movement when the simulation would otherwise
remain peaceful. But we do think that (2) has good potential and might revisit it later (and encourage other engine
writers to consider it so we can figure out how to make it work more robustly and efficiently).</p>
<p>The approach (3) was very promising as soon as we tried it. While we did not end up keeping an implementation that matches
everything from the paper, our solution can be seen as a dumbed-down variant of that paper. It boils down to one observation: the
"volume normal" obtained from the volume gradient (which the paper uses for defining the friction plane) turns out to be
a fairly good approximation of the MTV (Minimum Translation Vector) direction.</p>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>In rigid-body physics, the MTV is essentially the smallest direction and distance you need to push your object towards to fix
penetration. In a purely mathematical sense, this is the smallest distance between the origin and the boundary of the
<a href="https://en.wikipedia.org/wiki/Minkowski_addition" target="_blank" rel="noopener noreferrer">Minkowski Difference</a> of the two shapes. This is "easy" to find for
pairs of convex objects since their Minkowski Difference can be cheaply defined implicitly through the subtraction of
their respective support mappings (the <a href="https://docs.rs/parry3d/latest/parry3d/shape/trait.SupportMap.html" target="_blank" rel="noopener noreferrer"><code>SupportMap</code> trait</a> in Rapier/Parry). It is however extremely difficult and
computationally expensive to calculate on arbitrary non-convex shapes. The schematic below shows the difference between
local depenetration vectors (red) and the actual global MTV (blue) for a non-convex intersection.</p><center><p><img decoding="async" loading="lazy" alt="MTV versus local depenetration vectors for a bar stuck in a U-shaped obstacle" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NjAgMzg2LjM1IiB3aWR0aD0iNTYwIiBoZWlnaHQ9IjM4Ni4zNSIgZm9udC1mYW1pbHk9Ii1hcHBsZS1zeXN0ZW0sICdTZWdvZSBVSScsIFJvYm90bywgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZiIgcm9sZT0iaW1nIj4KICA8dGl0bGU+TVRWIHZlcnN1cyBsb2NhbCBkZXBlbmV0cmF0aW9uIHZlY3RvcnM8L3RpdGxlPgogIDxkZXNjPkEgcmVjdGFuZ3VsYXIgYmFyIHBlbmV0cmF0aW5nIGJvdGggYXJtcyBvZiBhIFUtc2hhcGVkIG9ic3RhY2xlLiBUaGUgbWluaW11bSB0cmFuc2xhdGlvbiB2ZWN0b3IgcHVzaGVzIHRoZSBiYXIgdXAsIG91dCBvZiB0aGUgVS4gVGhlIGxvY2FsIGRlcGVuZXRyYXRpb24gdmVjdG9ycywgY29tcHV0ZWQgZnJvbSB0aGUgd2FsbHMgb2YgdGhlIGFybXMsIHB1c2ggdGhlIGJhciBzaWRld2F5cyBpbiBvcHBvc2l0ZSBkaXJlY3Rpb25zIGFuZCBjYW5jZWwgZWFjaCBvdGhlci48L2Rlc2M+CiAgPHJlY3QgeD0iMC41IiB5PSIwLjUiIHdpZHRoPSI1NTkiIGhlaWdodD0iMzg1LjM1IiByeD0iMTIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iI2UxZTRlOCIvPgogIDx0ZXh0IHg9IjI4MC4wIiB5PSIzOC4wIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxZTIxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNjAwIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgcGFpbnQtb3JkZXI9InN0cm9rZSI+QmFyIHN0dWNrIGluIGJvdGggYXJtcyBvZiBhIFUtc2hhcGVkIG9ic3RhY2xlPC90ZXh0PgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTI0LjIpIj48cG9seWdvbiBwb2ludHM9IjExMS4wLDEzNy4wIDQ0OS4wLDEzNy4wIDQ0OS4wLDk4LjAgMTExLjAsOTguMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMjU2M2ViIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNCAzIi8+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTI0LjIpIj48cG9seWdvbiBwb2ludHM9IjEyNC4wLDM0NS4wIDQzNi4wLDM0NS4wIDQzNi4wLDEzNy4wIDM4NC4wLDEzNy4wIDM4NC4wLDI5My4wIDE3Ni4wLDI5My4wIDE3Ni4wLDEzNy4wIDEyNC4wLDEzNy4wIiBmaWxsPSIjZTRlN2ViIiBzdHJva2U9IiM0YjU1NjMiIHN0cm9rZS13aWR0aD0iMS44IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTI0LjIpIj48cG9seWdvbiBwb2ludHM9IjExMS4wLDIyMS41IDQ0OS4wLDIyMS41IDQ0OS4wLDE4Mi41IDExMS4wLDE4Mi41IiBmaWxsPSIjZDNmM2VhIiBmaWxsLW9wYWNpdHk9IjAuODUiIHN0cm9rZT0iIzFhODg3MCIgc3Ryb2tlLXdpZHRoPSIxLjgiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L2c+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMjQuMikiPjxwb2x5Z29uIHBvaW50cz0iMTI0LjAsMjIxLjUgMTc2LjAsMjIxLjUgMTc2LjAsMTgyLjUgMTI0LjAsMTgyLjUiIGZpbGw9IiNlNTQ4NGQiIGZpbGwtb3BhY2l0eT0iMC4zIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTI0LjIpIj48cG9seWdvbiBwb2ludHM9IjM4NC4wLDIyMS41IDQzNi4wLDIyMS41IDQzNi4wLDE4Mi41IDM4NC4wLDE4Mi41IiBmaWxsPSIjZTU0ODRkIiBmaWxsLW9wYWNpdHk9IjAuMyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PGxpbmUgeDE9IjExMS4wIiB5MT0iMjAyLjAiIHgyPSIxNjcuMCIgeTI9IjIwMi4wIiBzdHJva2U9IiNlNTQ4NGQiIHN0cm9rZS13aWR0aD0iMi42IiBzdHJva2UtbGluZWNhcD0iYnV0dCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PHBvbHlnb24gcG9pbnRzPSIxNzYuMCwyMDIuMCAxNjYuMCwyMDYuNSAxNjYuMCwxOTcuNSIgZmlsbD0iI2U1NDg0ZCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PGNpcmNsZSBjeD0iMTExLjAiIGN5PSIyMDIuMCIgcj0iMyIgZmlsbD0iI2U1NDg0ZCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PGxpbmUgeDE9IjQ0OS4wIiB5MT0iMjAyLjAiIHgyPSIzOTMuMCIgeTI9IjIwMi4wIiBzdHJva2U9IiNlNTQ4NGQiIHN0cm9rZS13aWR0aD0iMi42IiBzdHJva2UtbGluZWNhcD0iYnV0dCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PHBvbHlnb24gcG9pbnRzPSIzODQuMCwyMDIuMCAzOTQuMCwxOTcuNSAzOTQuMCwyMDYuNSIgZmlsbD0iI2U1NDg0ZCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PGNpcmNsZSBjeD0iNDQ5LjAiIGN5PSIyMDIuMCIgcj0iMyIgZmlsbD0iI2U1NDg0ZCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PGxpbmUgeDE9IjI4MC4wIiB5MT0iMjIxLjUiIHgyPSIyODAuMCIgeTI9IjE0Ny4wIiBzdHJva2U9IiMyNTYzZWIiIHN0cm9rZS13aWR0aD0iMi44IiBzdHJva2UtbGluZWNhcD0iYnV0dCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PHBvbHlnb24gcG9pbnRzPSIyODAuMCwxMzcuMCAyODQuOSwxNDguMCAyNzUuMSwxNDguMCIgZmlsbD0iIzI1NjNlYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PGNpcmNsZSBjeD0iMjgwLjAiIGN5PSIyMjEuNSIgcj0iMyIgZmlsbD0iIzI1NjNlYiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIvPjwvZz4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0yNC4yKSI+PHRleHQgeD0iMjkwLjAiIHk9IjE2OC4zIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMjU2M2ViIiB0ZXh0LWFuY2hvcj0ic3RhcnQiIGZvbnQtd2VpZ2h0PSI2MDAiIHN0cm9rZT0iI2ZmZmZmZiIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBwYWludC1vcmRlcj0ic3Ryb2tlIj5NVFY8L3RleHQ+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTQwLjcpIj48bGluZSB4MT0iNzcuMiIgeTE9IjQwMC4wIiB4Mj0iOTcuMiIgeTI9IjQwMC4wIiBzdHJva2U9IiMyNTYzZWIiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiLz48L2c+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNDAuNykiPjxwb2x5Z29uIHBvaW50cz0iMTAzLjIsNDAwLjAgOTYuMiw0MDMuMSA5Ni4yLDM5Ni45IiBmaWxsPSIjMjU2M2ViIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTQwLjcpIj48dGV4dCB4PSIxMTEuMiIgeT0iNDA0LjUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiM2MDY3NzAiIHRleHQtYW5jaG9yPSJzdGFydCIgZm9udC13ZWlnaHQ9Im5vcm1hbCIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHBhaW50LW9yZGVyPSJzdHJva2UiPk1UVjwvdGV4dD48L2c+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNDAuNykiPjxsaW5lIHgxPSIxNTcuNiIgeTE9IjQwMC4wIiB4Mj0iMTc3LjYiIHkyPSI0MDAuMCIgc3Ryb2tlPSIjZTU0ODRkIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJidXR0Ii8+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTQwLjcpIj48cG9seWdvbiBwb2ludHM9IjE4My42LDQwMC4wIDE3Ni42LDQwMy4xIDE3Ni42LDM5Ni45IiBmaWxsPSIjZTU0ODRkIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9nPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTQwLjcpIj48dGV4dCB4PSIxOTEuNiIgeT0iNDA0LjUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiM2MDY3NzAiIHRleHQtYW5jaG9yPSJzdGFydCIgZm9udC13ZWlnaHQ9Im5vcm1hbCIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHBhaW50LW9yZGVyPSJzdHJva2UiPmxvY2FsIGRlcGVuZXRyYXRpb24gdmVjdG9yczwvdGV4dD48L2c+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNDAuNykiPjxyZWN0IHg9IjQwNC4yIiB5PSIzOTMuMCIgd2lkdGg9IjIwLjAiIGhlaWdodD0iMTQuMCIgcng9IjIiIGZpbGw9IiNmN2I2YjgiIHN0cm9rZT0iI2U1NDg0ZCIgc3Ryb2tlLXdpZHRoPSIxLjIiLz48L2c+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNDAuNykiPjx0ZXh0IHg9IjQzNS4yIiB5PSI0MDQuNSIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzYwNjc3MCIgdGV4dC1hbmNob3I9InN0YXJ0IiBmb250LXdlaWdodD0ibm9ybWFsIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgcGFpbnQtb3JkZXI9InN0cm9rZSI+b3ZlcmxhcDwvdGV4dD48L2c+Cjwvc3ZnPgo=" width="560" height="386" class="img_XsDP"></p></center></div></div>
<p>Obtaining a good approximation of the MTV between two deformable meshes is very valuable, even if we don’t necessarily
know its magnitude. This allows us to push the shapes toward that direction until they de-penetrate. And since we
consider that direction as the "blessed" depenetration direction, we can use it to filter-out/fix incorrect local
triangle/triangle contact directions that would otherwise make the pair of meshes stay in a penetrating/tangled
configuration.</p>
<center><p><img decoding="async" loading="lazy" alt="Contact directions corrected with the volume normal" src="https://dimforge.com/assets/images/volume-normal-contacts-d64c1b30bfe50ce7e37bac89edb205e0.svg" width="960" height="292" class="img_XsDP"></p></center>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="the-concept-of-soft-frames-for-joints-and-colliders">The concept of soft frames for joints and colliders<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#the-concept-of-soft-frames-for-joints-and-colliders" class="hash-link" aria-label="Direct link to The concept of soft frames for joints and colliders" title="Direct link to The concept of soft frames for joints and colliders">​</a></h2>
<p>Physics engines often limit the types of joints you can attach to soft-bodies, and the API for doing so is usually
separate from the main rigid-body API. In Rapier, we introduce the concept of <strong>soft frames</strong> to solve this rather
elegantly. A <strong>soft frame</strong> is a coordinate system (translation + rotation) associated to a piece of a soft-body.
That coordinate system is represented as a <code>RigidBody</code> with a special <code>RigidBodyType::SoftFrame</code> type (recall that
until now Rapier supported the <code>RigidBodyType::Dynamic</code>, <code>::Fixed</code>, <code>::KinematicPositionBased</code> and <code>::KinematicVelocityBased</code>
types. So <code>::SoftFrame</code> is just an additional variant to that enum). This is useful for two reasons:</p>
<ul>
<li>Joints and non-deformable colliders need both a translation and a rotation to work. This is precisely what rigid-bodies provide.</li>
<li>By representing soft-frames as regular rigid-bodies, all the pre-existing APIs work the same: if you want to attach
a joint to a soft-body, just attach it to one of its soft-frames. Same for colliders. You define and manipulate them
exactly the same way as you would with a regular rigid-body.</li>
</ul>
<p>Essentially, the concept of soft-frame is to associate, and automatically update, a single translation and rotation to a soft-body.
That single translation and rotation should hopefully behave continuously through time and should be representative of
its location/orientation if it weren’t deformed. We already discussed a concept we can reuse precisely for
that: <a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#shape-matching">shape-matching</a>!</p>
<p>So, in essence, a <code>RigidBody</code> of type <code>SoftFrame</code> is a special type of <code>RigidBody</code> which has its translation
and rotation automatically calculated with shape-matching on its associated soft-body at each step.
When a <code>SoftBody</code> is created, Rapier automatically creates a companion <code>RigidBody</code> with type <code>SoftFrame</code>. That
companion <code>RigidBody</code> (that we also call a "proxy") has a <code>RigidBodyHandle</code> that you can use for attaching
impulse joints and rigid colliders to it, just like you would with any other rigid-body.</p>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>The existence of that rigid-body proxy is actually very convenient for other internal reasons. In Rapier, a lot of
the existing logic, like the handling of islands, the narrow-phase, etc., is built around rigid-bodies and colliders.
So relying on a rigid-body proxy and colliders attached to it avoids adding complexity (and potential bugs or performance
regressions) to this internal plumbing.</p></div></div>
<p>But that single soft-frame is often not expressive enough. If you want to attach two (or more) joints to a
soft-body, or if you want the joint’s effect to be concentrated at a particular location other than around
the center of mass, the whole-body soft-frame will not be enough.</p>
<p>This is why a soft-body can have multiple soft-frames associated to it. Each soft-frame can be associated to any
subset of the soft-body’s mass points and the resulting shape-matching for translation and rotation calculations will
be local to that subset of points. This allows joints to be attached to smaller clusters of mass points independently,
each with their own independent orientation.</p>
<center><p><img decoding="async" loading="lazy" alt="One soft-frame per cluster" src="https://dimforge.com/assets/images/multi-clusters-fa629042885822a398d43864447f3cca.svg" width="940" height="393" class="img_XsDP"></p></center>
<p>Therefore, Rapier allows you to create clusters on soft-bodies, each with an associated <code>SoftFrame</code>. Each of these
is a <code>RigidBody</code> with positions and rotations synced automatically from the shape-matching on subsets of the soft-body
mass points. Thus, you can also attach non-deformable colliders to them, meaning that two rigid-colliders attached to
the same soft-body but through different soft-frames will move and orient themselves independently.</p>
<center><p><img decoding="async" loading="lazy" alt="Rigid colliders attached to different soft-frames" src="https://dimforge.com/assets/images/multi-colliders-f4c175e899ca646f98a569c274cb3d4e.svg" width="940" height="340" class="img_XsDP"></p></center>
<div class="theme-admonition theme-admonition-warning admonition_v1XZ alert alert--warning"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>warning</div><div class="admonitionContent_nS2X"><p>If no rotation can be calculated from shape-matching (for example if the soft-frame only covers one or two mass points),
then joints attached to it will see their angular parts fully disabled.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="cage-simulation-and-skinning">Cage simulation and skinning<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#cage-simulation-and-skinning" class="hash-link" aria-label="Direct link to Cage simulation and skinning" title="Direct link to Cage simulation and skinning">​</a></h2>
<p>Unlike engineering, games don’t worry too much about mechanical correctness. Instead, they want the simulations to look
good, stable, and to run fast. As a result, it is not uncommon for the simulation shapes to be significantly simpler
than the visual shapes: meshes are approximated with coarser meshes or even with primitives, some details are ignored,
etc. The same holds for soft-bodies: handling every single visual triangle as its own soft cell is often unnecessary
and will often impact performance and even robustness badly (too large number of elements and/or badly shaped elements).
This is why Rapier supports <strong>cage simulation</strong> and <strong>skinning</strong>.</p>
<center><p><img decoding="async" loading="lazy" alt="Cage simulation and skinning: a detailed mesh, its coarse cage, and the mesh following the deformed cage" src="https://dimforge.com/assets/images/cage-skinning-1b52251a462fd85dcbfe4fe3782040eb.svg" width="1010" height="295" class="img_XsDP"></p></center>
<p><strong>Cage simulation</strong> means that your detailed deformable mesh (collision and/or visual) is trapped into a deformable "cage". That cage is
a volumetric blob that often has a larger volume than the original mesh. Similarly, a
deformable sheet would be modeled as a thicker set of deformable tetrahedrons (or triangles in 2D). That "cage" generally has a much
lower geometric precision than the visual mesh, and has the benefit of being well-formed (e.g. regular tetrahedrons) and
volumetric. The vertex positions of that detailed mesh are interpolated from the deformed cage: this is <strong>skinning</strong>. Note
that you don’t need a volumetric cage for leveraging skinning: it would also work with any deformable mesh associated to
your visual mesh.</p>
<div class="theme-admonition theme-admonition-tip admonition_v1XZ alert alert--success"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_nS2X"><p>Rapier is capable of automatically calculating a cage for simulating any deformable mesh with
<code>SoftBodyBuilder::volumetric_skinned</code>. In 3D, it is built using the
<a href="https://doi.org/10.1145/1276377.1276448" target="_blank" rel="noopener noreferrer">Isosurface Stuffing</a> algorithm, skipping the snapping step so that the input mesh
remains fully enclosed. That automatic calculation is focused on performance rather than geometric fidelity.</p><center><img src="https://dimforge.com/img/blog/2026-09-25/soft-trimesh-cages.png" width="500" alt="A screwdriver mesh and its automatically generated cage (blue)"><br><em>A detailed screwdriver mesh and its automatically generated coarse deformation cage (blue)</em></center></div></div>
<p>The paper
<a href="https://www.sciencedirect.com/science/article/pii/S0167839624000517?via%3Dihub" target="_blank" rel="noopener noreferrer">Skeleton based tetrahedralization of surface meshes</a>
is how we learned about the existence of cage simulation (but we didn’t end up implementing that paper’s skeleton-based
technique).</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="permanent-deformations-tearing-and-plasticity">Permanent deformations: tearing and plasticity<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#permanent-deformations-tearing-and-plasticity" class="hash-link" aria-label="Direct link to Permanent deformations: tearing and plasticity" title="Direct link to Permanent deformations: tearing and plasticity">​</a></h2>
<p><em>Main reference: <a href="https://dl.acm.org/doi/10.5555/1006058.1006087" target="_blank" rel="noopener noreferrer">Interactive virtual materials (Müller &amp; Gross)</a></em></p>
<p>Finally, two interesting features of soft-bodies are the ability to model permanent deformations. We distinguish two
concepts:</p>
<ul>
<li><strong>Plasticity:</strong> permanent change of rest position of the mass points (without any topology change). This models
materials like a piece of metal that folds on impact, clay being molded, etc.</li>
<li><strong>Tearing</strong> (aka. "failure/fracture")<strong>:</strong> permanent change of the soft-body topology where pieces of it physically
disconnect from other pieces. This models effects like breaking glass, a piece of fabric being torn in two, etc.
Tearing is implemented with a mass-splitting approach. Instead of removing elements (edges or cells) when they are
torn, we split their mass points in two. That way, the volume of the post-split shape matches the volume before the
split. Each connected component after the split becomes its own independent soft-body.</li>
</ul>
<center><p><img decoding="async" loading="lazy" alt="Plasticity and tearing" src="https://dimforge.com/assets/images/plasticity-tearing-824043fab8af69c179ccf5b0e3abd326.svg" width="920" height="486" class="img_XsDP"></p></center>
<p>Rapier supports tearing and plasticity with both solver types (<code>SoftBodySolver::Fem</code> and <code>::Constraints</code>). When
using the constraints-based solver, the quality of plastic deformations is strongly correlated to the solver’s
convergence, meaning that more solver iterations result in more convincing permanent deformations.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="where-can-i-use-rapiers-soft-bodies-today">Where can I use Rapier’s soft-bodies today?<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#where-can-i-use-rapiers-soft-bodies-today" class="hash-link" aria-label="Direct link to Where can I use Rapier’s soft-bodies today?" title="Direct link to Where can I use Rapier’s soft-bodies today?">​</a></h2>
<p>Soft-bodies are available starting with Rapier 0.36.0. They can currently be used from:</p>
<ul>
<li><strong>Rust:</strong> using the rapier crates directly: <a href="https://crates.io/crates/rapier2d" target="_blank" rel="noopener noreferrer">rapier2d</a> and <a href="https://crates.io/crates/rapier3d" target="_blank" rel="noopener noreferrer">rapier3d</a>, <a href="https://rapier.rs/docs/user_guides/rust/getting_started" target="_blank" rel="noopener noreferrer">user guide</a>.</li>
<li><strong>Typescript:</strong> using our official Typescript bindings, available on NPM: <a href="https://www.npmjs.com/package/@dimforge/rapier2d" target="_blank" rel="noopener noreferrer">@dimforge/rapier2d</a> and <a href="https://www.npmjs.com/package/@dimforge/rapier3d" target="_blank" rel="noopener noreferrer">@dimforge/rapier3d</a>, <a href="https://rapier.rs/docs/user_guides/javascript/getting_started_js" target="_blank" rel="noopener noreferrer">user guide</a>.</li>
<li><strong>Python:</strong> using our official Python bindings, available on PyPI (3D only): <a href="https://pypi.org/project/rapier3d/" target="_blank" rel="noopener noreferrer">rapier3d</a>, <a href="https://rapier.rs/docs/user_guides/python/getting_started_py" target="_blank" rel="noopener noreferrer">user guide</a>.</li>
<li><strong>C:</strong> using our (new <!-- -->🎉<!-- -->) official C bindings: <a href="https://github.com/dimforge/rapier/tree/master/bindings/c" target="_blank" rel="noopener noreferrer">sources</a>, <a href="https://rapier.rs/docs/user_guides/c/getting_started_c" target="_blank" rel="noopener noreferrer">user guide</a>.</li>
<li><strong>Bevy:</strong> with <code>bevy_rapier</code> for integration with the Bevy game engine: <a href="https://github.com/dimforge/rapier/tree/master/bindings/bevy_rapier" target="_blank" rel="noopener noreferrer">sources</a>, <a href="https://rapier.rs/docs/user_guides/bevy_plugin/getting_started_bevy" target="_blank" rel="noopener noreferrer">user guide</a>.</li>
</ul>
<div class="theme-admonition theme-admonition-danger admonition_v1XZ alert alert--danger"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>danger</div><div class="admonitionContent_nS2X"><p>Our updated Bevy plugin <code>bevy_rapier</code> is not published yet because it currently depends on a more recent, unreleased,
commit of the Bevy <code>main</code> branch. This is temporary until the next Bevy release. This is a necessary limitation because
Bevy 0.19.1 still depends on an outdated version of <code>glam</code>. It will be fixed with Bevy 0.20.0.</p></div></div>
<p>Support in <strong>Godot</strong> will likely be added once the third-party <a href="https://godot.rapier.rs/" target="_blank" rel="noopener noreferrer">godot-rapier</a> plugin gets updated.</p>
<p>The new C bindings will allow easier integration of Rapier into other popular game engines (Unity, Unreal, etc.) in the future.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="acknowledgements">Acknowledgements<a href="https://dimforge.com/blog/2026/09/25/advanced-soft-bodies-for-games-in-the-rapier-physics-engine#acknowledgements" class="hash-link" aria-label="Direct link to Acknowledgements" title="Direct link to Acknowledgements">​</a></h2>
<p>We cannot thank enough:</p>
<ul>
<li><a href="https://futurewei.com/" target="_blank" rel="noopener noreferrer">Futurewei</a> for sponsoring our physics work for robotics and AI.</li>
<li><a href="https://nlnet.nl/commonsfund/" target="_blank" rel="noopener noreferrer">NGI Zero Commons Fund</a> for accepting our grant proposal to further extend the solvers
supported by our GPU physics engine <a href="https://nexus.dimforge.com/" target="_blank" rel="noopener noreferrer">Nexus</a>.</li>
<li>The maintainers of all the fantastic libraries we build on top of.</li>
</ul>
<center><a href="https://futurewei.com/"><img src="https://dimforge.com/img/futurewei-logo.png" height="50px"></a><a href="https://nlnet.nl/commonsfund/"><img src="https://dimforge.com/img/nlnet-logo.png" height="50px"></a></center>
<p>Thanks to all the former, current and new sponsors! This helps us tremendously to sustain our Free and Open-Source work.
Finally, a huge thanks to the whole community and contributors!</p>
<p><em>** Credit: the car model from the "Plastic car chassis (3D)" demo video is
<a href="https://www.turbosquid.com/FullPreview/2179513" target="_blank" rel="noopener noreferrer">Dune Hunter (taanX)</a>.</em></p>
<hr>
<p>Help us sustain our open-source work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> or by <a href="mailto:contact@dimforge.com" target="_blank" rel="noopener noreferrer"><strong>reaching out</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dimforge Q2 2026 technical report − Nexus cross-platform GPU physics engine with rust-gpu]]></title>
            <link>https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report</link>
            <guid>https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report</guid>
            <pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Already half a year has past! This article summarizes the most significant additions made during]]></description>
            <content:encoded><![CDATA[<p>Already half a year has past! This article summarizes the most significant additions made during
the second quarter of 2026 to our open-source crates we develop for the Rust community.</p>
<p>If you haven’t seen it already please check out our <a href="https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report/" target="_blank" rel="noopener noreferrer">Q1 technical report</a> because our Q2 work is the continuation
of that exciting work. As promised, this second quarter led to the release of one of our new flagship projects:
<strong>Nexus</strong>, a cross-platform GPU multi-physics engine.</p>
<p>We also started making improvements to <strong>Rapier</strong>, our CPU-based rigid-body physics engine, for addressing issues and limitations
related to multibodies for robotics use-cases.</p>
<p>Finally, we have further enhanced the feature set of <strong>Kiss3d</strong>, or simple 2D and 3D graphics engine by bring a wide range
of more advanced rendering effects.</p>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p><strong>Nexus</strong> is still <strong>early and experimental</strong>. We are still in the process of figuring out the best APIs.
Expect rough edges and breaking changes.
The examples provided on the repository are currently the main source of truth on how to use Nexus.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="nexus-cross-platform-gpu-physics">Nexus: cross-platform GPU physics<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#nexus-cross-platform-gpu-physics" class="hash-link" aria-label="Direct link to Nexus: cross-platform GPU physics" title="Direct link to Nexus: cross-platform GPU physics">​</a></h2>
<center><a href="https://github.com/dimforge/nexus"><img src="https://dimforge.com/img/nexus-logo.jpg" width="50%"></a><p><a href="https://github.com/dimforge/nexus"></a><a href="https://github.com/dimforge/nexus" target="_blank" rel="noopener noreferrer">https://github.com/dimforge/nexus</a></p></center>
<div class="theme-admonition theme-admonition-tip admonition_v1XZ alert alert--success"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Try Nexus on the web!</div><div class="admonitionContent_nS2X"><p>Nexus is cross-platform and even works on the web if your browser supports WebGPU (but <strong>not in Safari</strong>).
Check out our online demos: <a href="https://nexus.dimforge.com/demos" target="_blank" rel="noopener noreferrer">https://nexus.dimforge.com/demos</a></p></div></div>
<p>We are very excited to release the first version of our GPU multi-physics engine: <strong>Nexus</strong>. It started as a port of our
former WGSL-based work <a href="https://github.com/wgmath/wgmath/tree/main/crates/wgrapier" target="_blank" rel="noopener noreferrer">wgrapier</a>. While it shares similar
algorithms, it differs in multiple major ways:</p>
<ul>
<li>All the shaders are written <strong>100% in Rust</strong>, using <a href="https://github.com/Rust-GPU/rust-gpu" target="_blank" rel="noopener noreferrer">rust-gpu</a>,
<a href="https://github.com/dimforge/khal" target="_blank" rel="noopener noreferrer">khal</a>, and <a href="https://github.com/dimforge/vortx" target="_blank" rel="noopener noreferrer">vortx</a>.</li>
<li>It implements <strong>more features</strong> including multibody joints, multiple colliders per bodies, and dynamic insertion of rigid-bodies.</li>
<li>It implements <strong>batch simulation</strong> to run thousands of variants of the same scene in parallel. This is typically used
for Machine Learning like Reinforcement Learning, and, more generally, training datasets generation.</li>
<li>It is generally <strong>2x faster</strong> than our WGSL implementation, and has a much smaller performance gap between running
natively and on the browser.</li>
</ul>
<div class="theme-admonition theme-admonition-warning admonition_v1XZ alert alert--warning"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>warning</div><div class="admonitionContent_nS2X"><p>URDF, MJCF and multibody support are still experimental. We are working on improving their performances and stability.</p></div></div>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-nexus-1" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/nexus-keva.png" width="300" title="Keva tower" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Keva tower</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-nexus-2" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/nexus-compound.png" width="300" title="Compound colliders" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Compound colliders</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-nexus-3" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/nexus-trimesh.png" width="300" title="Trimesh &amp; convex" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Trimesh &amp; convex</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-nexus-4" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/nexus-joints.png" width="300" title="Joints and bodies" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Joints and bodies</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-nexus-5" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/nexus-mjcf.png" width="300" title="MJCF robot" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">MJCF robot</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-nexus-6" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/nexus-2d.png" width="300" title="2D primitives" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">2D primitives</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="lightbox-nexus-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/nexus-keva.png" alt="Keva tower" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-nexus-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/nexus-compound.png" alt="Compound colliders" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-nexus-3" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/nexus-trimesh.png" alt="Trimesh &amp; convex" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-nexus-4" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/nexus-joints.png" alt="Joints and bodies" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-nexus-5" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/nexus-mjcf.png" alt="MJCF robot" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-nexus-6" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/nexus-2d.png" alt="2D primitives" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<p>Using the <code>wgpu</code> backend, Nexus can run on all major hardware and browsers (tested on Edge, Chrome, Firefox on Windows,
Linux, and MacOS). It is currently <strong>not</strong> compatible with Safari which has stronger restrictions on supported shaders.
It supports both 2D and 3D.</p>
<p>Creating a Nexus scene is done by initializing rigid-bodies, colliders, joints, etc. using Rapier types. They are
then converted to GPU resources internally. Nexus ships with a viewer built on top of <a href="https://kiss3d.dimforge.com/" target="_blank" rel="noopener noreferrer">kiss3d</a>; it is
capable of rendering the Nexus scene efficiently without any GPU→CPU synchronization when using its default (webgpu)
backend.</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">backend</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">GpuTimestamps</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">nexus_viewer3d</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">NexusViewer</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">nexus3d</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">prelude</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">NexusCapacities</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">NexusPipeline</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">NexusState</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RbdCoupling</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">rapier3d</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">prelude</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    viewer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">NexusViewer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">NexusPipeline</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">anyhow</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">NexusState</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">NXZ</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">isize</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">NY</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">isize</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">70</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> capacities </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NexusCapacities</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rbd_collisions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">500_000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> state </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NexusState</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">capacities</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> no_coupling </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RbdCoupling</span><span class="token punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">NONE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/*</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Falling dynamic objects.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token constant" style="color:#36acaa">NY</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> max_ik </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">NXZ</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">max_ik</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">max_ik </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> k </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">max_ik</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">max_ik </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.01</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.6</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> z </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> k </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.01</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> pos </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> body </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RigidBodyBuilder</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">dynamic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">translation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pos</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> collider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ColliderBuilder</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">cuboid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> shape </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">shared_shape</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">clone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> handle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert_rigid_body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> no_coupling</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert_shape</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">shape</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Pose</span><span class="token punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">IDENTITY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/*</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Floor made of large cuboids.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> thick </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">NXZ</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> height </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12.0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> walls_color </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Vec4</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> walls </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_pos</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> wall_sz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> walls </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> body </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RigidBodyBuilder</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">fixed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> collider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ColliderBuilder</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">cuboid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_sz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> wall_sz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> wall_sz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">z</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">translation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_pos</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> shape </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">shared_shape</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">clone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> handle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert_rigid_body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> no_coupling</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert_shape_with_color</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">shape</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Pose</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_translation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_pos</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> walls_color</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> timestamps </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GpuTimestamps</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">backend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2048</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">scene3d_mut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add_directional_light</span><span class="token punctuation" style="color:#393A34">(</span><span class="token namespace" style="opacity:0.7">glamx</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Optional finalize, useful so we can render even before starting the simulation.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">finalize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">backend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">render_frame</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">simulating</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            pipeline</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">simulate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">backend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> timestamps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Some</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> timestamps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="why-rust-gpu">Why rust-gpu?<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#why-rust-gpu" class="hash-link" aria-label="Direct link to Why rust-gpu?" title="Direct link to Why rust-gpu?">​</a></h3>
<p>You might be wondering why we decided to pick <code>rust-gpu</code> for such an ambitious project. Well, we tried many different
alternatives for single-source cross-platform GPU compute: WGSL, WESL, Slang. Unfortunately none of these reached the
quality of developper experience we were hopping for, either because of language limitations (with WGSL/WESL), or due to
difficulties to interface with a C++ stack and a lack of IDE tooling and package manager for sharing shaders across
projects (Slang).</p>
<p>Rust-gpu on the other hand lets us write shaders in Rust directly. It even allows us to reuse shader code across crates
using our beloved <code>cargo</code>. Because it is Rust, we don’t need to learn <em>yet another programming language</em>: we can even reuse
some of our (originally non-GPU) mathematics libraries (like <code>glamx</code> for advanced operations like the Singular Value
Decomposition), and we can write complex procedural macros in <code>khal</code> to interface the GPU code with the CPU code and
get compile-time type checking on kernel invocations! Moreover, the CPU code can depend on the GPU crate, so you can reuse the
GPU structures directly, eliminating all difficulties wrt. data layout mismatch. Finally, you can run your GPU code on the
CPU to debug easily like any other piece of regular Rust code. The productivity gain is massive, and writing GPU code
that way is much more pleasurable as a Rust developer!</p>
<p>But, still, is Rust the right choice for writing high-performance compute shaders? We are confident that, yes, it is a
strong option. We have actually observed a growing interest in writing compute shaders in Rust during the past few
months with:</p>
<ul>
<li><a href="https://github.com/NVlabs/cuda-oxide" target="_blank" rel="noopener noreferrer"><code>cuda-oxide</code></a>: recently announced by NVidia for compiling Rust code to Cuda.
It is somewhat similar in goals to <a href="https://github.com/Rust-GPU/rust-cuda" target="_blank" rel="noopener noreferrer"><code>rust-cuda</code></a>.</li>
<li><a href="https://github.com/NVlabs/cutile-rs" target="_blank" rel="noopener noreferrer"><code>cutile-rs</code></a>: Rust-based DSL for tile-based kernel programing, also maintained by NVidia.</li>
<li><a href="https://github.com/tracel-ai/cubecl" target="_blank" rel="noopener noreferrer"><code>cubecl</code></a>: Rust-based DSL for cross-platform gpu compute maintained by Tracel-AI.</li>
</ul>
<p>If NVidia themselves start to develop major interest into using Rust for CUDA, this suggests Rust on
GPU isn’t a bad idea after all. And this urges us to build a solid cross-platform scientific computing ecosystem in Rust
as early as possible, so the Rust community doesn’t get locked into the proprietary Cuda environments.</p>
<p>On a final note, it also feels encouraging that Khronos acknowledged the relevance of <code>rust-gpu</code> by listing it as one of
the options on their recent Shader Compiler Survey: <a href="https://www.surveymonkey.com/r/LKWFQ3M" target="_blank" rel="noopener noreferrer">https://www.surveymonkey.com/r/LKWFQ3M</a> (not sure how long that link
will remain valid).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="python-bindings">Python bindings<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#python-bindings" class="hash-link" aria-label="Direct link to Python bindings" title="Direct link to Python bindings">​</a></h3>
<p>Both the robotics and the machine learning communities strongly rely on Python. And since Nexus aims to also be beneficial
to both, we automatically generated Python bindings. The general design of the Python bindings aims to match the Rust
API as closely as possible in order to keep them as thin as possible (and make their maintainance easier). Bindings for
the viewer are also provided in the same package.</p>
<div class="language-py codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-py codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">"""Python port of `crates/examples3d/boxes3.rs`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="display:inline-block;color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">A grid of dynamic cuboids falls into a walled box. Run with:</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="display:inline-block;color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    maturin develop -m crates/nexus_python3d/Cargo.toml --features metal</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    python crates/nexus_python3d/examples/boxes3.py</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">"""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> nexus3d </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    NexusViewer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    NexusPipeline</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    NexusState</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    RbdCoupling</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    RigidBodyBuilder</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ColliderBuilder</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    GpuTimestamps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    Vec3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    Vec4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    Pose</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NXZ </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NY </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">70</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> NexusViewer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> NexusPipeline</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> NexusState</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    state </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> NexusState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    no_coupling </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> RbdCoupling</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">NONE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># Falling dynamic objects.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token builtin">range</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">NY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        max_ik </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> NXZ </span><span class="token operator" style="color:#393A34">//</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token builtin">range</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">max_ik</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> max_ik</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> k </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token builtin">range</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">max_ik</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> max_ik</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.01</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.6</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                z </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> k </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.01</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                pos </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                body </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> RigidBodyBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">dynamic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">translation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pos</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                collider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ColliderBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cuboid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                shape </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">shared_shape</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                handle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">insert_rigid_body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> no_coupling</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">insert_shape</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shape</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Pose</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">IDENTITY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># Floor made of large cuboids.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    thick </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> NXZ </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    height </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12.0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    walls_color </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> Vec4</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    walls </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">thick</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> wall_pos</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> wall_sz </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> walls</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        body </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> RigidBodyBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fixed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        collider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ColliderBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cuboid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_sz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> wall_sz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> wall_sz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">z</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">translation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_pos</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shape </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">shared_shape</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        handle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">insert_rigid_body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> no_coupling</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">insert_shape_with_color</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            handle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shape</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Pose</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">from_translation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">wall_pos</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> walls_color</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    timestamps </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> GpuTimestamps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2048</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_directional_light</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Vec3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># Optional finalize, useful so we can render even before starting the simulation.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">finalize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">render_frame</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">simulating</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            pipeline</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">simulate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestamps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">sync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestamps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> state</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    viewer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> NexusViewer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    viewer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">init_backend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> NexusPipeline</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">preload_pipelines</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">viewer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pipeline</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> __name__ </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"__main__"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> os</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">_exit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="reinforcement-learning">Reinforcement learning<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#reinforcement-learning" class="hash-link" aria-label="Direct link to Reinforcement learning" title="Direct link to Reinforcement learning">​</a></h3>
<p>We have been collaborating with Xavier Tao − <a href="https://github.com/haixuanTao" target="_blank" rel="noopener noreferrer">@haixuantao</a> − from <a href="https://1ms.ai/" target="_blank" rel="noopener noreferrer">1ms.ai</a> for feedbacks, optimizations, and
contributions related to using the  Nexus stack for Reinforcement Learning. While we are still early in the process, we are
already able to train a simple robot to stand and walk, relying on Nexus’ batch simulation to accelerate the training
loop. The <a href="https://github.com/haixuanTao/zealot" target="_blank" rel="noopener noreferrer">entire project</a> is in Rust.</p>
<p>Both videos below showcase a bipedal robot controlled by a neural network trained for standing (left) and walking
(right) using Nexus multibody joints and batch simulations.</p>
<center><video width="40%" controls="" style="margin-right:4%"><source src="/img/blog/2026-07-01/standing.mp4" type="video/mp4"><p>Your browser does not support the video tag.</p></video><video width="40%" controls=""><source src="/img/blog/2026-07-01/walking.mp4" type="video/mp4"><p>Your browser does not support the video tag.</p></video></center>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="next-steps">Next steps<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#next-steps" class="hash-link" aria-label="Direct link to Next steps" title="Direct link to Next steps">​</a></h3>
<p>While we present Nexus as a <strong>multi-physics</strong> engine, this release only supports rigid-body physics. We intend to extend
it further by supporting more models for non-rigid physics. One of our next main objectives is the addition of an MPM
solver (Material Points Method) with coupling with Nexus’ rigid-body solver.</p>
<p>We also intend to further improve the stability of multibodies, performances, and the public API of Nexus to make it
easier to interact with the scene while the simulation is running.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-improvements-for-robotics">Rapier: improvements for robotics<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#rapier-improvements-for-robotics" class="hash-link" aria-label="Direct link to Rapier: improvements for robotics" title="Direct link to Rapier: improvements for robotics">​</a></h2>
<center><a href="https://github.com/dimforge/rapier"><img src="https://dimforge.com/img/rapier-logo.jpg" width="50%"></a><p><a href="https://github.com/dimforge/rapier"></a><a href="https://github.com/dimforge/rapier" target="_blank" rel="noopener noreferrer">https://github.com/dimforge/rapier</a></p></center>
<p>One of our main focus for Rapier in 2026 is the improvement of its robotics-oriented features. During the past three
months, we started by addressing some long-standing bug reports on multibodies (both regarding crashes in instabilities).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="multibodies-and-mjcf">Multibodies and MJCF<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#multibodies-and-mjcf" class="hash-link" aria-label="Direct link to Multibodies and MJCF" title="Direct link to Multibodies and MJCF">​</a></h3>
<p>Since we wanted to test multibody simulations on more actual robot models, we implemented the support for MJCF files (i.e. the file format
from the MuJoCo project). These resulted in the <a href="https://github.com/dimforge/rapier/tree/master/crates/mjcf-rs" target="_blank" rel="noopener noreferrer"><code>mjcf-rs</code></a>
crate as the low-level parser that is independent of Rapier, and
<a href="https://github.com/dimforge/rapier/tree/master/crates/rapier3d-mjcf" target="_blank" rel="noopener noreferrer"><code>rapier3d-mjcf</code></a> for loading these MJCF files as
rapier multibodies. We then added a <a href="https://github.com/dimforge/rapier/blob/master/examples3d/mujoco_menagerie3.rs" target="_blank" rel="noopener noreferrer">new 3D example</a>
that lets you browse through a collection of MJCF models and simulate them. It is capable of loading most robots from
the <a href="https://github.com/google-deepmind/mujoco_menagerie" target="_blank" rel="noopener noreferrer">MoJoCo menagerie</a> dataset (you will have to clone the dataset yourself), including actuator keyframes as showcased
in the video below.</p>
<center><video width="90%" controls=""><source src="/img/blog/2026-07-01/rapier-mjcf-hand.mp4" type="video/mp4"><p>Your browser does not support the video tag.</p></video></center>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="the-physicsworld-object">The PhysicsWorld object<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#the-physicsworld-object" class="hash-link" aria-label="Direct link to The PhysicsWorld object" title="Direct link to The PhysicsWorld object">​</a></h3>
<p>One common difficulty with using <code>rapier</code> as a beginner is the large number of different collections to create
before being able to run a simulation. Rapier 0.34 introduces a new structure <code>PhysicsWorld</code> that wraps all these fields so
you can create them all at once. Using <code>PhysicsWorld</code> is not mendatory so you are free to keep using the individual
resounces and physics pipeline.</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">PhysicsWorld</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Gravity applied to all dynamic bodies each step.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> gravity</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Vector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Parameters controlling the simulation (timestep, solver iterations, etc.).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> integration_parameters</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">IntegrationParameters</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// The main simulation pipeline that orchestrates each physics step.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> physics_pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">PhysicsPipeline</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Manages active/sleeping body groups (islands) for efficient simulation.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> islands</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">IslandManager</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// The broad-phase acceleration structure for fast spatial queries.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> broad_phase</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">BroadPhaseBvh</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Precise contact and intersection detection between collider pairs.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> narrow_phase</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">NarrowPhase</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// All rigid bodies in this world.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> bodies</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodySet</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// All colliders (collision shapes) in this world.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> colliders</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderSet</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// All impulse-based joints (hinges, springs, ropes, etc.).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> impulse_joints</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ImpulseJointSet</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// All multibody joints (kinematic chains, articulations).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> multibody_joints</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">MultibodyJointSet</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// The continuous collision detection solver.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> ccd_solver</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">CCDSolver</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In addition, it exposes helper functions for inserting bodies, colliders, joints, etc. and stepping the simulation.
All the fields are public if you need finer grained control or need to avoid some situations where borrowing the whole
physics world instead of some of its components would be limiting.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="kiss3d-advanced-rendering-effects">Kiss3d: advanced rendering effects<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#kiss3d-advanced-rendering-effects" class="hash-link" aria-label="Direct link to Kiss3d: advanced rendering effects" title="Direct link to Kiss3d: advanced rendering effects">​</a></h2>
<center><a href="https://github.com/dimforge/kiss3d"><img src="https://dimforge.com/img/kiss3d-logo.png" width="50%"></a><p><a href="https://github.com/dimforge/kiss3d"></a><a href="https://github.com/dimforge/kiss3d" target="_blank" rel="noopener noreferrer">https://github.com/dimforge/kiss3d</a></p></center>
<p>Most popular physics engines from the robotics community ship with a nice viewer. This becomes especially relevant if
we want the viewer exposed through python bindings while being able to interact with the Nexus GPU resources
efficiently. Therefore, we have been enhancing the quality of the Kiss3d renderer significantly during the past quarter.
We also added a hardware-accelerated <strong>path-tracer</strong> for high-fidelity rendering.</p>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-1" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/pbr.png" width="300" title="PBR material" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">PBR material</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-2" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/transmission.png" width="300" title="Refraction" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Refraction</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-4" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/oit.png" width="300" title="Order Independent Transparency" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Order Independent Transparency</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-5" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/gltf.png" width="300" title="GLTF + animations" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">GLTF + animations</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-6" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/dof.png" width="300" title="Depth of field" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Depth of field</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-7" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/offscreen.png" width="300" title="Offscreen rendering" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Offscreen rendering</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-8" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/reflections.png" width="300" title="Reflections" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Reflections</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-9" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/bloom.png" width="300" title="Bloom" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Bloom</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#lightbox-kiss-10" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-07-01/pathtracing.png" width="300" title="Path tracing" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Path tracing</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="lightbox-kiss-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/pbr.png" alt="PBR material" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/transmission.png" alt="Refraction" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-4" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/oit.png" alt="Order Independent Transparency" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-5" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/gltf.png" alt="GLTF + animations" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-6" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/dof.png" alt="Depth of field" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-7" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/offscreen.png" alt="Offscreen rendering" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-8" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/reflections.png" alt="Reflections" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-9" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/bloom.png" alt="Bloom" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-kiss-10" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-07-01/pathtracing.png" alt="Path tracing" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<p>Of course, all these rendering features are cross-platform, and compatible with the web (though the path-tracer won’t
leverage GPU RT-specific hardware on the web). The <a href="https://kiss3d.dimforge.com/examples" target="_blank" rel="noopener noreferrer">kiss3d online examples</a> have been
updated for showcasing all the new features.</p>
<p><strong>Kiss3d</strong> is used as the  renderer for the Rapier and Nexus viewers. In particular, with Nexus, it enables rendering
all the simulated objects without any GPU→CPU synchronization since all the data needed for rendering is already available
on the GPU by making both use the same <code>wgpu</code> device.</p>
<div class="theme-admonition theme-admonition-tip admonition_v1XZ alert alert--success"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_nS2X"><p>If you enable the <code>rt-switcher</code> cargo feature of <strong>Kiss3d</strong>, then pressing keys from F5 to F8 will switch the renderer
to the path tracer where F5 is lowest quality preset and F8 highest. Press F4 to switch back to the rasterizer.
That feature is enabled on all Rapier and Nexus demos too. Keep in mind that it can be pretty slow on platforms with no
RT hardware acceleration (including all browsers).</p></div></div>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="conclusion">Conclusion<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>During this second quarter we reached a significant milestone on our cross-platform GPU physics journey by releasing the
rigid-body solver of Nexus, written with <code>rust-gpu</code>. With the introduction of python bindings and
the support of the popular MJCF format, we aim to reach a wider audience from the Robotics and ML communities.
We intend to make of Nexus a major multi-physics engine for large-scale robotics, ML,
animations, and engineering by adding more rigid and non-rigid solvers in the future like MPM.</p>
<p>We also started improving Rapier (our CPU-based rigid-body physics engine) for robotics by fixing long-standing bugs and
stability issues on multibodies. We also reworked its testbed to make it easier to use, making examples more
self-contained by avoiding internal callbacks.</p>
<p>Finally, the improvements of our Kiss3d renderer allowed us to easily integrate advanced rendering effects as well as a
path tracer to our physics showcases, while at the same time making it available through the Python bindings too. By
ensuring direct compatibility with the dependency versions shared with Nexus, we can guarantee the ability to render
complex 3D physics simulations without any GPU→CPU synchronization, ensuring excellent performances in most browsers too.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="acknowledgements">Acknowledgements<a href="https://dimforge.com/blog/2026/07/01/dimforge-Q2-technical-report#acknowledgements" class="hash-link" aria-label="Direct link to Acknowledgements" title="Direct link to Acknowledgements">​</a></h2>
<p>We cannot thank enough:</p>
<ul>
<li><a href="https://futurewei.com/" target="_blank" rel="noopener noreferrer">Futurewei</a> for sponsoring our physics work for robotics and AI.</li>
<li><a href="https://nlnet.nl/commonsfund/" target="_blank" rel="noopener noreferrer">NGI Zero Commons Fund</a> for accepting our grant proposal to further extend the solvers
supported by Nexus.</li>
<li>The maintainers of all the fantastic libraries we build on top of.</li>
</ul>
<center><a href="https://futurewei.com/"><img src="https://dimforge.com/img/futurewei-logo.png" height="50px"></a><a href="https://nlnet.nl/commonsfund/"><img src="https://dimforge.com/img/nlnet-logo.png" height="50px"></a></center>
<p>Thanks to all the former, current and new sponsors! This helps us tremendously to sustain our Free and Open-Source work.
Finally, a huge thanks to the whole community and contributors!</p>
<hr>
<p>Help us sustain our open-source work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> or by <a href="mailto:contact@dimforge.com" target="_blank" rel="noopener noreferrer"><strong>reaching out</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dimforge Q1 2026 technical report − GPU compute with khal, vortx, inferi]]></title>
            <link>https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report</link>
            <guid>https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report</guid>
            <pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Happy Easter Holiday everyone! This article summarizes the most significant additions made during]]></description>
            <content:encoded><![CDATA[<p>🐰<!-- --> <strong>Happy Easter Holiday everyone!</strong> <!-- -->🐰<!-- --> This article summarizes the most significant additions made during
the first quarter of 2026 to our open-source crates for cross-platform GPU compute that we develop for the Rust
community.</p>
<p>The first quarter of 2026 has been very exciting as we are laying out the foundations of our upcoming cross-platform
GPU physics libraries. We are introducing new crates:</p>
<ul>
<li><a href="https://github.com/dimforge/khal" target="_blank" rel="noopener noreferrer"><strong>Khal</strong></a>: abstraction layer for cross-platform compute on GPU and CPU.</li>
<li><a href="https://github.com/dimforge/vortx" target="_blank" rel="noopener noreferrer"><strong>Vortx</strong></a>: cross-platform GPU tensor library for general linear algebra.</li>
<li><a href="https://github.com/dimforge/inferi" target="_blank" rel="noopener noreferrer"><strong>Inferi</strong></a>: cross-platform GPU inference library.</li>
</ul>
<p>All these libraries are also compatible with browsers running WebGpu.
Physics simulation is still cooking and will be the main highlight of our next update for Q2 2026.</p>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>All the presented work is still <strong>early and experimental</strong>. We are still in the process of figuring out the best APIs.
Expect rough edges, breaking changes, as well as a general lack of reliable tutorials/documentation for now.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="khal-write-once-run-on-webgpu-cuda-and-cpu">Khal: write once, run on WebGpu, Cuda, and CPU<a href="https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report#khal-write-once-run-on-webgpu-cuda-and-cpu" class="hash-link" aria-label="Direct link to Khal: write once, run on WebGpu, Cuda, and CPU" title="Direct link to Khal: write once, run on WebGpu, Cuda, and CPU">​</a></h2>
<center><a href="https://github.com/dimforge/khal"><img src="https://dimforge.com/img/khal-logo.jpg" width="50%"></a><p><a href="https://github.com/dimforge/khal"></a><a href="https://github.com/dimforge/khal" target="_blank" rel="noopener noreferrer">https://github.com/dimforge/khal</a></p></center>
<p><strong>Khal</strong> (meaning "Kompute Hardware Abstraction Layer") facilitates writing Rust code once and have
it run on Vulkan, Metal, DirectX, WebGPU, CUDA, and the CPU. It can be seen as a wrapper around very strong tooling
developed by the community. For the Rust-to-GPU conversion it wraps:</p>
<ul>
<li><strong>rust-gpu</strong>: for compiling Rust code to SpirV.</li>
<li><strong>naga</strong>: for transpiling SpirV to target Metal, DirectX, Vulkan, WebGpu.</li>
<li><strong>rust-cuda</strong>: for compiling Rust code to Ptx (Cuda’s IR).</li>
</ul>
<p>On the host, it wraps:</p>
<ul>
<li><strong>wgpu</strong>: for initializing resources and running shaders on all gpu platforms over than Cuda.</li>
<li><strong>cudarc</strong>: for initializing resources and running shaders on Cuda.</li>
<li><strong>rayon</strong> and <strong>corosensei</strong>: for running the shaders on the CPU directly. It uses parallel iterations to run workgroups
in parallel, and coroutines for running threads from the same workgroup concurrently. The CPU target is currently very
inefficient so it is mostly relevant for debugging.</li>
</ul>
<p>The general idea is that you write two crates. A <code>no-std</code> crate holding your shader code that will get compiled by
rust-gpu and rust-cuda. And a second crate for holding all your application logic, gpu resource allocations, and shader
calls orchestration.</p>
<p>The key is that by abstracting all the elements mentioned above, <strong>khal</strong> allows you to write both crates only once
independently of your target (and 100% in Rust). If it works on any target (and, in particular the CPU target which is
the easiest to test and debug), you can be fairly confident it will work everywhere unless you hit some unexpected
platform-specific edge cases. <strong>Khal</strong> only focuses on compute shaders. Any rendering-specific shaders (vertex shader,
fragment shader, etc.) are out of scope.</p>
<center><img src="https://dimforge.com/img/blog/2026-04-05/khal-diagram.png" width="90%"></center>
<p>Let’s have a quick look at the <a href="https://github.com/dimforge/khal/tree/main/crates/khal-example" target="_blank" rel="noopener noreferrer">khal-example</a> and
<a href="https://github.com/dimforge/khal/tree/main/crates/khal-example-shaders" target="_blank" rel="noopener noreferrer">khal-example-shaders</a> example pair. The shader
crate for calculating the sum of two vectors is fairly straightforward:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token attribute attr-name" style="color:#00a4db">#![cfg_attr(target_arch = </span><span class="token attribute attr-name string" style="color:#e3116c">"spirv"</span><span class="token attribute attr-name" style="color:#00a4db">, no_std)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal_std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">glamx</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">UVec3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal_std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">macros</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">spirv_bindgen</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> spirv</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[spirv_bindgen]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[spirv(compute(threads(64)))]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">gpu_add_assign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token attribute attr-name" style="color:#00a4db">#[spirv(global_invocation_id)]</span><span class="token plain"> invocation_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">UVec3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token attribute attr-name" style="color:#00a4db">#[spirv(storage_buffer, descriptor_set = 0, binding = 0)]</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token attribute attr-name" style="color:#00a4db">#[spirv(storage_buffer, descriptor_set = 0, binding = 1)]</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> thread_id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> invocation_id</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">x </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> thread_id </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        a</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">thread_id</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">thread_id</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you are already familiar with rust-gpu, this should look like what you are used to, except for two details:</p>
<ul>
<li>We are importing the <code>spirv</code> macro and <code>UVec3</code> through <code>khal_std</code> instead of <code>spirv_std</code>. This is because <code>khal_std</code>
hides the details of conditional compilation between <code>spirv_std</code> and <code>cuda_std</code> depending on the target platform.</li>
<li>We are calling the <code>#[spirv_bindgen]</code> proc-macro. This is a new macro introduced by <code>khal_std</code> that runs compile-time
reflection for generating strongly typed interfaces between the device kernel and rust on the host. In particular, it generates
a <code>GpuAddAssign</code> structure (same name as the entrypoint but in PascalCase) with a <code>::call</code> method that expects strongly
typed gpu buffers for launching the kernel.</li>
</ul>
<p>Now let’s look at the host-side code:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">backend</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">Backend</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Buffer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Encoder</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">GpuBackend</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">GpuBackendError</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">WebGpu</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">re_exports</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">include_dir</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">Dir</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> include_dir</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">BufferUsages</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Shader</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal_example_shaders</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">AddAssign</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SPIRV_DIR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Dir</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'static</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">include_dir!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"$CARGO_MANIFEST_DIR/shaders-spirv"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[derive(Shader)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">GpuKernels</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    add_assign</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">GpuAddAssign</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[async_std::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> webgpu </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">WebGpu</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> backend </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GpuBackend</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">WebGpu</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">webgpu</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Run the operation and display the result.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">10000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">i</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Vec</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">_</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">10000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">i</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Vec</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">_</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">compute_sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">backend</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Computed sum: {result:?}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">compute_sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    backend</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token class-name">GpuBackend</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Vec</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">GpuBackendError</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Generate the GPU buffers.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> backend</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init_buffer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">BufferUsages</span><span class="token punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">STORAGE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token class-name">BufferUsages</span><span class="token punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">COPY_SRC</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> backend</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init_buffer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">b</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">BufferUsages</span><span class="token punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">STORAGE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Dispatch the operation on the gpu.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> kernels </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GpuKernels</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_backend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">backend</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> encoder </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> backend</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">begin_encoding</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> pass </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> encoder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">begin_pass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"add_assign"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    kernels</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_assign</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> pass</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">drop</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pass</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    backend</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">submit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encoder</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Read the result (slower but convenient version).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    backend</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">slow_read_vec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>A few elements are worth noting here:</p>
<ul>
<li>Depending on the selected backend <code>GpuBackend::WebGpu</code>, <code>::Cuda</code>, or <code>::Cpu</code>, the created buffer’s underlying
type will be respectively a <code>wgpu::Buffer</code>, a <code>CudaBuffer</code>, or a simple <code>Vec</code>.</li>
<li>The <code>kernels.add_assign.call</code> function is strongly typed. For example if you changed the type of <code>a: &amp;mut [f32]</code> to
<code>a: &amp;mut [u32]</code> on the entrypoint definition, you will get a compilation error (type mismatch) at the <code>.call</code> site.
Same with const-correctness, if the shader expects <code>&amp;mut [T]</code>, you must provide a <code>&amp;mut</code> reference to your gpu
buffer to the <code>.call</code> function.</li>
<li>The <code>SPIRV_DIR</code> static constant embeds all the compiled spirv/ptx shaders in your executable. This makes it standalone, and,
in particular, simplifies serving it on the web as a single wasm file. It is also used by default by the <code>#[derive(Shader)]</code> macro for
finding and instantiating the compute pipelines.</li>
</ul>
<p>The strong typing eliminates extremely hard-to-debug bugs that would arise if there was any silent mismatch between the
gpu kernel’s inputs and your gpu buffers. This would typically arise after some refactoring or changes to the shader
entrypoint signature. Here, the compiler will prevent you from forgetting to update the <code>.call</code> function arguments.</p>
<p>The host crate also has a <code>build.rs</code> file for triggering the compilation of the shaders whenever you are
compiling your rust crate. The compilation is done by calling the <a href="https://github.com/Rust-GPU/cargo-gpu" target="_blank" rel="noopener noreferrer"><code>cargo gpu</code></a>
CLI (when targeting spirv/wgpu), or the <a href="https://github.com/dimforge/khal/tree/main/crates/cargo-cuda" target="_blank" rel="noopener noreferrer"><code>cargo cuda</code></a> CLI
when targeting PTX/Cuda. Note that we have only tested <code>cargo cuda</code> on a Windows machine for the moment. So your
experience may vary on Linux. Both executables are responsible for handling the toolchains specific to rust-gpu and
rust-cuda. You need to install them prior to compiling your shaders:</p>
<div class="language-sh codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-sh codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token plain"># Install the cargo subcommands</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cargo install cargo-gpu --version 0.10.0-alpha.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cargo install cargo-cuda</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Install the toolchains used by both commands</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cargo gpu install</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cargo cuda install</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>build.rs</code> is fairly straightforward but lacks configurability at the moment. It is responsible for running <code>cargo gpu</code>
and <code>cargo cuda</code> automatically for you:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">khal_builder</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">KhalBuilder</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Relative path to the shader crate’s directory.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> shader_crate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"../khal-example-shaders"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Relative path where the compiled spirv and ptx files will be generated.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> output_dir </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shaders-spirv"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">KhalBuilder</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shader_crate</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">output_dir</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Finally, note that the GPU resources created through <code>khal</code> aim to remain as transparent as possible: they are merely
enums containing the underlying GPU resource from the backend’s API. So you are always able to break free of <code>khal</code>’s
thin abstractions if you need more control, for example to reuse your buffers for a separate rendering library based on <code>wgpu</code>,
or to use your CUDA buffers as inputs to third-party libraries like <code>cublas</code>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="vortx-cross-platform-gpu-tensors">Vortx: cross-platform GPU tensors<a href="https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report#vortx-cross-platform-gpu-tensors" class="hash-link" aria-label="Direct link to Vortx: cross-platform GPU tensors" title="Direct link to Vortx: cross-platform GPU tensors">​</a></h2>
<center><a href="https://github.com/dimforge/vortx"><img src="https://dimforge.com/img/vortx-logo.jpg" width="50%"></a><p><a href="https://github.com/dimforge/vortx"></a><a href="https://github.com/dimforge/vortx" target="_blank" rel="noopener noreferrer">https://github.com/dimforge/vortx</a></p></center>
<p><strong>Vortx</strong> is a tensor library where each tensor can have rank up to 4 under the NCHW format (Batch/Batch/Rows/Columns).
The rank is bounded to keep the GPU-side code simpler while covering most scientific computing use-cases. It provides
simple ways to initialize tensors and manipulate their shapes. Some common general-purpose tensor operations are
provided. Keep in mind that some of these operations are not optimized as much as they could be yet.</p>
<ul>
<li><strong>componentwise operations</strong>: add, mul, sub, div, copy, inv.</li>
<li><strong>reductions</strong>: sum, product, min, max, squared norm.</li>
<li><strong>matrix multiplication</strong>: naive and tiled <code>gemm</code>.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="inferi-cross-platform-gpu-inference">Inferi: cross-platform GPU inference<a href="https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report#inferi-cross-platform-gpu-inference" class="hash-link" aria-label="Direct link to Inferi: cross-platform GPU inference" title="Direct link to Inferi: cross-platform GPU inference">​</a></h2>
<center><a href="https://github.com/dimforge/inferi"><img src="https://dimforge.com/img/inferi-logo.jpg" width="50%"></a><p><a href="https://github.com/dimforge/inferi"></a><a href="https://github.com/dimforge/inferi" target="_blank" rel="noopener noreferrer">https://github.com/dimforge/inferi</a></p></center>
<p>It turns out that implementing LLM inference is an excellent way to stress-test and benchmark linear-algebra operators,
and, in particular, all the libraries described above.
Moreover, because inference operates mostly on primitive types, it is an easy starting point without having to worry too much
about GPU/CPU data layouts (as opposed to physics that relies on a ton of more complex custom types).</p>
<p><strong>Inferi</strong> is an inference library that implements a modest number of common operators and a couple of models (namely Llama,
Qwen, and Whisper). The main objective is to explore writing inference kernels once and run them on all platforms, as opposed
to popular frameworks like <code>llama.cpp</code> and <code>candle</code> that rely on rewriting every operator again and again for each
different possible target (Metal, Cuda, Vulkan, etc.) The implementation has not been optimized too much yet, so we are
not in par with <code>llama.cpp</code> or <code>candle</code> performance-wise yet.</p>
<p><strong>Inferi</strong> comes with a web-compatible GUI application and CLI <code>inferi-chat</code> that runs inference locally
after loading a GGUF file. The <code>inferi-whisper-chat</code> CLI does the same but uses voice transcription for the user prompt.
Note that the application is mainly here for testing and demoing. Inferi is more about implementing the gpu operators
rather than creating an end-user application.</p>
<center><img src="https://dimforge.com/img/blog/2026-04-05/inferi-chat-screenshot.png" width="50%"></center>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>The Inferi codebase is still a bit messy so it might be unclear how to setup a complete inference loop from your own
project. The easiest path forward would be to look at the <code>inferi-chat</code> binary’s source code.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="how-about-physics">How about physics?<a href="https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report#how-about-physics" class="hash-link" aria-label="Direct link to How about physics?" title="Direct link to How about physics?">​</a></h2>
<p>As promised in our <a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge" target="_blank" rel="noopener noreferrer">2026 newsletter</a>, we are working on
porting to Rust-GPU the GPU physics work we started in WGSL (see
<a href="https://github.com/wgmath/wgmath/tree/main/crates/wgrapier" target="_blank" rel="noopener noreferrer">wgrapier</a>). Our current plan for Q2 is to open-source a migration of our WGSL codebase
to Khal in May and then continue improving the implementation by sharing more code with the no-std part of the Rapier and
Parry codebases.</p>
<p>But our long-term objective doesn’t  stop there: we intend to create a
full GPU multiphysics system, somewhat similar to <a href="https://github.com/Genesis-Embodied-AI/Genesis" target="_blank" rel="noopener noreferrer">Genesis</a> or
<a href="https://developer.nvidia.com/newton-physics" target="_blank" rel="noopener noreferrer">Newton</a>; all 100% in Rust thanks to Khal,
Rust-GPU, and Rust-CUDA.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="conclusion">Conclusion<a href="https://dimforge.com/blog/2026/04/05/dimforge-Q1-technical-report#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>This first quarter has been a very exciting opportunity to strengthen the foundations of our philosophy of writing
GPU code once, and have it run on most platforms (including the web). Despite just being at the beginning of this
journey, the developer-experience massively improved compared to our former experiments with WGSL and Slang. We are
looking forward to release a first version of our GPU physics engine within the next couple of months.</p>
<p>We cannot thank enough:</p>
<ul>
<li><a href="https://futurewei.com/" target="_blank" rel="noopener noreferrer">Futurewei</a> for sponsoring our work on cross-platform GPU scientific computing.</li>
<li>The maintainers of all the fantastic libraries we build on top of.</li>
</ul>
<p>Thanks to all the former, current and new sponsors! This helps us tremendously to sustain our Free and Open-Source work.
Finally, a huge thanks to the whole community and code contributors!</p>
<hr>
<p>Help us sustain our open-source work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> or by <a href="mailto:contact@dimforge.com" target="_blank" rel="noopener noreferrer"><strong>reaching out</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reviving Kiss3d - a simple 3D and 2D graphics engine]]></title>
            <link>https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine</link>
            <guid>https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine</guid>
            <pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The kiss3d crate was one of my very first projects in Rust in 2013! It is an easy-to-use 2D and 3D graphics engine for writing small demos (or even small games if you feel like it). Back in the days, there wasn’t any other easy-to-use graphics library, especially for 3D, and I needed one for showcasing my work on physics simulation; that’s why I created Kiss3d!]]></description>
            <content:encoded><![CDATA[<center><img src="https://dimforge.com/img/kiss3d-logo.png" width="500"></center>
<p>The <a href="https://kiss3d.dimforge.com/" target="_blank" rel="noopener noreferrer"><code>kiss3d</code> crate</a> was one of my very first projects in Rust in 2013! It is an easy-to-use 2D and 3D graphics engine for writing small demos (or even small games if you feel like it). Back in the days, there wasn’t any other easy-to-use graphics library, especially for 3D, and I needed one for showcasing my work on physics simulation; that’s why I created Kiss3d!</p>
<p>I paused its maintenance around 2020 when I switched to <a href="https://bevy.org/" target="_blank" rel="noopener noreferrer">Bevy</a> for the testbed of the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer">Rapier</a> physics engine. Some amazing community members helped to maintain Kiss3d since then (huge thanks to <a href="https://github.com/donkeyteethUX" target="_blank" rel="noopener noreferrer">@Alex Maiorella</a> and <a href="https://github.com/alvinhochun" target="_blank" rel="noopener noreferrer">@
alvinhochun</a> among others) but no significant activity happened since 2023.</p>
<p>Fast-forward today, the progressive complexification and frequent breaking of Bevy’s API has made it difficult to keep up and update the testbed every few months. Moreover, I needed an easier access to <code>async</code> functions and latest <code>wgpu</code> versions for experiments involving GPU computing. So it was time to switch back to <code>kiss3d</code> but with a deep refresh:</p>
<ul>
<li>It is now based of <a href="https://github.com/bitshifter/glam-rs" target="_blank" rel="noopener noreferrer"><code>glam</code></a> (or rather <a href="https://github.com/dimforge/glamx" target="_blank" rel="noopener noreferrer"><code>glamx</code></a> which is built on top of <code>glam</code>) instead of <a href="https://nalgebra.rs/" target="_blank" rel="noopener noreferrer"><code>nalgebra</code></a> to simplify its API.</li>
<li>It is based on <a href="https://github.com/gfx-rs/wgpu" target="_blank" rel="noopener noreferrer"><code>wgpu</code></a> (WebGpu) instead <a href="https://github.com/grovesNL/glow" target="_blank" rel="noopener noreferrer"><code>glow</code></a> (OpenGL) for rendering to align with community standards and for easier compatibility with advanced compute shaders.</li>
<li>It now has a unified interface when targeting native and the web (you control the <code>main</code> loop in both cases) thanks to an <code>async main</code> function, inspired from a similar approach in <a href="https://macroquad.rs/" target="_blank" rel="noopener noreferrer">macroquad</a>.</li>
<li>Many of the functions for manipulating scene nodes have been renamed to something simpler. (For example <code>append_local_translation</code> is renamed <code>translate</code>).</li>
<li>Addition of a few convenience and performance-oriented features like support for <a href="https://www.kiss3d.dimforge.com/examples#ui" target="_blank" rel="noopener noreferrer">egui</a>,  <a href="https://www.kiss3d.dimforge.com/examples#instancing3d" target="_blank" rel="noopener noreferrer">instancing</a> and <a href="https://www.kiss3d.dimforge.com/examples#polylines" target="_blank" rel="noopener noreferrer">polylines rendering</a>. <em>(Disclaimer: you might notice that the polyline demo is strongly inspired from a similar demo in <a href="https://github.com/ForesightMiningSoftwareCorporation/bevy_polyline" target="_blank" rel="noopener noreferrer">bevy_polyline</a>)</em></li>
<li>Added support for multiple lights.</li>
</ul>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-1" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-1.png" width="300" title="3D primitives" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">3D primitives</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-2" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-2.png" width="300" title="Multiple lights" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Multiple lights</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-4" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-4.png" width="300" title="Meshes, lines, points" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Meshes, lines, points</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-5" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-5.png" width="300" title="Obj and textures" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Obj and textures</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-6" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-6.png" width="300" title="Post-processing effects" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Post-processing effects</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-7" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-7.png" width="300" title="Instancing 10.000 2D rectangles" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Instancing 10.000 2D rectangles</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-8" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-8.png" width="300" title="Instancing 1.000.000 3D cubes" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Instancing 1.000.000 3D cubes</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-9" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-9.png" width="300" title="3D Polylines" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">3D Polylines</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-10" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-10.png" width="300" title="egui support" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">egui support</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="lightbox-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-1.png" alt="3D primitives" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-2.png" alt="Multiple lights" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-4" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-4.png" alt="Meshes, lines, points" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-5" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-5.png" alt="Obj and textures" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-6" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-6.png" alt="Post-processing effects" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-7" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-7.png" alt="Instancing 10.000 2D rectangles" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-8" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-8.png" alt="Instancing 1.000.000 3D cubes" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-9" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-9.png" alt="3D Polylines" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="lightbox-10" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-10.png" alt="egui support" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<p>The <code>kiss3d</code> graphics engine is cross-platform (including the web) and aims to remain simple to use. It does not support Android/iOS yet, but we are planning on it. It is based on a scene tree to describe the rendering scene. You keep total control over <code>main</code> and the render loop and ou don’t need to fit everything into a new paradigm like ECS: you organize your data however you want, arrange your function calls yourself (no complex system scheduling declarations). Rendering simple primitives and meshes only takes a few of lines of code to get you started quickly. The following shows how you render a 3D cube and get an interactive camera supporting mouse controls:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">kiss3d</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">prelude</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[kiss3d::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> window </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Window</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Kiss3d: cube"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> camera </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">OrbitCamera3d</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> scene </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SceneNode3d</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">empty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    scene</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add_light</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Light</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">point</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">100.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_position</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> cube </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> scene</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add_cube</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_color</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">RED</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> rot </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Quat</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_axis_angle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Vec3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.014</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// axis-angle in radians</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">render_3d</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> scene</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> camera</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        cube</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rotate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rot</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The 2D equivalent follows the same logic:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">kiss3d</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">prelude</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[kiss3d::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> window </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Window</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Kiss3d: rectangle"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> camera </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">PanZoomCamera2d</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Vec2</span><span class="token punctuation" style="color:#393A34">::</span><span class="token constant" style="color:#36acaa">ZERO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> scene </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SceneNode2d</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">empty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> cube </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> scene</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add_rectangle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">100.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">150.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set_color</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">RED</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> rot </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.014</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// radians</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">render_2d</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> scene</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> camera</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        cube</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rotate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rot</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Check out the source-code of all the examples <a href="https://github.com/dimforge/kiss3d/tree/master/examples" target="_blank" rel="noopener noreferrer">on github</a>. You may also interact with some of them with the <a href="https://www.kiss3d.dimforge.com/examples" target="_blank" rel="noopener noreferrer">online demos</a> compiled to WASM (your browser needs to support WebGpu).
Refer to <code>kiss3d</code>’s <a href="https://github.com/dimforge/kiss3d/blob/master/CHANGELOG.md#v0390" target="_blank" rel="noopener noreferrer">CHANGELOG</a> for detailed information about these breaking changes.</p>
<p>Unfortunately, I have since then lost control over the <em>kiss3d.org</em> domain name. The (new!) website is now hosted at <a href="https://kiss3d.dimforge.com/" target="_blank" rel="noopener noreferrer">https://kiss3d.dimforge.com</a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="acknowledgements">Acknowledgements<a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#acknowledgements" class="hash-link" aria-label="Direct link to Acknowledgements" title="Direct link to Acknowledgements">​</a></h2>
<p>We hope that reviving Kiss3d will help fill a gap in the Rust community for users needing a simple graphics engine with a lower learning curve.</p>
<p>Thanks to all the former, current and new supporters through GitHub sponsors! This helps us tremendously to sustain our Free and Open-Source work. Finally, a huge thanks to the whole community and code contributors!</p>
<p>Help us sustain our open-source work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> or by <a href="mailto:contact@dimforge.com" target="_blank" rel="noopener noreferrer"><strong>reaching out</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Rapier physics engine 2025 review and 2026 goals]]></title>
            <link>https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge</link>
            <guid>https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge</guid>
            <pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[🎊🎊🎊 Happy new year 2026 everyone! 🎊🎊🎊]]></description>
            <content:encoded><![CDATA[<p><strong>🎊🎊🎊 Happy new year 2026 everyone! 🎊🎊🎊</strong></p>
<p>This article summarizes the most significant additions made in 2025 to our open-source crates
for geometry and physics simulation that we develop for the Rust community. We also present our
main objectives for 2026.</p>
<p><img decoding="async" loading="lazy" alt="rapier logo" src="https://dimforge.com/assets/images/rapier_logo_color_textpath_dark-67093214cb8594cb6bf7b952ff3e3027.svg" width="527" height="131" class="img_XsDP"></p>
<p>It has been way too long since our last communication! We were deep into experiments and reflexions on the future of Rapier and our upcoming technological choices.
In this article, we will be reviewing what notable work has been done on Rapier in 2025 and our envisioned priorities for 2026:</p>
<ol>
<li><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#a-focus-on-performance-improvements">A focus on performance improvements</a></li>
<li><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#an-unexpected-turn-of-events-the-glam-migration">An unexpected turn of events: the <code>glam</code> migration</a></li>
<li><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#a-new-small-crate-glamx">A new small crate: <code>glamx</code></a></li>
<li><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgsl-and-slang-cross-platform-gpu-physics-exploration">WGSL and Slang: cross-platform GPU physics exploration</a></li>
<li><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#next-steps-for-2026-robotics-and-gpu-physics-with-rust-gpu">Next steps for 2026: robotics and GPU computing</a></li>
</ol>
<p>We are also finally resuming maintenance of the <a href="https://kiss3d.dimforge.com/" target="_blank" rel="noopener noreferrer">kiss3d</a> graphics engine. Check out our <a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine">dedicated blog post on kiss3d</a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="a-focus-on-performance-improvements">A focus on performance improvements<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#a-focus-on-performance-improvements" class="hash-link" aria-label="Direct link to A focus on performance improvements" title="Direct link to A focus on performance improvements">​</a></h2>
<p>Rapier’s main focus for 2025 was performance improvements. Especially on web browser through WASM and its JavaScript bindings <a href="https://github.com/dimforge/rapier.js" target="_blank" rel="noopener noreferrer">rapier.js</a>. The main highlights are:</p>
<ul>
<li>A  <strong>new BVH</strong> implementation (<a href="https://github.com/dimforge/parry/pull/361" target="_blank" rel="noopener noreferrer">parry#361</a>). This new Dynamic BVH supports efficient automatic rebalancing and SIMD-accelerated tree traversals. It is used in Rapier for both scene queries (ray-casting, point projection, etc) and the broad-phase. This eliminates the need to maintain two separate acceleration structures as it also replaces the older broad-phase based on a Hierarchical Sweep-and-Prune algorithm.</li>
<li>A <strong>collider for sparse voxels</strong> (<a href="https://github.com/dimforge/parry/pull/336" target="_blank" rel="noopener noreferrer">parry#336</a>). To our knowledge, Rapier is the first general-purpose rigid-body physics engine to support voxels explicitly. A dedicated collider offers several advantages compared to alternatives like making a surface mesh or using compound colliders made of cubes: lower memory footprint (each voxel size is close to a single <code>u8</code>), no <a href="https://box2d.org/posts/2020/06/ghost-collisions/" target="_blank" rel="noopener noreferrer">ghost collisions</a>, and efficient collision detection through automatic blocks grouping.</li>
</ul>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:508px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#voxels-1" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/voxels2d.png" width="500" title="2D voxels and primitives" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">2D voxels and primitives</div></div><div style="padding:4px;text-align:center;width:508px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#voxels-2" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/voxels3d.png" width="500" title="3D voxels and primitives" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">3D voxels and primitives</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="voxels-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/voxels2d.png" alt="2D voxels and primitives" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="voxels-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/voxels3d.png" alt="3D voxels and primitives" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<ul>
<li><strong>Persistent islands</strong> (<a href="https://github.com/dimforge/rapier/pull/895" target="_blank" rel="noopener noreferrer">rapier#895</a>). By persisting simulation islands across frames, we avoid re-extraction of all the collision graph’s connected components at each frame. While this reduces significantly the computational cost of handling islands, this will also help with future performance improvements on the constraints solver.</li>
<li><strong>Manifold reduction</strong> (<a href="https://github.com/dimforge/rapier/pull/895" target="_blank" rel="noopener noreferrer">rapier#895</a>). This ensures all contact manifolds handled by the constraint solver never have more than 4 contacts. This simplifies the solver code.</li>
<li><strong>Simplified 3D friction model</strong> (<a href="https://github.com/dimforge/rapier/pull/876" target="_blank" rel="noopener noreferrer">rapier#876</a>). This reduces the number of constraints the solver has to solve in 3D for contact manifold involving at least two contacts. This resulted in a 25% speedup on scenes involving many contacts (like large stacks).</li>
<li><strong>New simd-accelerated NPM packages</strong>. Before, the only NPM packages we published for the WASM/JS version of Rapier didn’t have SIMD optimizations enabled. Since modern browser are starting to offer stable implementation of SIMD in wasm, we have built and published additional SIMD-accelerated packages for Rapier (for example <a href="https://www.npmjs.com/package/@dimforge/rapier3d-simd" target="_blank" rel="noopener noreferrer">@dimforge/rapier3d-simd</a>).</li>
</ul>
<p>With all these improvements combined, on the web, the fastest Rapier NPM package you can use today is now between 2x and 5x faster than the faster Rapier NPM package you could use in 2024 (v0.24.0). The performance gains on native is more moderate considering that SIMD-acceleration has always been available there.
The graphs below illustrate some of the performance gain compared to the last version form 2024 (0.23.0, blue curve) compared to 0.32 (red curve), both running on native with the <code>simd-stable</code> feature enabled. The new version is up to 2x faster than a year before.</p>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-1" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/bench1.png" width="300" title="8000 balls" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">8000 balls</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-2" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/bench2.png" width="300" title="19.800 spherical joints" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">19.800 spherical joints</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-5" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/bench5.png" width="300" title="8000 revolute joints" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">8000 revolute joints</div></div></div><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-3" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/bench3.png" width="300" title="Falling stacks of 3027 cubes" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Falling stacks of 3027 cubes</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-4" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/bench4.png" width="300" title="Single tower made of 5320 planks" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">Single tower made of 5320 planks</div></div><div style="padding:4px;text-align:center;width:308px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-6" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/bench6.png" width="300" title="40 pyramids with 210 cubes each" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">40 pyramids with 210 cubes each</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="bench-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/bench1.png" alt="8000 balls" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="bench-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/bench2.png" alt="19.800 spherical joints" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="bench-5" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/bench5.png" alt="8000 revolute joints" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="bench-3" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/bench3.png" alt="Falling stacks of 3027 cubes" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="bench-4" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/bench4.png" alt="Single tower made of 5320 planks" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="bench-6" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/bench6.png" alt="40 pyramids with 210 cubes each" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="an-unexpected-turn-of-events-the-glam-migration">An unexpected turn of events: the <code>glam</code> migration<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#an-unexpected-turn-of-events-the-glam-migration" class="hash-link" aria-label="Direct link to an-unexpected-turn-of-events-the-glam-migration" title="Direct link to an-unexpected-turn-of-events-the-glam-migration">​</a></h2>
<p>Starting with <strong>rapier 0.32</strong> and <strong>parry 0.26</strong>, most of their API and internals using the <a href="https://crates.io/crates/nalgebra" target="_blank" rel="noopener noreferrer">nalgebra</a> linear algebra library have been modified to use <a href="https://crates.io/crates/glam" target="_blank" rel="noopener noreferrer">glam</a> instead. This is significant change motivated by two key factors:</p>
<ol>
<li>The gaming and graphics communities are increasingly adopting <code>glam</code> for linear algebra. Which makes sense due to its simpler API and lower leaning curve.</li>
<li>The <a href="https://github.com/Rust-GPU/rust-gpu" target="_blank" rel="noopener noreferrer">rust-gpu</a> compiler backend has first-class support of <code>glam</code>. Unfortunately <code>nalgebra</code> internals are too complex for it to be compiled with <code>rust-gpu</code> (at least currently).</li>
</ol>
<p>So our goal is to make Rapier easier to learn and use, and to allow us to reuse a substantial amount of code for a future GPU version of Rapier based on <code>rust-gpu</code> (we’ll detail the GPU story more in <a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgsl-and-slang-cross-platform-gpu-physics-exploration">one of the next sections below</a>). While <code>parry 0.26</code> no longer has any dependency to <code>nalgebra</code>, <code>rapier</code> continues to use <code>nalgebra</code> internally in two situations where <code>glam</code> falls short:</p>
<ul>
<li>For the multibody implementation that requires a unique combination dynamically-sized matrices and fixed-size vectors (varying between 1D and 6D) and slices. These are both strong features of <code>nalgebra</code>.</li>
<li>For the AoSoA (Array-of-Struct-of-Array) SIMD internal optimizations of the constraints solver. <code>nalgebra</code>’s generics wrt. the scalar type and abstractions based on <a href="https://crates.io/crates/simba" target="_blank" rel="noopener noreferrer"><code>simba</code></a> make it an obvious choice.</li>
</ul>
<p>Overall, this is not a "one crate is better than the other" situation. We simply aim to use what we feel is the best tool for each job: <code>glam</code> for its simplicity for 2D and 3D math and for its compatibility with rust-gpu (which just doesn’t work with <code>nalgebra</code> right now); and <code>nalgebra</code> for its genericity on matrix dimensions and scalar types when it’s needed.</p>
<p>Both usages of <code>nalgebra</code> are mostly internal, so 99% of the public API is <code>glam</code>-based.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="impact-on-performances">Impact on performances<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#impact-on-performances" class="hash-link" aria-label="Direct link to Impact on performances" title="Direct link to Impact on performances">​</a></h4>
<p>One very interesting aspect of this migration is that you rarely see comparative benchmarks between linear-algebra libraries in large-scale projects. Usually, you only see micro-benchmarks like <a href="https://github.com/bitshifter/mathbench-rs" target="_blank" rel="noopener noreferrer">mathbench</a> that might not be representative of the actual results you would get in a real-life project.</p>
<p>So we were naturally very curious on what performance impact this change would have! And it turned out that… <strong>nothing changed</strong>, at all (measured on a Macbook Pro M4 Max). All our stress-test scenes ended up with the same performances as before (within margin of error). The only measurable difference we observed was a ~10% slowdown when using glam’s <code>Vec3A</code> type instead of <code>Vec3</code>, so we picked <code>Vec3</code>.</p>
<p>This shows that despite its internal complexity, the compiler manages to optimize <code>nalgebra</code> just as well as <code>glam</code> in our codebase. However, in debug runs, the new <code>glam</code> version tends to be around 20% faster, likely due to fewer indirections when the compiler does not inline.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="impact-on-the-community">Impact on the community<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#impact-on-the-community" class="hash-link" aria-label="Direct link to Impact on the community" title="Direct link to Impact on the community">​</a></h4>
<p>If you are currently using <code>rapier</code> or <code>parry</code>, you are likely in one of three situations:</p>
<ul>
<li>You entire codebase already relies on <code>glam</code>. Then, good news, you no longer need to convert from <code>glam</code> no <code>nalgebra</code> when interacting with <code>rapier/parry</code>.</li>
<li>Your entire codebase relies on neither <code>glam</code> nor <code>nalgebra</code>. Then, not much is changing for you: just convert your types to <code>glam</code> instead of converting to <code>nalgebra</code>.</li>
<li>Your entire codebase relies on <code>nalgebra</code>. Then, keep in mind that <a href="https://github.com/dimforge/glamx" target="_blank" rel="noopener noreferrer"><code>glamx</code></a> and <code>nalgebra</code> implement type conversions (with the <code>Into/From</code> traits) between <code>nalgebra</code> and <code>glam</code>. Simply enable the <em>nalgebra</em> feature of the <code>glamx</code> crate. This will allow you to convert types between both linear algebra libraries when interacting with the newest <code>rapier/parry</code> version. We have checked with high-profile users (like the fantastic <a href="https://github.com/FyroxEngine/Fyrox" target="_blank" rel="noopener noreferrer">Fyrox</a> game engine) and got feedbacks that this is a generally acceptable approach.</li>
</ul>
<p>If you are experiencing difficulties with this migration, please don’t hesitate to reach out!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="a-new-small-crate-glamx">A new small crate: <code>glamx</code><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#a-new-small-crate-glamx" class="hash-link" aria-label="Direct link to a-new-small-crate-glamx" title="Direct link to a-new-small-crate-glamx">​</a></h2>
<p>The <a href="https://github.com/dimforge/glamx" target="_blank" rel="noopener noreferrer"><code>glamx</code> crate</a> (meaning <em>glam eXtensions</em>), provides a few features that are absent from <code>glam</code> but essential for geometry and physics:</p>
<ul>
<li><code>Pose2</code>, <code>Pose3</code> for 2D and 3D poses (rotations + translation). Also known as <code>Isometry2</code> and <code>Isometry3</code> in <code>nalgebra</code>.</li>
<li><code>Rot2</code> for 2D rotations. Glam already supports 3D rotations with <code>Quat</code>.</li>
<li><code>MatExt</code> for additional operation of 2D and 3D matrices. In particular, this implements SVD and eigendecomposition of
symmetric matrices.</li>
<li>An optional feature named <code>nalgebra</code> for converting between <code>glam/glamx</code> types and <code>nalgebra</code> types.</li>
</ul>
<p>It aims to keep its API simple and with no generics, in the same spirit as <code>glam</code>. It also re-exports every types from <code>glam</code> so you can simply use, e.g., <code>glamx::Vec3</code> instead of dealing with two crate names everywhere. It is being used by <code>parry</code>, <code>rapier</code>, and <a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine"><code>kiss3d</code></a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="wgsl-and-slang-cross-platform-gpu-physics-exploration">WGSL and Slang: cross-platform GPU physics exploration<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgsl-and-slang-cross-platform-gpu-physics-exploration" class="hash-link" aria-label="Direct link to WGSL and Slang: cross-platform GPU physics exploration" title="Direct link to WGSL and Slang: cross-platform GPU physics exploration">​</a></h2>
<p>Our second big focus for 2025 was experimenting with various approaches for cross-platform GPU scientific computing in Rust. We have explored (at varying depths) multiple options:</p>
<ul>
<li><a href="https://www.w3.org/TR/WGSL/" target="_blank" rel="noopener noreferrer">WGSL</a> is the shading language behind WebGpu. This is shading the language most Rust graphics/game engines based on <a href="https://wgpu.rs/" target="_blank" rel="noopener noreferrer">wgpu</a> are using. The <a href="https://wesl-lang.dev/" target="_blank" rel="noopener noreferrer">WESL</a> initiative aims to provide extensions and tooling around WGSL to make it more developer-friendly (e.g. with a module system).</li>
<li><a href="https://shader-slang.org/" target="_blank" rel="noopener noreferrer">Slang</a> is both a shading language and a compiler for that language. You write your Slang shader once, and its compiler transforms it into your platform-specific shader (HLSL, Metal, SpirV, PTX, etc). While this project has been around since 2017 under the Nvidia umbrella, it has been transferred to Khronos in <a href="https://www.khronos.org/news/press/khronos-group-launches-slang-initiative-hosting-open-source-compiler-contributed-by-nvidia" target="_blank" rel="noopener noreferrer">November 2024</a>.</li>
<li><a href="https://github.com/tracel-ai/cubecl" target="_blank" rel="noopener noreferrer">CubeCL</a> is a procedural-macro-based system for compiling Rust code to the GPU without needing a nightly compiler. This can be seen as writing shaders with a Rust-based DSL rather than regular Rust code as many of the idiomatic Rust language features are not available in CubeCL shaders.</li>
<li><a href="https://rust-gpu.github.io/" target="_blank" rel="noopener noreferrer">rust-gpu</a> is as compiler backend for compiling regular (no-std) Rust code to SpirV. A similar project, <a href="https://github.com/Rust-GPU/rust-cuda" target="_blank" rel="noopener noreferrer">rust-cuda</a>, does the same but targeting CUDA. Rust-gpu has a troubled past. Originally created by <a href="https://www.embark-studios.com/" target="_blank" rel="noopener noreferrer">Embark Studio</a> it has then been abandoned as Embark revisited their priorities. It has then been maintained by the community, some of the maintainers now involved with <a href="https://www.vectorware.com/blog/announcing-vectorware/" target="_blank" rel="noopener noreferrer">VectorWare</a> which aims to build GPU-native applications in Rust.</li>
</ul>
<p><strong>Long story short</strong>, we started with WGSL, switched to Slang, and are now settling with rust-gpu! The experiments with CubeCL were short as we’ve hit very difficult-to-navigate limitations of the subset of Rust language features that actually compile.</p>
<p>We have built quite an ecosystem with WGSL. This ecosystem codename is <a href="https://wgmath.rs/" target="_blank" rel="noopener noreferrer">wgmath</a>. In particular, we have a fully working implementation of a subset of Rapier running on any GPU, even in the browser. <a href="https://github.com/wgmath/wgmath/tree/main/crates/wgrapier" target="_blank" rel="noopener noreferrer">wgrapier</a> includes for example a BVH-based broad-phase and modern Soft-TGS constraint solver all running on the GPU. You can try it out at the links below (you will get different performance depending on your browser/platform. See more details on the <a href="https://github.com/wgmath/wgmath/tree/main/crates/wgrapier#web-performance-notes" target="_blank" rel="noopener noreferrer">wgrapier README</a>):</p>
<ul>
<li><a href="https://wgmath.rs/demos/wgrapier2d/index.html" target="_blank" rel="noopener noreferrer">https://wgmath.rs/demos/wgrapier2d/index.html</a></li>
<li><a href="https://wgmath.rs/demos/wgrapier3d/index.html" target="_blank" rel="noopener noreferrer">https://wgmath.rs/demos/wgrapier3d/index.html</a></li>
</ul>
<div style="margin:0 auto 1rem"><div style="display:flex;justify-content:center;flex-wrap:wrap"><div style="padding:4px;text-align:center;width:508px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgrapier-1" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/wgrapier3d-1.png" width="500" title="93.000 bodies and 120.000 joints" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">93.000 bodies and 120.000 joints</div></div><div style="padding:4px;text-align:center;width:508px"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgrapier-2" style="cursor:pointer;display:block"><img src="https://dimforge.com/img/blog/2026-01-09/wgrapier3d-2.png" width="500" title="stack of 34.000 planks" style="display:block"></a><div style="margin-top:4px;margin-bottom:12px">stack of 34.000 planks</div></div></div></div><style>
    .lightbox-target:target {
      opacity: 1 !important;
      pointer-events: auto !important;
    }
  </style><div id="wgrapier-1" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/wgrapier3d-1.png" alt="93.000 bodies and 120.000 joints" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div><div id="wgrapier-2" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;pointer-events:none;transition:opacity 0.3s" class="lightbox-target"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:0;left:0;width:100%;height:100%"></a><img src="https://dimforge.com/img/blog/2026-01-09/wgrapier3d-2.png" alt="stack of 34.000 planks" style="max-width:90%;max-height:90%;position:relative;z-index:1;cursor:pointer"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#" style="position:absolute;top:20px;right:30px;font-size:40px;color:white;text-decoration:none;z-index:2">×</a></div>
<p>We have also built an MPM (Material Point Method) simulation library in WGSL named <a href="https://github.com/dimforge/wgsparkl" target="_blank" rel="noopener noreferrer">wgsparkl</a>. You can try it there (the same performance notes from the  <a href="https://github.com/wgmath/wgmath/tree/main/crates/wgrapier#web-performance-notes" target="_blank" rel="noopener noreferrer">wgrapier README</a> are applicable too):</p>
<ul>
<li><a href="https://wgmath.rs/demos/wgsparkl2d/index.html" target="_blank" rel="noopener noreferrer">https://wgmath.rs/demos/wgsparkl2d/index.html</a></li>
<li><a href="https://wgmath.rs/demos/wgsparkl3d/index.html" target="_blank" rel="noopener noreferrer">https://wgmath.rs/demos/wgsparkl3d/index.html</a></li>
</ul>
<center><img src="https://dimforge.com/img/blog/2026-01-09/wgsparkl2d.png" width="650"></center>
<p>Unfortunately, WGSL is a verry annoying language to work with for advanced mathematics! It lacks a solid module system, and the supported language features are extremely basic. While <a href="https://github.com/bevyengine/naga_oil" target="_blank" rel="noopener noreferrer">naga-oil</a> or <a href="https://wesl-lang.dev/" target="_blank" rel="noopener noreferrer">WESL</a> make it a bit easier, it remains too limited to reach a pleasing development experience like we are used to in Rust. Moreover, WGSL is tied to the WebGpu standard which significantly reduces chances of ever targeting native-only APIs like CUDA.</p>
<p>Next, we tried <a href="https://shader-slang.org/" target="_blank" rel="noopener noreferrer">Slang</a>. Much nicer to work with than WGSL, supports high-level constructs like generics, albeit with more C++ flavors than we would like. Its main pain points are the lack of ecosystem in Rust (aside for the <a href="https://crates.io/crates/shader-slang" target="_blank" rel="noopener noreferrer">shader-slang</a> compiler bindings), poor IDE support (with RustRover), and the fact that the Slang compiler is written in C++, making it more difficult to integrate with Rust (dylib handling or static linking, bindings, etc). The <a href="https://github.com/shader-slang/slang-rhi" target="_blank" rel="noopener noreferrer">slang-rhi</a> library (think <code>wgpu</code> but for Slang) is also a C++ library so we made <a href="https://github.com/dimforge/slang-hal" target="_blank" rel="noopener noreferrer">our own slang-hal</a> which is both very limited and way too much work to maintain/improve. At the end of the day, we ported wgsparkl to Slang under the project name <a href="https://github.com/dimforge/slosh" target="_blank" rel="noopener noreferrer">Slosh</a>. The code is much nicer than the WGSL version, but still not quite there yet due to constant friction between Slang and Rust. We are still working actively on Slosh but are aiming to transition it to <code>rust-gpu</code> eventually.</p>
<p>Finally, there is <a href="https://github.com/Rust-GPU/rust-gpu" target="_blank" rel="noopener noreferrer">rust-gpu</a>. This should technically solve all the aforementioned limitations/friction: you can write your <em>no-std</em> GPU code directly in Rust with most of its high-level language features and Cargo package management, but you are not limited to WebGPU. With some extra indirections, CUDA could also be targeted through <a href="https://github.com/Rust-GPU/Rust-CUDA" target="_blank" rel="noopener noreferrer">rust-cuda</a> sharing most of the same code. Finally, you can imagine libraries like Parry and Rapier being refactored in such a way that both CPU and GPU versions can share a non-negligible amount of code, reducing risks of bugs and making maintenance much easier. The migration of Parry and Rapier to glam was the first, and necessary, step towards that goal.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="next-steps-for-2026-robotics-and-gpu-physics-with-rust-gpu">Next steps for 2026: robotics and GPU physics with rust-gpu<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#next-steps-for-2026-robotics-and-gpu-physics-with-rust-gpu" class="hash-link" aria-label="Direct link to Next steps for 2026: robotics and GPU physics with rust-gpu" title="Direct link to Next steps for 2026: robotics and GPU physics with rust-gpu">​</a></h2>
<p>As far as Rapier and Parry are concerned, we have two major goals for 2026:</p>
<ol>
<li>Improving Rapier’s features and accuracy for robotics.</li>
<li>Cross-platform GPU rigid-body physics based on <code>rust-gpu</code>.</li>
</ol>
<p>While Rapier already has some features geared towards robotics like the support for multibody joints (using the reduced-coordinates formalism), URDF file import (with the <a href="https://crates.io/crates/rapier3d-urdf" target="_blank" rel="noopener noreferrer">rapier3d-urdf</a> crate), and <a href="https://github.com/dimforge/rapier/pull/632" target="_blank" rel="noopener noreferrer">inverse kinematics</a>, we still have a long road ahead of us:</p>
<ul>
<li>The multibody implementation needs some love as there are several outstanding known bugs and limitations reported by the community. It could use some numerical stability and performance improvements as well.</li>
<li>A new, more accurate constraints solver needs to be implemented for robotics use-cases.</li>
<li>Overall, we will be taking heavy inspiration from <a href="https://mujoco.org/" target="_blank" rel="noopener noreferrer">Mujoco</a> to identify the features we need for robotics simulation. Though we will ensure it doesn’t impact the performances of game applications that doesn’t require that much accuracy.</li>
</ul>
<p>Regarding cross-platform GPU rigid-body physics, we will apply the knowledge we obtained from the wgrapier WGSL experiment for making a version based on <code>rust-gpu</code>, with a systematic attempt to share as much code as possible with <code>rapier</code> itself. In particular, we envision sharing type definitions and fundamental numeric and geometric operations.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="conclusion">Conclusion<a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>The year 2025 has been very exciting; full of experiments on GPU computing, while at the same time making significant improvements to Rapier’s performances. We are also glad to get back to writing a bit about what we are working on, considering that it’s been way too long since our last communication! Hopefully, now that the technological choices and path forward are clear, we will be in a good position to provide more regular updates.</p>
<p>We cannot thank enough:</p>
<ul>
<li><a href="https://futurewei.com/" target="_blank" rel="noopener noreferrer">Futurewei</a> for sponsoring our work on cross-platform GPU scientific computing.</li>
<li><a href="https://hytopia.com/" target="_blank" rel="noopener noreferrer">Hytopia</a> for sponsoring most of the performance improvements on Rapier.</li>
<li><a href="https://fslabs.ca/" target="_blank" rel="noopener noreferrer">Foresight Spatial Labs</a> for contributing to the development of Slosh.</li>
</ul>
<p>Thanks to all the former, current and new sponsors! This helps us tremendously to sustain our Free and Open-Source work.<br>Finally, a huge thanks to the whole community and code contributors!</p>
<hr>
<p>Help us sustain our open-source work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> or by <a href="mailto:contact@dimforge.com" target="_blank" rel="noopener noreferrer"><strong>reaching out</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The year 2022 in Dimforge and our objectives for 2023]]></title>
            <link>https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge</link>
            <guid>https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge</guid>
            <pubDate>Sun, 22 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[🎊🎊🎊 Happy new year 2023 everyone! 🎊🎊🎊]]></description>
            <content:encoded><![CDATA[<p><strong>🎊🎊🎊 Happy new year 2023 everyone! 🎊🎊🎊</strong></p>
<p>This article summarizes the most significant additions made in 2022 to our open-source crates
for linear-algebra and physics simulation that we develop for the Rust community. We also present our
main objectives for 2023.</p>
<p>Help us sustain our open-source work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>
<p><img decoding="async" loading="lazy" alt="rapier logo" src="https://dimforge.com/assets/images/rapier_logo_color_textpath_dark-67093214cb8594cb6bf7b952ff3e3027.svg" width="527" height="131" class="img_XsDP"></p>
<p>Rapier is a 2D and 3D physics engine for games, robotics, and animation written in Rust. Our
<a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge">goal for 2022</a> was to
work on the missing <em>high-level</em> features of Rapier. This month we released the version <code>0.17</code> of Rapier with significant feature additions since the version <code>0.12</code> released in January 2022:</p>
<ul>
<li>The addition of a <a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#kinematic-character-controller"><strong>kinematic character controller</strong></a>.</li>
<li>The addition of a <a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#dynamic-vehicle-controller"><strong>dynamic vehicle controller</strong></a>.</li>
<li>The addition of a <a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#debug-renderer"><strong>generic debug-renderer</strong></a>.</li>
<li>The exploration of <a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#exploring-destructible-voxel-based-physics"><strong>destructible voxel-based physics</strong></a>.</li>
<li>The significant improvement of the <a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#bevy-rapier-ergonomics-improvements"><strong>ergonomics of bevy-rapier</strong></a>.</li>
<li>The fix of the <strong>internal edges problem</strong> in 3D: flat meshes no longer cause unexpected bumps when something slides
or rolls on it.</li>
</ul>
<p>We were also amazed to see Rapier being used by <a href="https://www.resolutiongames.com/" target="_blank" rel="noopener noreferrer">Resolution Games</a> for one of their latest VR multiplayer game: <a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#game-highlight-ultimechs"><strong>Ultimechs</strong></a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="kinematic-character-controller">Kinematic character controller<a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#kinematic-character-controller" class="hash-link" aria-label="Direct link to Kinematic character controller" title="Direct link to Kinematic character controller">​</a></h2>
<center><video width="560" controls=""><source src="/vids/character-controller-3d.mp4" type="video/mp4"><p>Your browser does not support the video tag.</p></video></center>
<p>We added a <a href="https://rapier.rs/docs/user_guides/rust/character_controller" target="_blank" rel="noopener noreferrer">kinematic character controller</a> to Rapier
(as well as <a href="https://rapier.rs/docs/user_guides/bevy_plugin/character_controller" target="_blank" rel="noopener noreferrer"><code>bevy-rapier</code></a> and the
<a href="https://rapier.rs/docs/user_guides/javascript/character_controller" target="_blank" rel="noopener noreferrer">JS bindings</a> for rapier). The character
controller was designed mostly with platformers in mind, supporting the following operations:</p>
<ul>
<li>Slide on uneven terrains.</li>
<li>Interaction with dynamic bodies.</li>
<li>Climb stairs automatically.</li>
<li>Automatically snap the body to the floor when going downstairs.</li>
<li>Prevent sliding up slopes that are too steep.</li>
<li>Prevent sliding down slopes that are not steep enough.</li>
<li>Interactions with moving platforms.</li>
<li>Report information about the obstacles it hit on its path.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="dynamic-vehicle-controller">Dynamic vehicle controller<a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#dynamic-vehicle-controller" class="hash-link" aria-label="Direct link to Dynamic vehicle controller" title="Direct link to Dynamic vehicle controller">​</a></h2>
<center><video width="560" controls=""><source src="/vids/vehicle-controller-3d.mp4" type="video/mp4"><p>Your browser does not support the video tag.</p></video></center>
<p>A <a href="https://docs.rs/rapier3d/0.17.1/rapier3d/control/struct.DynamicRayCastVehicleController.html" target="_blank" rel="noopener noreferrer">dynamic vehicle controller</a>
was also a very popular feature request. We ported to Rust the vehicle controller from the
<a href="https://github.com/bulletphysics/bullet3" target="_blank" rel="noopener noreferrer">Bullet</a> physics engine, and integrated it to Rapier. This
vehicle controller is based on ray-casting (one ray per wheel) to detect the ground. It simulates wheel friction,
suspension, and braking.</p>
<div class="theme-admonition theme-admonition-note admonition_v1XZ alert alert--secondary"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_nS2X"><p>Dynamic vehicle controllers are only usable with the main Rapier crates (<code>rapier2d, rapier3d, rapier2d-f64, rapier3d-f64</code>). It is not integrated yet into <code>bevy-rapier</code> and it is not usable yet with the JS bindings either.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="debug-renderer">Debug renderer<a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#debug-renderer" class="hash-link" aria-label="Direct link to Debug renderer" title="Direct link to Debug renderer">​</a></h2>
<center><img src="https://dimforge.com/img/debug-render.png" alt="Foresight Mining Software Corporation" width="560"></center>
<p>We added a debug-renderer to let the user see the scene as is actually seen by the physics engine, in order to easily
spot common mistakes on objects dimentions and placements relative to their game assets.</p>
<p>Despite its name, Rapier’s debug-renderer doesn’t actually draw anything to the screen directly (except
for the <a href="https://docs.rs/bevy_rapier3d/0.20.0/bevy_rapier3d/render/struct.RapierDebugRenderPlugin.html" target="_blank" rel="noopener noreferrer"><code>RapierDebugRenderPlugin</code></a>
of <code>bevy-rapier</code> which actually draws lines using Bevy’s rendering capabilities).
Instead, the user is responsible for providing a method to draw lines using their favorite graphics engine. The <a href="https://docs.rs/rapier3d/0.17.1/rapier3d/pipeline/struct.DebugRenderPipeline.html" target="_blank" rel="noopener noreferrer"><code>DebugRenderPipeline</code></a>
simply returns the lines that need to be rendered. This makes it very easy to integrate to any game engine for quick physics debugging!</p>
<p>In JS, the lines to draw can be obtained with <code>World.debugRender()</code> which returns the vertex buffer and color
buffer to render. See <a href="https://github.com/dimforge/rapier.js/pull/119" target="_blank" rel="noopener noreferrer">rapier.js#119</a> for integration examples with THREE.js,
PIXI, and PlayCanvas.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="exploring-destructible-voxel-based-physics">Exploring destructible voxel-based physics<a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#exploring-destructible-voxel-based-physics" class="hash-link" aria-label="Direct link to Exploring destructible voxel-based physics" title="Direct link to Exploring destructible voxel-based physics">​</a></h2>
<p>We explored the feasibility of destructible voxel physics with Rapier. This requires three parts:</p>
<ul>
<li>A new <code>Voxels</code> shape in <code>parry</code>. This <code>Voxels</code> shape is composed of several grid-aligned voxels, where each voxel
is represented as a pseudo-sphere (a sphere with cube-like corners along faces were the adjacent voxel exists).
Using pseudo-spheres makes the collision-detection more efficient than using actual cubes.</li>
<li>Collision-detection (also implemented in <code>parry</code>) with these new <code>Voxels</code> shape, and, in particular, between two <code>Voxels</code>
shapes.</li>
<li>The definition of a <code>VoxelFracturePipeline</code> in <code>rapier</code> responsible for calculating approximate stress values within
a single <code>Voxels</code> shape in order to detected potential fracture locations.</li>
</ul>
<p>This first exploration resulted in the following proof-of-concept: a room collapsing under its own weight. Each new colored body
appearing is a fractured piece that separates from the main body:</p>
<center><video width="560" controls=""><source src="/vids/fracture-demo.mp4" type="video/mp4"><p>Your browser does not support the video tag.</p></video></center>
<div class="theme-admonition theme-admonition-note admonition_v1XZ alert alert--secondary"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_nS2X"><p>This work on voxels hasn’t been merged yet because it is not efficient enough nor feature-complete enough for
production use yet. It is only available on the <code>voxels</code> branch of <a href="https://github.com/dimforge/rapier/tree/voxels" target="_blank" rel="noopener noreferrer">Rapier</a>
and <a href="https://github.com/dimforge/parry/tree/voxels" target="_blank" rel="noopener noreferrer">Parry</a>.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="bevy-rapier-ergonomics-improvements">Bevy-rapier: ergonomics improvements<a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#bevy-rapier-ergonomics-improvements" class="hash-link" aria-label="Direct link to Bevy-rapier: ergonomics improvements" title="Direct link to Bevy-rapier: ergonomics improvements">​</a></h2>
<p>The <code>bevy-rapier2d</code> and <code>bevy-rapier3d</code> crates provide plugins to use <code>rapier</code> easily with the <code>bevy</code> game engine.
In April 2022 we released a complete rewrite of this plugin to make the API significantly more "bevy-friendly":</p>
<ul>
<li>Colliders and rigid-bodies can be configured through multiple components.</li>
<li>Collider and rigid-body positioning operates through the familiar <code>Transform/GlobalTransform</code> components
directly.</li>
<li>Mesh colliders can be created automatically after a <code>Mesh</code> asset is done loading, using
the <code>AsyncCollider</code> or <code>AsyncSceneCollider</code> components.</li>
<li>All the components and query functions now rely
on <code>glam</code> types instead of <code>nalgebra</code>. <code>nalgebra</code> types are only needed when calling into the raw Rapier
objects (which can be used for niche operations that are not exposed explicitly by the plugin yet).</li>
<li>A wireframe debug-renderer can be enabled with the new <code>RapierDebugRenderPlugin</code>.</li>
</ul>
<p>These changes were strongly inspired by the <a href="https://github.com/jcornaz/heron" target="_blank" rel="noopener noreferrer">heron crate</a> which
had a way nicer API than <code>bevy-rapier</code> before this rewrite</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="game-highlight-ultimechs">Game highlight: Ultimechs<a href="https://dimforge.com/blog/2023/01/22/the-year-2022-in-dimforge#game-highlight-ultimechs" class="hash-link" aria-label="Direct link to Game highlight: Ultimechs" title="Direct link to Game highlight: Ultimechs">​</a></h2>
<center><iframe width="560" height="315" src="https://www.youtube.com/embed/pvQJ7_3Q_TU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe></center>
<p>In September 2022, our sponsor <a href="https://www.resolutiongames.com/" target="_blank" rel="noopener noreferrer"><strong>Resolution Games</strong></a> launched the exciting free-to-play multiplayer VR game: <a href="https://www.resolutiongames.com/ultimechs" target="_blank" rel="noopener noreferrer">Ultimechs</a>.
Based on Unity, Ultimechs relies on our Rapier physics engine for physics. You can read more about Resolution Games’ use of Rust alongside Unity
in their <a href="https://www.resolutiongames.com/blog/calling-rust-from-c-in-unity" target="_blank" rel="noopener noreferrer">May 20 Insight</a>.</p>
<h1>Sparkl: exploring MPM physics simulation</h1>
<p>The <strong>Sparkl</strong> project is entirely sponsored by <a href="https://foresightmining.com/" target="_blank" rel="noopener noreferrer">Foresight Mining Software Corporation</a> which
currently leverages it in production for industrial applications.</p>
<center><a href="https://foresightmining.com/"><img src="https://user-images.githubusercontent.com/2632925/151242316-db3455d1-4934-4374-8369-1818daf512dd.png" alt="Foresight Mining Software Corporation" width="480"></a></center>
<p>We silently released in December 2022 our open-source MPM (Material Point Method) physics simulation libraries:
<code>sparkl2d</code>, <code>sparkl3d</code>. In their current form, they supports 2D and 3D particle-based deformable physics simulation
with various materials, including sand, snow, elasticity and fracture. They do
not support two-way coupling with <code>rapier</code> yet, meaning that Rapier colliders can be used
to define the ground using boxes or heightfields, but interaction with dynamic bodies isn’t
implemented yet.</p>
<p><strong>Sparkl</strong> runs on CUDA-enabled GPUs only (running on multiple GPUs is supported). All the CUDA kernels are written 100% in Rust thanks to
the <a href="https://github.com/Rust-GPU/Rust-CUDA" target="_blank" rel="noopener noreferrer">Rust CUDA Project</a>.</p>
<h1>nalgebra: linear-algebra</h1>
<center><p><img decoding="async" loading="lazy" src="https://nalgebra.org/img/logo_nalgebra.svg" alt="nalgebra logo" class="img_XsDP"></p></center>
<p><strong>nalgebra</strong> is a general-purpose linear-algebra library for Rust. It supports low-dimensional, high-dimensional,
sparse matrices, as well as geometric transformations (rotations, isometries, etc.)</p>
<p>In 2022, most of our efforts went in <strong>Rapier</strong> rather than <strong>nalgebra</strong> itself. Most new features were added by
the community, including:</p>
<ul>
<li>Matrix <strong>slices</strong> were renamed as matrix <strong>views</strong> to avoid confusion with rust slices (by <a href="https://github.com/dimforge/nalgebra/pull/1178" target="_blank" rel="noopener noreferrer">Andlon #1178</a>).</li>
<li>Enabling the <code>rayon</code> feature of <strong>nalgebra</strong> will enable the<code>Matrix::par_column_iter</code> and <code>Matrix::par_column_iter_mut</code> methods. As their names suggest, these are rayon-based parallel
iterators on the matrix’s columns (by <a href="https://github.com/dimforge/nalgebra/pull/1165" target="_blank" rel="noopener noreferrer">geo-ant #1165</a>).</li>
<li>Generalized eigenvalues problem resolution, generalized eigenvalues/eigenvector calculations, and QZ decomposition have been added to <code>nalgebra-lapack</code> (by <a href="https://github.com/dimforge/nalgebra/pull/1067" target="_blank" rel="noopener noreferrer">metric-space #1067</a> and <a href="https://github.com/dimforge/nalgebra/pull/1106" target="_blank" rel="noopener noreferrer">geoeo #1106</a>).</li>
<li>Performance of the product of two sparse matrices in <code>nalgebra-sparse</code> has been improved significantly
(by <a href="https://github.com/dimforge/nalgebra/pull/1081" target="_blank" rel="noopener noreferrer">smr97 #1081</a>).</li>
</ul>
<p>Check out the <a href="https://github.com/dimforge/nalgebra/blob/dev/CHANGELOG.md" target="_blank" rel="noopener noreferrer">Changelog</a> for details on the other  additions.</p>
<hr>
<h1>What’s next in 2023</h1>
<p>Because we focused on features during the past two years, we will take a different route for
2023. In its current form, Rapier looks complete enough feature-wise to fit most
game use-cases. So our main objective will be to work on <strong>bug fixes</strong>, <strong>user-experience
improvements</strong>, and <strong>documentation</strong>. This quality improvement effort will be focused mainly on Rapier, and include
for example:</p>
<ul>
<li>Addressing most bugs reported on GitHub in 2022 and before, as well as complaints that are
frequently reported on Discord (for example, related to some limitations of the character-controller when it hits vertical walls).</li>
<li>Reduce risks of internal panics in Rapier (for example when a rigid-body has a <code>NaN</code> position).</li>
<li>Make the debugging experience nicer with the JS bindings by detecting potential problems
(and raising an exception) before reaching the WASM module.</li>
</ul>
<p>In order to get a better awareness of Rapier’s ergonomics issues and bugs, we will be working on a small
physics sandbox app. It is currently closed-source, but will be open-sourced once it is more fleshed-out
and usable. Think of something similar <a href="https://fr.wikipedia.org/wiki/Phun" target="_blank" rel="noopener noreferrer">Phun</a>/<a href="http://www.algodoo.com/" target="_blank" rel="noopener noreferrer">Algodoo</a> but written
in Rust, based on Rapier, compatible with WASM (i.e. runs on the browser), and handling both 2D and 3D (in two different apps. sharing the same codebase).</p>
<p>Writing this physics sandbox will also be the opportunity to explore the scaling large-scale distributed
physics simulation. This exploratory work is sponsored by <a href="https://www.futurewei.com/" target="_blank" rel="noopener noreferrer">Futurewei</a>.</p>
<hr>
<h1>Thanks</h1>
<p>We can’t thank enough:</p>
<ul>
<li><a href="https://www.foresightmining.com/" target="_blank" rel="noopener noreferrer">Foresight Mining Software Corporation</a>
for sponsoring <strong>Sparkl</strong>, all our CUDA-related efforts on <strong>nalgebra</strong> and <strong>parry</strong>, many of the new geometric primitives
in <strong>Parry</strong>.</li>
<li><a href="https://futurewei.com/" target="_blank" rel="noopener noreferrer">Futurewei</a> for sponsoring the ongoing exploration of distributed physics simulation.</li>
<li><a href="https://fragcolor.com/" target="_blank" rel="noopener noreferrer">Fragcolor</a> and
<a href="https://www.resolutiongames.com/" target="_blank" rel="noopener noreferrer">Resolution Games</a> for being our Gold sponsors for a whole year.</li>
</ul>
<p>Thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This helps us tremendously to sustain our Free and Open-Source work.</p>
<center><a href="https://foresightmining.com/"><img src="https://user-images.githubusercontent.com/2632925/151242316-db3455d1-4934-4374-8369-1818daf512dd.png" alt="Foresight Mining Software Corporation" width="480"></a><br><br><a href="https://futurewei.com/"><img src="https://www.futurewei.com/images/logo_files/futurewei-logo-swirl-400x113.png"></a><br><br><a href="https://resolutiongames.com/"><img src="https://dimforge.com/img/logo_resolution_games.png" height="100px"></a><a href="https://fragcolor.com/"><img src="https://dimforge.com/img/fragcolor_logo2_color_black.svg" height="100px"></a></center>
<p></p>
<p>This help is greatly appreciated and allows us to continue working on our open-source projects.
Finally, a huge thanks to the whole community and code contributors!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The year 2021 in Dimforge and our objectives for 2022]]></title>
            <link>https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge</link>
            <guid>https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge</guid>
            <pubDate>Sun, 02 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[🎉🎉🎉 Happy new year 2022 everyone! 🎉🎉🎉]]></description>
            <content:encoded><![CDATA[<p><strong>🎉🎉🎉 Happy new year 2022 everyone! 🎉🎉🎉</strong></p>
<p>The year 2021 has been a very exciting for Dimforge and the Rust community at a whole! This blog post
summarizes the most significant additions made in 2021 to the open-source crates for
linear-algebra and physics simulation we develop for the Rust community. We also present our
main objectives for 2022.</p>
<p>Help us sustain this work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>
<p><img decoding="async" loading="lazy" alt="rapier logo" src="https://dimforge.com/assets/images/rapier_logo_color_textpath_dark-67093214cb8594cb6bf7b952ff3e3027.svg" width="527" height="131" class="img_XsDP"></p>
<p>Rapier is a 2D and 3D physics engine for games, robotics, and animation written in Rust. Our
<a href="https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap">goal for 2021</a> was to
work on the missing <em>low-level</em> features of Rapier: <strong>shape-casting, CCD, joint limits and motors, custom collider
shapes, dominance, multibodies</strong>. We also significantly improved Rapier’s documentation by writing
<a href="https://rapier.rs/docs/" target="_blank" rel="noopener noreferrer">complete user-guides</a> for the Rust version of Rapier, it’s Typescript bindings, as well
as its Bevy plugin.</p>
<p>Today we released the version <code>0.12-alpha.0</code> of Rapier. This release features three significant changes:</p>
<ol>
<li>The addition of <a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#multibody-joints"><strong>multibody joints</strong></a> (part of our 2021 objectives).</li>
<li>The change of our <a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#constraint-solver-change">constraint solver</a>.</li>
<li>A complete redesign of our <a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#joints-redesign">joints</a>.</li>
</ol>
<p>Please note that this is an <strong>alpha</strong> release which still has a few <a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#why-an-alpha-release">known limitations</a> we
would like to address before making a proper release.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="multibody-joints">Multibody joints<a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#multibody-joints" class="hash-link" aria-label="Direct link to Multibody joints" title="Direct link to Multibody joints">​</a></h2>
<p>The main focus of this release was to add the support for joints based on the <strong>reduced-coordinates</strong> formalism.
There are basically two main ways of modeling joints:</p>
<ul>
<li>The <strong>full-coordinates</strong> approach, aka. <strong>impulse-based joints</strong>, that applies forces/impulses to enforce the joint’s
positional constraints.</li>
<li>The <strong>reduced-coordinates</strong> approach, aka. <strong>multibody joints</strong>, that encodes the positional constraints directly
into the parametrization of the rigid-bodies positions when developing the equations of motions.</li>
</ul>
<p>Both approaches have advantages and drawbacks. The impulse-based joints are more computationally efficient, and can
sustain higher relative velocities without completely diverging. However, the constraint solver may not always be
able to compute the exact forces needed to fulfill the joints requirements. This can result in a wobbly behavior, where
the attached objects appear to oscillate. For example, you can observe this "wobbly" behavior here with fixed joints (top-left),
limited prismatic-joints (bottom), and motorized revolute joints (top-right):</p>
<center><p><img decoding="async" loading="lazy" alt="impulse joints" src="https://dimforge.com/assets/images/impulse_joints-d3f4c376b8c27fc60bc7635ea3360acb.gif" width="558" height="480" class="img_XsDP"></p></center>
<p>The multibody joints however can be less computationally efficient and do not allow joint assemblies with loops (it must
form a tree). However, these joints will never be violated, avoiding any wobbly behavior. The assembly looks
perfectly stiff:</p>
<center><p><img decoding="async" loading="lazy" alt="multibody joints" src="https://dimforge.com/assets/images/multibody_joints-7d9535997df6a78b4e12bfa28f951a57.gif" width="558" height="480" class="img_XsDP"></p></center>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="constraint-solver-change">Constraint solver change<a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#constraint-solver-change" class="hash-link" aria-label="Direct link to Constraint solver change" title="Direct link to Constraint solver change">​</a></h2>
<p>The addition of multibody joints proved to be quite difficult considering the design of our former constraint solver.
Before the version 0.12-alpha.0, Rapier used a linear velocity-based solver (with warm-starting) to solve velocity (contact and joint)
constraints, followed by a non-linear position-based post-projection to correct any penetration or joint drift at the
position level. This scheme proved to be quite difficult to extend (because of the non-linear nature of the position-based
solver) and computationally expensive when multibodies were involved. Therefore, we changed our solver to only contain
two linear velocity-based phases:</p>
<ol>
<li><strong>A biased velocity constraint resolution</strong>, which solves for the contact and joint constraints and tries to correct
penetrations and joint drifts at the same time. This will potentially add artificial energy to the mechanical system,
resulting in potential jitters, and "popping" effects due to penetration.</li>
<li><strong>A non-biased <em>stabilization</em> velocity resolution</strong>, which removes most of the excessive energy introduced into the
mechanical system by the previous phase.</li>
</ol>
<p>With both phases combined, typical simulations won’t show any large "popping" effect or jitter, while feeling stiffer
overall. In addition, this solver doesn't require any warm-starting, meaning that the force computation no longer
rely on the complete history of the simulation to converge. In the future this should allow the implementation of
rollback systems with less state needed to keep the simulation stable.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="joints-redesign">Joints redesign<a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#joints-redesign" class="hash-link" aria-label="Direct link to Joints redesign" title="Direct link to Joints redesign">​</a></h2>
<p>One of our objectives with the introduction of multibody joints was to keep the multibody joints API as close as
possible as the impulse-based joints API, despite the fact that their mathematical modeling are completely different.
Before the release 0.12-alpha.0, we had different types for each impulse-based joint (<code>RevoluteJoint</code>, <code>PrismaticJoint</code>,
<code>FixedJoint</code> and <code>BallJoint</code>). In the version 0.12-alpha.0, all the impulse-based joints are replaced by a single
generic joint <code>ImpulseJoint</code> similar to "6-dofs joints" in other 3D physics engines. Similarly, the multibody
joints have all been grouped into a single generic joint <code>MultibodyJoint</code> which can be configured to represent any
combination of free/limited/motorized degrees-of-freedoms.</p>
<p>The structures <code>FixedJoint, BallJoint, PrismaticJoint</code> and <code>SphericalJoint</code> (formerly named <code>BallJoint</code>) still exist,
but are only used as a simple way to build an <code>ImpulseJoint</code> or a <code>MultibodyJoint</code>. Impulse joints are added to the
<code>ImpulseJointSet</code> (formerly named <code>JointSet</code>) and multibody joints are added to the <code>MultibodyJointSet</code>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="why-an-alpha-release">Why an alpha release?<a href="https://dimforge.com/blog/2022/01/02/the-year-2021-in-dimforge#why-an-alpha-release" class="hash-link" aria-label="Direct link to Why an alpha release?" title="Direct link to Why an alpha release?">​</a></h2>
<p>For the first time in the history of <code>rapier</code>, we are making an <strong>alpha</strong> release. This release introduces significant
changes, and still has a few bugs we are aware of:</p>
<ul>
<li>Multibody joints created from a <code>JointData</code> directly instead of through a <code>RevoluteJoint, PrismaticJoint, FixedJoint, SphericalJoint</code> structure may behave oddly. We will soon make sure that the general case works properly (we finished
the mathematical modeling but not the implementation yet).</li>
<li>Joint motors affecting multiple free angular degrees of freedom may behave in an unexpected way because of
a few numerical issues due that we need to address.</li>
<li>We haven’t updated the user-guide yet (however all our examples have been updated).</li>
<li>The parallel version of Rapier should not be used with this alpha version.</li>
</ul>
<p>These issues will be our first priority for 2022. We didn't want to postpone the alpha release any further so that users
that don’t rely on these specific features can already start switching to, testing, and providing feedbacks on this new version
(especially regarding the new constraint solver). This also allows us to keep <code>rapier</code> in sync with the newer version of
<code>nalgebra</code> we released today.</p>
<h1>nalgebra: linear-algebra</h1>
<center><p><img decoding="async" loading="lazy" src="https://nalgebra.org/img/logo_nalgebra.svg" alt="nalgebra logo" class="img_XsDP"></p></center>
<p><strong>nalgebra</strong> is a general-purpose linear-algebra library for Rust. It supports low-dimensional, high-dimensional,
sparse matrices, as well as geometric transformations (rotations, isometries, etc.)</p>
<p>The main features added in 2021 were:</p>
<ul>
<li>The release of the new <a href="https://crates.io/crates/nalgebra-sparse" target="_blank" rel="noopener noreferrer">nalgebra-sparse</a> crate entirely contributed by
<a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andreas Longva</a>. This is a complete rewrite of our former <code>nalgebra::sparse</code> module.</li>
<li>The integration of <a href="https://www.dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra/" target="_blank" rel="noopener noreferrer">const-generics</a>,
improving the ergonomics, debuggability, and generic programming, for code involving statically-sized matrices.</li>
<li>The addition of the <code>matrix!</code>, <code>vector!</code>, <code>point!</code>, etc. macros to construct matrices from their components more easily.
They allow the easy construction of <code>const</code> matrices and vectors too.</li>
<li>The fix of several soundness issues, in particular by properly using <code>MaybeUninit</code> instead of the deprecated, unsound,
<code>mem::uninitialized()</code>.</li>
</ul>
<p>Finally, today we released the version 0.30 of <code>nalgebra</code> which adds the compatibility with the recently announced
<a href="https://github.com/Rust-GPU/Rust-CUDA" target="_blank" rel="noopener noreferrer">rust-cuda</a> project. This allows the usage of every <code>no-std</code> features of
<code>nalgebra</code> (which are, everything, including matrix decompositions, excluding sparse matrices and dynamically-sized
matrices) inside <strong>CUDA kernels</strong> written in Rust. The transfer of <code>nalgebra</code> structures between the RAM and VRAM is
also possible.</p>
<h1>Parry: collision-detection</h1>
<center><img src="https://parry.rs/img/logo_parry.svg" height="250px"><br></center>
<p>In 2021, we released our new collision-detection library <code>parry</code> which replaces our former crate <code>ncollide</code>. The <code>parry</code>
crate is more efficient than <code>ncollide</code> and is easier to use thanks to a much smaller amount of generics. Some notable
features supported by <code>parry</code> that were not included in <code>ncollide</code> are:</p>
<ul>
<li>An implementation of the <strong>VHACD algorithm</strong> for approximate convex decomposition of concave 2D and 3D shapes.</li>
<li>An implementation of an <strong>SIMD-accelerated quaternary BVH</strong> structure, much more efficient than <code>ncollide</code>’s <code>BVT</code> and
<code>DBVT</code> structures.</li>
<li>A more versatile <strong>non-linear shape casting</strong>.</li>
<li>An implementation of the <strong>Hertel-Mehlhorn algorithm</strong> for 2D convex decomposition, fully contributed by
<a href="https://github.com/EmbersArc" target="_blank" rel="noopener noreferrer">Sven Niederberger</a>.</li>
</ul>
<p>Finally, today we released the version 0.8 of <code>parry</code>. This version allows a subset of <code>parry</code> to work in a <code>no-std</code>
context. This was required to add the compatibility of this subset of <code>parry</code> with <code>rust-cuda</code>, allowing various
geometric operations (including ray-casting, distance computation, intersection tests, etc.) to be used inside of a
<strong>CUDA kernel</strong> written in Rust.</p>
<h1>Salva: fluids simulation</h1>
<p>In our <a href="https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap">roadmap for 2021</a>, we mentioned that we would
work on improving the performances of Salva with SIMD optimizations. We are sorry to announce that none of
it has been done. Instead, we focused more of <code>Rapier</code>, and started experimenting with the Material Point Method. This
experiment is important because:</p>
<ul>
<li>MPM has shown to be quite promising lately, for example with the recent presentation of the
<a href="https://github.com/Wumpf/blub" target="_blank" rel="noopener noreferrer">blub project</a>.</li>
<li>MPM is extremely versatile to simulate models sustaining large deformations, and a wide range of various materials, from
sponges to fluids.</li>
<li>MPM is very friendly for aggressive optimizations based on multithreading, SIMD, and GPU computing.</li>
<li>MPM may end up replacing completely the SPH implemented in <code>Salva</code> if we get good results.</li>
</ul>
<p>We currently have promising preliminary results using a CPU-based implementation multithreaded with <code>rayon</code>, or a
GPU-based CUDA implementation based on <code>rust-cuda</code> (all our CUDA kernels are written in Rust, using <code>nalgebra</code> and
<code>parry</code>). As always, we are targeting both 2D and 3D simulations. The development of this new crate is currently
closed-source, with a plan to open-source it in April 2022. Here are a couple of small simulations featuring deformations,
sand, fluids and fractures:</p>
<center><p><img decoding="async" loading="lazy" alt="MPM 3d" src="https://dimforge.com/assets/images/mpm_cuda_3d-e5e14fd30a54f4b12e09267256e937c4.gif" width="602" height="446" class="img_XsDP">
<img decoding="async" loading="lazy" alt="MPM 2d" src="https://dimforge.com/assets/images/mpm_cuda_2d-60e0b5d478d9f3b626b7ea9858507f55.gif" width="602" height="446" class="img_XsDP"></p></center>
<h1>What’s next in 2022</h1>
<p>For 2022, we have two main objectives:</p>
<ol>
<li>Work on <strong>high-level features</strong> for Rapier.</li>
<li>Continue our <strong>exploration of MPM</strong> for fluids and deformable bodies simulation.</li>
</ol>
<p>By <em>high-level</em> features for Rapier, we mean all these features that make the user’s life easier and that have been
frequently requested in 2021. This includes:</p>
<ul>
<li>A more efficient handling of <strong>voxel-based worlds</strong>. We also consider experimenting with <strong>destruction</strong> on
voxel-based games, similar to what can be seen in the <a href="https://teardowngame.com/" target="_blank" rel="noopener noreferrer">Teardown game</a>.</li>
<li>A sample <strong>character controller</strong>.</li>
<li><strong>Utilities</strong> like Godot’s <code>move_and_slide</code> for easier control of kinematic rigid-bodies.</li>
<li><strong>Inverse kinematics</strong>.</li>
<li>Solutions for the <strong>internal edge problem</strong> that may cause "bumps" when an object slides on a flat surface represented
by multiple triangles or cubes.</li>
</ul>
<p>These additions will bring Rapier to a very usable place for both physics beginners and experts.</p>
<hr>
<h1>Thanks</h1>
<p>We would like to thank <a href="https://www.croquet.io/" target="_blank" rel="noopener noreferrer">Croquet</a> for sponsoring our work right from the beginning of Dimforge,
as well as <a href="https://fragcolor.com/" target="_blank" rel="noopener noreferrer">Fragcolor</a> for being  our new Gold sponsor for 2022! This helps us tremendously to
sustain our Free and Open-Source work.</p>
<center><a href="https://www.croquet.io/"><img src="https://www.croquet.io/images/logo-light.png" height="70px"></a><br><a href="https://fragcolor.com/"><img src="https://dimforge.com/img/fragcolor_logo2_color_black.svg" height="100px"></a></center>
<p></p>
<p>Thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on our open-source projects.
Finally, a huge thanks to the whole community and code contributors!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The last two months in Dimforge (June - July 2021)]]></title>
            <link>https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge</link>
            <guid>https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge</guid>
            <pubDate>Sun, 15 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[This newsletter provides you with a]]></description>
            <content:encoded><![CDATA[<p>This newsletter provides you with a
summary of important updates that occurred within the Dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>Salva</strong></a> (fluid simulation),
<a href="https://parry.rs/" target="_blank" rel="noopener noreferrer"><strong>Parry</strong></a> (collision-detection), <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>Simba</strong></a> (abstract algebra) crates. This article will contain updates for
the months of <strong>June and July 2021</strong>.</p>
<p>Help us sustain this work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="new-user-guide-for-rapiers-js-bindings-">New, user-guide for Rapier’s JS bindings 📖<a href="https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge#new-user-guide-for-rapiers-js-bindings-" class="hash-link" aria-label="Direct link to New, user-guide for Rapier’s JS bindings 📖" title="Direct link to New, user-guide for Rapier’s JS bindings 📖">​</a></h2>
<p>During April and May, we completely rewrote the user-guides for the Rust version Rapier and <code>bevy_rapier</code>. During the
past two months, we continued this documentation work by completely rewriting the user-guide for the JS/TypeScript
bindings for Rapier too. It is now <strong>much more complete</strong> as it covers all the available features.</p>
<p>Check it out on <a href="https://www.rapier.rs/docs/user_guides/javascript/getting_started_js" target="_blank" rel="noopener noreferrer">rapier.rs</a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="nalgebra-v029-soundness-and-better-non-copy-types-support-">nalgebra v0.29: soundness and better non-Copy types support 🎊<a href="https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge#nalgebra-v029-soundness-and-better-non-copy-types-support-" class="hash-link" aria-label="Direct link to nalgebra v0.29: soundness and better non-Copy types support 🎊" title="Direct link to nalgebra v0.29: soundness and better non-Copy types support 🎊">​</a></h2>
<p>The development of <code>nalgebra</code> started even before the 1.0 release of the Rust compiler. Needless to say this was
long before the <code>MaybeUninit</code> type was stabilized in <a href="https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html" target="_blank" rel="noopener noreferrer">Rust 1.36</a>.
Before the introduction of <code>MaybeUninit</code>, the use of <code>mem:uninitialized()</code> was the de-facto way of creating an uninitialized
variable, and was therefore used extensively throughout the codebase of <code>nalgebra</code>. Switching to <code>MaybeUninit</code> instead of
<code>mem::uninitialized()</code> was a <strong>major</strong> undertaking that never happened completely. We did replace all the <code>mem::uninitialized()</code>
by <code>MaybeUninit::new().uninit()</code> a while ago but that was still technically unsound, even if it didn’t cause
any actual problem in practice because <code>nalgebra</code> was mostly used with primitive <code>Copy</code> types.</p>
<p>With <code>nalgebra</code> 0.29, we completely reworked our trait system in order to use <code>MaybeUninit</code> properly. This has two
benefits:</p>
<ul>
<li>The parts of <code>nalgebra</code> using uninitialized matrices is no longer unsound.</li>
<li>It is now possible to use non-<code>Copy</code> types safely as matrix components (for example, <code>BigUint</code> from the <code>num_bigint</code>
crate).</li>
</ul>
<p>This work was the result of a significant group effort, for which we thank in particular</p>
<ul>
<li><a href="https://github.com/OfficialURL" target="_blank" rel="noopener noreferrer">Violeta Hernández</a> who made a fantastic work exploring all the possible design
solutions we could think of.</li>
<li><a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andreas Longva</a>, <a href="https://github.com/Ralith" target="_blank" rel="noopener noreferrer">Benjamin Saunders</a>, and others on
our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> for providing valuable comments and ideas.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="announcing-rapier-011-️">Announcing Rapier 0.11 ⚔️<a href="https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge#announcing-rapier-011-%EF%B8%8F" class="hash-link" aria-label="Direct link to Announcing Rapier 0.11 ⚔️" title="Direct link to Announcing Rapier 0.11 ⚔️">​</a></h2>
<p>With the release 0.11 of Rapier, we implemented all the <strong>joint limits</strong> that were missing, this includes
joint limits for revolute joints and ball joints.</p>
<p>During the past two months, we also started working on joints modeled using <strong>reduced coordinates</strong>. These joints have the
benefit of being <em>unbreakable</em>, at the cost of being slightly less versatile (joint forces can’t be read, the chain of
articulations can’t form a loop) and more computationally expensive</p>
<p>As mentioned in our
<a href="https://www.dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#rapier-roadmap-for-2021" target="_blank" rel="noopener noreferrer">2021 roadmap for Rapier</a>,
we initially planned to release reduced-coordinates joints in August. However, it will take more time because we spent
the last few months improving the documentation of Rapier (which we initially planned on doing at the end of this year
instead) instead of working on these joints.</p>
<p>This work is happening in the <a href="https://github.com/dimforge/rapier/tree/multibody" target="_blank" rel="noopener noreferrer">multibody branch</a> and will be our
focus for the next couple of months.</p>
<hr>
<h1>Thanks</h1>
<p>We would like to thank the whole community and code contributors. In particular, thanks to the code contributors from
the past two months<sup><a href="https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge#user-content-fn-1-1da410" id="user-content-fnref-1-1da410" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li>
<p><a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">@Andlon</a></p>
</li>
<li>
<p><a href="https://github.com/atouchet" target="_blank" rel="noopener noreferrer">@atouchet</a></p>
</li>
<li>
<p><a href="https://github.com/CAD97" target="_blank" rel="noopener noreferrer">@CAD97</a></p>
</li>
<li>
<p><a href="https://github.com/CattleProdigy" target="_blank" rel="noopener noreferrer">@CattleProdigy</a></p>
</li>
<li>
<p><a href="https://github.com/Cryptjar" target="_blank" rel="noopener noreferrer">@Cryptjar</a></p>
</li>
<li>
<p><a href="https://github.com/Demindiro" target="_blank" rel="noopener noreferrer">@Demindiro</a></p>
</li>
<li>
<p><a href="https://github.com/extrawurst" target="_blank" rel="noopener noreferrer">@extrawurst</a></p>
</li>
<li>
<p><a href="https://github.com/grimko" target="_blank" rel="noopener noreferrer">@grimko</a></p>
</li>
<li>
<p><a href="https://github.com/hoiast" target="_blank" rel="noopener noreferrer">@hoiast</a></p>
</li>
<li>
<p><a href="https://github.com/jpetkau" target="_blank" rel="noopener noreferrer">@jpetkau</a></p>
</li>
<li>
<p><a href="https://github.com/jsmith628" target="_blank" rel="noopener noreferrer">@jsmith628</a></p>
</li>
<li>
<p><a href="https://github.com/MalteT" target="_blank" rel="noopener noreferrer">@MalteT</a></p>
</li>
<li>
<p><a href="https://github.com/mariusknaust" target="_blank" rel="noopener noreferrer">@mariusknaust</a></p>
</li>
<li>
<p><a href="https://github.com/n3vu0r" target="_blank" rel="noopener noreferrer">@n3vu0r</a></p>
</li>
<li>
<p><a href="https://github.com/Nateckert" target="_blank" rel="noopener noreferrer">@Nateckert</a></p>
</li>
<li>
<p><a href="https://github.com/OfficialURL" target="_blank" rel="noopener noreferrer">@OfficialURL</a></p>
</li>
<li>
<p><a href="https://github.com/oli-obk" target="_blank" rel="noopener noreferrer">@oli-obk</a></p>
</li>
<li>
<p><a href="https://github.com/Ralith" target="_blank" rel="noopener noreferrer">@Ralith</a></p>
</li>
<li>
<p><a href="https://github.com/remilauzier" target="_blank" rel="noopener noreferrer">@remilauzier</a></p>
</li>
<li>
<p><a href="https://github.com/rezural" target="_blank" rel="noopener noreferrer">@rezural</a></p>
</li>
<li>
<p><a href="https://github.com/skairunner" target="_blank" rel="noopener noreferrer">@skairunner</a></p>
</li>
<li>
<p><a href="https://github.com/ssbr" target="_blank" rel="noopener noreferrer">@ssbr</a></p>
</li>
<li>
<p><a href="https://github.com/SuperSamus" target="_blank" rel="noopener noreferrer">@SuperSamus</a></p>
</li>
<li>
<p><a href="https://github.com/vadixidav" target="_blank" rel="noopener noreferrer">@vadixidav</a></p>
</li>
<li>
<p><a href="https://github.com/viridia" target="_blank" rel="noopener noreferrer">@viridia</a></p>
</li>
<li>
<p><a href="https://github.com/Waridley" target="_blank" rel="noopener noreferrer">@Waridley</a></p>
</li>
<li>
<p><a href="https://github.com/wwwtyro" target="_blank" rel="noopener noreferrer">@wwwtyro</a></p>
</li>
<li>
<p><a href="https://github.com/zedseven" target="_blank" rel="noopener noreferrer">@zedseven</a></p>
</li>
<li>
<p><a href="https://github.com/zicklag" target="_blank" rel="noopener noreferrer">@zicklag</a></p>
</li>
<li>
<p>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</p>
</li>
<li>
<p>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</p>
</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on our open-source projects.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-1da410">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2021/08/15/the-last-two-months-in-dimforge#user-content-fnref-1-1da410" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in Dimforge \#6 (Apr. 2021 - May. 2021)]]></title>
            <link>https://dimforge.com/blog/2021/06/06/this-month-in-dimforge</link>
            <guid>https://dimforge.com/blog/2021/06/06/this-month-in-dimforge</guid>
            <pubDate>Sun, 06 Jun 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the sixth edition of This month in Dimforge! This newsletter provides you with a]]></description>
            <content:encoded><![CDATA[<p>Welcome to the sixth edition of <em>This month in Dimforge</em>! This newsletter provides you with a
summary of important updates that occurred within the Dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>Salva</strong></a> (fluid simulation),
<a href="https://parry.rs/" target="_blank" rel="noopener noreferrer"><strong>Parry</strong></a> (collision-detection), <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>Simba</strong></a> (abstract algebra) crates. This sixth edition will contain updates for
the months of <strong>April and May 2021</strong>.</p>
<p>Help us sustain this work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="announcing-rapier-09--bevy_rapier-010-️">Announcing Rapier 0.9 + bevy_rapier 0.10 ⚔️<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#announcing-rapier-09--bevy_rapier-010-%EF%B8%8F" class="hash-link" aria-label="Direct link to Announcing Rapier 0.9 + bevy_rapier 0.10 ⚔️" title="Direct link to Announcing Rapier 0.9 + bevy_rapier 0.10 ⚔️">​</a></h2>
<p>The release 0.9 was mostly focussed on improving the ergonomics of the crate by:</p>
<ul>
<li>Allowing <strong>user-defined storages</strong> containing rigid-bodies and colliders in place of the
default <code>ColliderSet</code>, <code>RigidBodySet</code> (which are still available). Actually the <code>RigidBody</code> and <code>Collider</code> structs can
also be optionally replaced by a set of individual components (<code>RigidBodyVelocity</code>, <code>RigidBodyPosition</code>, <code>ColliderShape</code>,
etc.) This can make the integration of Rapier into another framework much more ergonomic (<code>bevy_rapier 0.10</code> is an
example of improved integration).</li>
<li>Allowing <strong>colliders not attached to any rigid-body</strong>.</li>
<li>Adding a few <strong>simple methods</strong> to get/set the translation and rotation of a rigid-body or collider (instead of setting the whole
isometry at once).</li>
<li>Adding an easy way to <strong>enable collision-detection</strong> between a collider attached to a kinematic rigid-body and a
collider attached to a static rigid-body. More generally, we can now easily enable collision detection between two colliders
attached to non-dynamic rigid-bodies by configuring their <a href="https://www.rapier.rs/docs/user_guides/rust/colliders#active-collision-types" target="_blank" rel="noopener noreferrer">active collision types</a>.</li>
<li>Adding <strong>velocity-based kinematic bodies</strong>. They are rigid-bodies controlled by setting their velocity instead of
their next position.</li>
<li>Making collision events and physics hooks enabled for each individual collider explicitly instead of being enabled for
all the colliders automatically. See the collider's <a href="https://www.rapier.rs/docs/user_guides/rust/colliders#active-events" target="_blank" rel="noopener noreferrer">active events</a>
and <a href="https://www.rapier.rs/docs/user_guides/rust/colliders#active-events" target="_blank" rel="noopener noreferrer">active hooks</a>.</li>
</ul>
<p>Check out the <a href="https://github.com/dimforge/rapier/blob/master/CHANGELOG.md#v090" target="_blank" rel="noopener noreferrer"><strong>v0.9.0 changelog</strong></a> for an exhaustive
list of the changes.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="completely-rewritten-bevy_rapier-010-">Completely rewritten bevy_rapier 0.10 🐦<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#completely-rewritten-bevy_rapier-010-" class="hash-link" aria-label="Direct link to Completely rewritten bevy_rapier 0.10 🐦" title="Direct link to Completely rewritten bevy_rapier 0.10 🐦">​</a></h3>
<p>Thanks to the support of user-defined storages in Rapier 0.9, we were able to rewrite our Rapier plugin for Bevy
<code>bevy_rapier 0.10</code> to make it significantly more ergonomic (giving it a more <em>bevy-native</em> feeling) than
<code>bevy_rapier 0.9</code>.</p>
<p>As a result, Bevy's <code>QuerySet</code> are now used as rigid-body/collider storages instead of the <code>RigidBodySet/ColliderSet</code>.
Rigid-bodies and collider are now defined as bundles (instead of the monolithic structs <code>RigidBody</code> and <code>Collider</code>):</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token attribute attr-name" style="color:#00a4db">#[derive(Bundle)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">RigidBodyBundle</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> body_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> position</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyPosition</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> velocity</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyVelocity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> mass_properties</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyMassProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> forces</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyForces</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> activation</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyActivation</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> damping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyDamping</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> dominance</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyDominance</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> ccd</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyCcd</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> changes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyChanges</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> ids</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyIds</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> colliders</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">RigidBodyColliders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[derive(Bundle)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">ColliderBundle</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> collider_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> shape</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderShape</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> position</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderPosition</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> material</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderMaterial</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> flags</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderFlags</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> mass_properties</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderMassProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> changes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderChanges</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> bf_data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ColliderBroadPhaseData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The components in these bundles can be queried like any other components of <code>Bevy</code>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="new-complete-user-guides-">New, complete, user-guides 📖<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#new-complete-user-guides-" class="hash-link" aria-label="Direct link to New, complete, user-guides 📖" title="Direct link to New, complete, user-guides 📖">​</a></h2>
<p>During the past two months we have also been working at making the documentation of Rapier and bevy-rapier <strong>much more
complete</strong>! We now have user-guides that cover all the available features of Rapier, excepted details about implementing
your own custom storage for colliders and rigid-bodies.</p>
<p>Check out the new <a href="https://www.rapier.rs/docs/user_guides/rust/getting_started" target="_blank" rel="noopener noreferrer">Rapier user-guide</a>
and the new <a href="https://www.rapier.rs/docs/user_guides/rust_bevy_plugin/getting_started_bevy" target="_blank" rel="noopener noreferrer">bevy-rapier user-guide</a>. We
haven't improved the JavaScript user-guide but we will work on it in June.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-javascript-bindings-v060-">Rapier JavaScript bindings v0.6.0 🌐<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#rapier-javascript-bindings-v060-" class="hash-link" aria-label="Direct link to Rapier JavaScript bindings v0.6.0 🌐" title="Direct link to Rapier JavaScript bindings v0.6.0 🌐">​</a></h2>
<p>The JavaScript bindings for Rapier have been updated to use Rapier 0.9.0. In addition, we added the ability to:</p>
<ul>
<li>Create velocity-based kinematic bodies.</li>
<li>Read contact information (contact points, contact normals, etc.) and intersection statuses from the narrow-phase</li>
<li>Write custom filters (as JS objects implementing a specific interface) for applying any rule to select what
pair of colliders can or cannot collide.</li>
</ul>
<p>Check out <a href="https://github.com/dimforge/rapier.js/blob/master/CHANGELOG.md#v060" target="_blank" rel="noopener noreferrer">the 0.6.0 changelog</a> for a list of all
the changes.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="nalgebra-v026-and-v027-const-generics-">nalgebra v0.26 and v0.27: const-generics 🎊<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#nalgebra-v026-and-v027-const-generics-" class="hash-link" aria-label="Direct link to nalgebra v0.26 and v0.27: const-generics 🎊" title="Direct link to nalgebra v0.26 and v0.27: const-generics 🎊">​</a></h2>
<p>In April, we released the version 0.26 of <strong>nalgebra</strong> with one major changed: we integrated const-generics.
Check out <a href="https://www.dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra" target="_blank" rel="noopener noreferrer">our dedicated announcement</a>
if you missed it.</p>
<p>In nalgebra v0.27, we added (thanks to the contribution from <a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andreas Longva</a>) the macros <code>matrix!</code>, <code>dmatrix!</code>,
<code>vector!</code>, <code>dvector!</code>, <code>point!</code> for constructing matrices/vectors/points in a convenient way. The length of the
matrix/vector/point is deduced automatically from the number of elements given to the macros:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">nalgebra</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">vector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> matrix</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> vec3 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">vector!</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Constructs a `Vector3`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> pt2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">point!</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Constructs a `Point2`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> mat2x3 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">matrix!</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">11.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13.0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// The ; delimits each row of the matrix.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">21.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">22.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">23.0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Constructs a `Matrix2x3`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> dvec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">dvector!</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Constructs a `DVector` with four elements.</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>vector!</code>, <code>matrix!</code> and <code>point!</code> macros can also be used in a <code>const</code> context:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MY_VECTOR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Vector2</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">vector!</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next">​</a></h2>
<p>At the beginning of this year, we announced our
<a href="https://www.dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#rapier-roadmap-for-2021" target="_blank" rel="noopener noreferrer">2021 roadmap for Rapier</a>.
During the past two months, we slightly diverged from that roadmap because we figured it was time to make the library
more accessible to the community by improving its API (especially for <strong>bevy_rapier</strong>) and by providing comprehensive
docs. Hopefully, this will make game-development in Rust even more appealing to newcomers, and will allow everybody to
use the more advanced features of Rapier (that were not documented at all before).</p>
<p>In May, we will continue on that path by rewriting/completing the user-guide for the JavaScript bindings of Rapier.
If we have time after that, we will implement the joint limits we initially planned for last month (currently, only
joint limits for prismatic bodies are implemented).</p>
<hr>
<h1>Thanks</h1>
<p>We would like to thank the whole community and code contributors. In particular, thanks to the code contributors from
the past two months<sup><a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#user-content-fn-1-ee5b71" id="user-content-fnref-1-ee5b71" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/alec-deason" target="_blank" rel="noopener noreferrer">alec-deason</a></li>
<li><a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andlon</a></li>
<li><a href="https://github.com/chammika-become" target="_blank" rel="noopener noreferrer">chammika-become</a></li>
<li><a href="https://github.com/DasEtwas" target="_blank" rel="noopener noreferrer">DasEtwas</a></li>
<li>Dave Farnham</li>
<li><a href="https://github.com/djkoloski" target="_blank" rel="noopener noreferrer">djkoloski</a></li>
<li><a href="https://github.com/dstaatz" target="_blank" rel="noopener noreferrer">dstaatz</a></li>
<li><a href="https://github.com/illis" target="_blank" rel="noopener noreferrer">illis</a></li>
<li><a href="https://github.com/jturner314" target="_blank" rel="noopener noreferrer">jturner314</a></li>
<li><a href="https://github.com/MJohnson459" target="_blank" rel="noopener noreferrer">MJohnson459</a></li>
<li><a href="https://github.com/OfficialURL" target="_blank" rel="noopener noreferrer">OfficialURL</a></li>
<li><a href="https://github.com/rezural" target="_blank" rel="noopener noreferrer">rezural</a></li>
<li><a href="https://github.com/sdfgeoff" target="_blank" rel="noopener noreferrer">sdfgeoff</a></li>
<li><a href="https://github.com/vks" target="_blank" rel="noopener noreferrer">vks</a></li>
<li><a href="https://github.com/zakarumych" target="_blank" rel="noopener noreferrer">zakarumych</a></li>
</ul>
<ul>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on our open-source projects.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-ee5b71">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2021/06/06/this-month-in-dimforge#user-content-fnref-1-ee5b71" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Integrating const-generics to nalgebra 0.26]]></title>
            <link>https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra</link>
            <guid>https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra</guid>
            <pubDate>Mon, 12 Apr 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Today we released the version 0.26 of our general-purpose linear-algebra crate: nalgebra 🎊]]></description>
            <content:encoded><![CDATA[<p>Today we released the version 0.26 of our general-purpose linear-algebra crate: <strong>nalgebra</strong> 🎊</p>
<p>The version <a href="https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html" target="_blank" rel="noopener noreferrer">1.51.0 of Rust</a> has been released
three weeks ago. That version stabilized an MVP for one of the feature we wanted the most: <strong>const-generics</strong>.
Const-generics allow you to define types parametrized by const integers, chars, or booleans. One iconic
example is writing a structure wrapping an array of any size:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Example taken from the 1.51 Rust announcement.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Array</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LENGTH</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    list</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LENGTH</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>nalgebra</strong> supports matrices (and vectors) with dimensions known at runtime or at compile-time.
The components of matrices/vectors with dimensions known at runtime are stored in a <code>Vec&lt;T&gt;</code>.
Before <strong>nalgebra 0.26</strong>, matrices/vectors with dimensions known at compile-time were stored
in a <code>GenericArray</code>, from the excellent <a href="https://docs.rs/generic-array/0.14.4/generic_array/" target="_blank" rel="noopener noreferrer">generic-array</a>
crate. Thanks to const-generics, we were able to replace <code>GenericArray</code> by standard  arrays: <code>[[T; R]; C]</code>
(where <code>R</code> is the number of rows, and <code>C</code> the number of columns) in <strong>nalgebra 0.26</strong>.</p>
<p>This change results in significant ergonomics improvements when using statically-sized matrices or
vectors:</p>
<ul>
<li><a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#1-simpler-generic-programming-with-statically-sized-entities">Simpler generic programming.</a></li>
<li><a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#2-simpler-debugging-of-small-matrices-and-vectors">Simpler debugging.</a></li>
<li><a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#3-building-small-constant-matrices-and-vectors">Constructors using const-fn.</a></li>
<li><a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#4-new-aliases">New aliases.</a></li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="1-simpler-generic-programming-with-statically-sized-entities">1. Simpler generic programming with statically-sized entities<a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#1-simpler-generic-programming-with-statically-sized-entities" class="hash-link" aria-label="Direct link to 1. Simpler generic programming with statically-sized entities" title="Direct link to 1. Simpler generic programming with statically-sized entities">​</a></h3>
<p>Using <strong>nalgebra</strong> for generic programming with statically-sized
matrices/vectors/points  was quite challenging before. Let's take a
simple example of a generic structure that wraps a point, a vector,
and a matrix and performs some kind integration using 64-bit precision.
In previous version of <strong>nalgebra</strong> this would look like this:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_rBMM">Before (nalgebra &lt; 0.26)</div><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">nalgebra</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">DimName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">MatrixMN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">VectorN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Point</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DefaultAllocator</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">allocator</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Allocator</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Integrator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">DimName</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">where</span><span class="token plain"> </span><span class="token class-name">DefaultAllocator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Allocator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Allocator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">MatrixMN</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  v</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">VectorN</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  p</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Point</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">DimName</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">Integrator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">where</span><span class="token plain"> </span><span class="token class-name">DefaultAllocator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Allocator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Allocator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// A method that performs some kind of integration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// using `f64` intermediate results.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">integrate_highp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dt</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Point</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">where</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MatrixMN</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Copy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">VectorN</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Copy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Point</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Copy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">DefaultAllocator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Allocator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Allocator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// First cast all the operants to `f64`:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> p</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">p</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Perform the computation with f64 precision, then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// cast the result to f32.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> m </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> v </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> dt </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>See all the <code>DefaultAllocator: Allocator&lt;...&gt;</code> trait bounds? They are here to help the compiler
deduce the proper storage types for the matrix/vector/points (i.e. to deduce the <code>GenericArray</code>
with the right dimensions).</p>
<p>Now that const-generics have been integrated to <strong>nalgebra</strong> this code becomes as simple
as one would expect:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_rBMM">Now (nalgebra 0.26)</div><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">nalgebra</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">Point</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SMatrix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SVector</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Integrator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  m</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">SMatrix</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  v</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">SVector</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  p</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Point</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">Integrator</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// A method that performs some kind of integration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// using `f64` intermediate results.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">integrate_highp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dt</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Point</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// First cast all the operants to `f64`:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> p</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">p</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">::</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Perform the computation with f64 precision, then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// cast the result to f32.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> m </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> v </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> dt </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>See that there isn't any <code>DefaultAllocator: Allocator</code> trait bounds whatsoever.</p>
<p>Now, keep in mind that these simplifications will only work if you stick with entities
with dimensions known at compile-time. If your code needs to work generically for both
statically-sized matrices and dynamically-sized matrices, then the <code>DefaultAllocator: Allocator</code>
bounds are still necessary (we should be able to get rid of them too once <strong>specialization</strong>
is stabilized).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="2-simpler-debugging-of-small-matrices-and-vectors">2. Simpler debugging of small matrices and vectors<a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#2-simpler-debugging-of-small-matrices-and-vectors" class="hash-link" aria-label="Direct link to 2. Simpler debugging of small matrices and vectors" title="Direct link to 2. Simpler debugging of small matrices and vectors">​</a></h3>
<p>This one is a life-changer for those relying extensively on debuggers. Until now,
inspecting with a debugger the content of statically-sized matrices or vectors (or
points, quaternions, etc.) was extremely difficult. This was caused by the smart,
but complicated, recursive definition of <code>GenericArray</code>. Here is what inspecting
the content of <code>let matrix = Matrix2::new(1, 2, 3, 4)</code> looked like (in CLion's debugger,
using the Rust plugin):</p>
<p><img decoding="async" loading="lazy" alt="nalgebra_debug_before" src="https://dimforge.com/assets/images/nalgebra-debug-before-dc999673125fac96b22eea7db13bce3d.png" width="2176" height="1160" class="img_XsDP"></p>
<p>Here is what it looks like now that we replaced <code>GenericArray</code> by standard arrays:</p>
<p><img decoding="async" loading="lazy" alt="nalgebra_debug_now" src="https://dimforge.com/assets/images/nalgebra-debug-now-ec966204ddb226c4257c84f7beb9cbde.png" width="2290" height="440" class="img_XsDP"></p>
<p>This is much clearer now. Keep in mind that <strong>nalgebra</strong> stores its matrices in
column-major format. That's why the components appear in the order <code>[[1, 3], [2, 4]]</code> (column
by column).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="3-building-small-constant-matrices-and-vectors">3. Building small, constant, matrices and vectors<a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#3-building-small-constant-matrices-and-vectors" class="hash-link" aria-label="Direct link to 3. Building small, constant, matrices and vectors" title="Direct link to 3. Building small, constant, matrices and vectors">​</a></h3>
<p>Now that small matrices are using standard arrays under the hood, it is now possible
to define constant vectors, matrices, points, quaternions, and translations by using
their <code>const fn new(...)</code> constructors:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">nalgebra</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">Vector3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Point4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Matrix2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Quaternion</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Translation3</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">VECTOR</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Vector3</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Vector3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">POINT</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Point4</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">  </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Point4</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MATRIX</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Matrix2</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">i32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Matrix2</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                          </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">QUATERNION</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Quaternion</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Quaternion</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">TRANSLATION</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Translation3</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">f32</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Translation3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="4-new-aliases">4. New aliases<a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#4-new-aliases" class="hash-link" aria-label="Direct link to 4. New aliases" title="Direct link to 4. New aliases">​</a></h3>
<p>Everything in <strong>nalgebra</strong> ends up being expressed as a matrix, in one way or another. Even
a vector is just the <code>Matrix</code> type setup to have only one column. This is why we have so many
type aliasses like <code>Vector3</code> which is an alias for a matrix with 3 rows and one column.</p>
<p>In <strong>nalgebra 0.26</strong> we have the following dimension-generic type aliases:</p>
<ul>
<li><code>OMatrix&lt;T, R: Dim, C: Dim&gt;</code>: for owned matrices (formerly called <code>MatrixMN</code>), i.e., matrices
that own their components (as opposed to matrix slices that borrow them).</li>
<li><code>SMatrix&lt;T, const R: usize, const C: usize&gt;</code>: for statically-allocated matrices.</li>
<li><code>DMatrix&lt;T&gt;</code>: for dynamically-allocated matrices.</li>
</ul>
<p>All the aliases for specific dimensions (e.g. <code>Vector3</code> for 3D vectors) remain unchanged.</p>
<p>The same applies to vectors: <code>OVector, SVector, DVector</code>. For example a statically-sized vector
with 528 components can be written <code>SVector&lt;f32, 528&gt;</code>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="limitations-why-typenum-is-still-needed">Limitations: why <code>typenum</code> is still needed<a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#limitations-why-typenum-is-still-needed" class="hash-link" aria-label="Direct link to limitations-why-typenum-is-still-needed" title="Direct link to limitations-why-typenum-is-still-needed">​</a></h2>
<p>We no longer use the <code>generic-array</code> crate, but you will notice that <strong>nalgebra</strong> continues
to depend on the <code>typenum</code> crate. This is needed because const-generics support on Rust 1.51
isn't complete yet, and doesn't allow operations on the const-parameters like in the following
<code>push</code> method that adds an element to an array:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">impl</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LENGTH</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">Vector</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LENGTH</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// The { LENGTH + 1 } isn't allowed yet in this context.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Vector</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LENGTH</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">unimplemented!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In order to overcome this limitation, we have to rely on <code>typenum</code> by converting the
integer to a type-level-integer, performing the operation with <code>typenum</code>'s type-level operators,
and then extracting the result as a const value. This roughly looks like this:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token class-name">D</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> </span><span class="token type-definition class-name">ToTypenum</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token type-definition class-name">Output</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> </span><span class="token type-definition class-name">ToConst</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token type-definition class-name">Output</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">ToTypenum</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token number" style="color:#36acaa">1</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token type-definition class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">ToConst</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U1</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token type-definition class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token number" style="color:#36acaa">1</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">ToTypenum</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token number" style="color:#36acaa">2</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token type-definition class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">ToConst</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U2</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token type-definition class-name">Output</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token number" style="color:#36acaa">2</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ... make the same impl. for all values until some arbitrary</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//     limit (currently 127 in nalgebra).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">Vector</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">N</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">R</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Vector</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">N</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Sum</span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">R</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token class-name">ToTypenum</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Output</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U1</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token class-name">ToConst</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Output</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">where</span><span class="token plain"> </span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">R</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ToTypenum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">R</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token class-name">ToTypenum</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Output</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Add</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U1</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token class-name">Sum</span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token class-name">Const</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">R</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token class-name">ToTypenum</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">Output</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">typenum</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">U1</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ToConst</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">unimplemented!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_Q64n"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_oNG0" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_H210"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_Yw6x"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>It's actually less verbose in <strong>nalgebra</strong> because we have some additional traits to hide some
of the complexity going on here. But  the fact remains that without more advanced const-generics
support from the compiler, methods like this <code>push</code> will be more verbose to define, and will be limited
to the values of <code>D</code> (currently the values in <code>[0, 127]</code>) such that <code>Const&lt;D&gt;: TyTypenum</code> is implemented.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next?<a href="https://dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra#whats-next" class="hash-link" aria-label="Direct link to What's next?" title="Direct link to What's next?">​</a></h2>
<p>The const-generics MVP allowed us to significantly improve the ergonomics of statically-sized
matrices and vectors. However, we are still waiting for two features to land to make
<strong>nalgebra</strong> much nicer:</p>
<ul>
<li><strong>Specialization</strong>: with specialization in place, we could get rid of all the <code>DefaultAllocator: Allocator&lt;...&gt;</code>
bounds. This means writing generic code that accepts both statically-sized matrices and dynamically-sized
matrices would become much easier.</li>
<li><strong>Const-generics</strong> (the complete version): being able to write something like <code>[T;&nbsp;{&nbsp;LENGTH&nbsp;+&nbsp;1&nbsp;}]</code>
would allow us to remove the <code>typenum</code> dependency completely.</li>
<li><strong>Const-fn</strong> (the complete version): being able to have trait bounds other than <code>Sized</code> in generic
const-functions would allow us to mark most of <strong>nalgebra</strong>'s methods as <code>const</code>. Right now, only some
constructors are possible.</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in Dimforge \#5 (Feb. 2021 - Mar. 2021)]]></title>
            <link>https://dimforge.com/blog/2021/04/04/this-month-in-dimforge</link>
            <guid>https://dimforge.com/blog/2021/04/04/this-month-in-dimforge</guid>
            <pubDate>Sun, 04 Apr 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the fifth edition of This month in Dimforge! This newsletter provides you with a]]></description>
            <content:encoded><![CDATA[<p>Welcome to the fifth edition of <em>This month in Dimforge</em>! This newsletter provides you with a
summary of important updates that occurred within the Dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>Salva</strong></a> (fluid simulation),
<a href="https://parry.rs/" target="_blank" rel="noopener noreferrer"><strong>Parry</strong></a> (collision-detection), <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>Simba</strong></a> (abstract algebra) crates. This fifth edition will contain updates for
the months of <strong>February and March 2021</strong>.</p>
<p>Help us sustain this work by <strong>sponsoring</strong> us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsors</strong></a> ♥<br>
Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer"><strong>discord</strong></a>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="announcing-nalgebra-sparse-01-">Announcing <strong>nalgebra-sparse</strong> 0.1 🎊<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#announcing-nalgebra-sparse-01-" class="hash-link" aria-label="Direct link to announcing-nalgebra-sparse-01-" title="Direct link to announcing-nalgebra-sparse-01-">​</a></h2>
<p>In February, we silently released a new crate: <a href="https://docs.rs/nalgebra-sparse/0.1.0/nalgebra_sparse/" target="_blank" rel="noopener noreferrer"><strong>nalgebra-sparse</strong></a>.
This new crate is a complete rewrite of sparse-matrix computations with <strong>nalgebra</strong>. It aims to completely replace
the <code>sparse</code> module from the <strong>nalgebra</strong> crate. Here are the most significant features of that new crate:</p>
<ul>
<li><strong>CSR</strong>, <strong>CSC</strong> and <strong>COO</strong> formats, and conversions between them.</li>
<li>Common <strong>arithmetic operations</strong> are implemented: sparse addition, multiplication, and triangular solve.</li>
<li>Sparse <strong>Cholesky decomposition</strong> for CDC sparse matrices.</li>
</ul>
<p>We thank <a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andreas Longva</a> for his amazing work in this crate!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="announcing-rapier-07-️">Announcing Rapier 0.7 ⚔️<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#announcing-rapier-07-%EF%B8%8F" class="hash-link" aria-label="Direct link to Announcing Rapier 0.7 ⚔️" title="Direct link to Announcing Rapier 0.7 ⚔️">​</a></h2>
<p>The versions <strong>0.6</strong> (which we didn't communicate about) and <strong>0.7</strong> of <strong>Rapier</strong> come with very exciting new features!
Here is a summary:</p>
<ul>
<li><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#joint-motors"><strong>Joint motors</strong></a>: control the position and/or velocity of a joint.</li>
<li><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#dominance-groups"><strong>Dominance groups</strong></a>: make one dynamic rigid-body immune to the forces generated by some other dynamic rigid-bodies.</li>
<li><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#contact-modification"><strong>Contact modification</strong></a>: simulate conveyor belts, one-way platforms and other special effects.</li>
<li><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#collider-modification"><strong>Collider modification</strong></a>: modify a collider after it has been added to the <code>ColliderSet</code>.</li>
<li><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#continuous-collision-detection"><strong>Continuous collision detection</strong></a>: don't miss any collision because of fast-moving bodies.</li>
<li><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#large-colliders-support"><strong>Large colliders support</strong></a>: colliders with very large shapes can be used efficiently now.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="joint-motors">Joint motors<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#joint-motors" class="hash-link" aria-label="Direct link to Joint motors" title="Direct link to Joint motors">​</a></h3>
<p><strong>Joint motors</strong> allow you to make a joint move the rigid-bodies it is attached to by:</p>
<ul>
<li>Choosing the relative velocity of the rigid-bodies along the joint's free degrees of freedoms.</li>
<li>Or choosing a desired relative position of the rigid-bodies, along the joints's free degrees of freedoms.</li>
</ul>
<p>For example, you can set the target angular velocity, or the target angle of a <code>RevoluteJoint</code>. One typical
use-case is to make a simulated car move by making the joint rotate its wheels.</p>
<p>The following illustrates examples of motorized ball joints, revolute joints, and prismatic joints:</p>
<p><img decoding="async" loading="lazy" alt="joint motors" src="https://dimforge.com/assets/images/joint_motors-be3d13d872009f736e1c1a962089694e.gif" width="1054" height="572" class="img_XsDP"></p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="dominance-groups">Dominance groups<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#dominance-groups" class="hash-link" aria-label="Direct link to Dominance groups" title="Direct link to Dominance groups">​</a></h3>
<p><strong>Dominance groups</strong> is a non-physical feature that allows you to ignore <a href="https://en.wikipedia.org/wiki/Newton's_laws_of_motion" target="_blank" rel="noopener noreferrer">Newton's third law of motion</a> (force reciprocity)
for chosen pairs of rigid-bodies.</p>
<p>Each dynamic rigid-body can be given a dominance group number in <code>[-127; 127]</code> (the default is <code>0</code>). If two dynamic
rigid-bodies are in  contact, the one with the highest dominance group number will act as if it has an infinite mass,
making it immune to  the forces the  other body would apply on it. If both bodies are have the same dominance group
number, then their contacts  will work in the usual way (both are affected  by opposite forces with equal magnitude).</p>
<p>Dominance is a completely unrealistic feature. But it can be used to simulate specific effects in games. An example is
the simulation of a player represented as a dynamic rigid-body that cannot be "pushed back" by some other dynamic rigid-bodies
part of the environment.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="contact-modification">Contact modification<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#contact-modification" class="hash-link" aria-label="Direct link to Contact modification" title="Direct link to Contact modification">​</a></h3>
<p><strong>Contact modification</strong> allows you to modify the properties of a contact (or completely delete a contact)
after it has been computed by the narrow-phase, but before it reaches the constraints  solver. Typical use-cases
of contact modification are:</p>
<ul>
<li>The simulation of <strong>conveyor belts</strong> by modifying the <code>tangent_velocity</code> field of a contact.</li>
<li>The simulation of <strong>one-way platforms</strong> by removing some contacts depending on their contact normal.</li>
<li>The simulation of  <strong>materials with smooth friction/restitution coefficient</strong> variations by modifying the friction
and/or restitution coefficient of a contact, bypassing the <code>CoefficientCombineRule</code> of the colliders involved in
the contact.</li>
</ul>
<p>The <a href="https://github.com/dimforge/rapier/blob/master/examples3d/one_way_platforms3.rs" target="_blank" rel="noopener noreferrer">one-way platforms example</a>
illustrates the first two use-cases enumerated above. Both platforms act as conveyor belts (i.e.
they move objects towards predefined directions), and both platforms are one-way platforms:</p>
<p><img decoding="async" loading="lazy" alt="contact_modification" src="https://dimforge.com/assets/images/contact_modifications-50f5a9d44872d53035895a54bd6085ce.gif" width="1072" height="294" class="img_XsDP"></p>
<p>(Note that the gravity is set to opposite directions on both sides of the simulation to make it more interesting).</p>
<p>These contact modifications are possible thanks to the introduction of a new <a href="https://docs.rs/rapier3d/0.7.2/rapier3d/pipeline/trait.PhysicsHooks.html" target="_blank" rel="noopener noreferrer"><code>PhysicsHooks</code></a>
trait that defines methods called during a timestep to filter contact pairs, filter intersection pairs,
and modify the contacts to be processed by the constraints solver.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="collider-modification">Collider modification<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#collider-modification" class="hash-link" aria-label="Direct link to Collider modification" title="Direct link to Collider modification">​</a></h3>
<p>Before Rapier 0.7, it wasn't possible to <strong>modify a collider</strong> after it was added to the <code>ColliderSet</code>.
Therefore, changing a collider's shape, its position relative to the rigid-body it is attached to,
or even changing its collision groups, was only possible by removing the collider and inserting a
new one. That was both inconvenient and inefficient.</p>
<p>With <strong>Rapier 0.7</strong>, these modifications are now possible, and will automatically be taken into account
by the physics engine.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="continuous-collision-detection">Continuous collision detection<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#continuous-collision-detection" class="hash-link" aria-label="Direct link to Continuous collision detection" title="Direct link to Continuous collision detection">​</a></h3>
<p><strong>Fast moving bodies</strong> are generally difficult to simulate because the physics engine may not be able to detect
some collisions. Indeed, the physics simulation operates by <strong>discretizing the motion</strong> of
rigid-bodies at fixed time intervals (equal to the timestep length <code>dt</code>). Therefore, a fast-moving rigid-body
may end up ignoring some contacts that would have happened in-between two discrete positions along this motion.
This is known as <em>the tunnelling problem</em>.</p>
<p>The following example illustrates this problem. The blue and green balls are colliders attached to
fast-moving rigid-bodies. The simulation is run step-by-step for clarity. It is clear that the blue ball is missing a lot of collisions,
resulting  in the pyramids not being hit at all! The green ball is a sensor configured in such a way that all the
cubes it traverses are recolored in dark-blue. As you can see, only the pyramid at middle of the top row has some of its cubes
recolored to dark-blue:</p>
<p><img decoding="async" loading="lazy" alt="no CCD" src="https://dimforge.com/assets/images/no_ccd-80dfd815fea073049fa15bc0e31306f0.gif" width="1162" height="572" class="img_XsDP"></p>
<p><strong>Continuous collision detection (CCD)</strong> is a technique that aims to eliminate this tunnelling problem.
CCD will take into account the actual <strong>continuous motion</strong> of the rigid-bodies (and their colliders)
in order to detect every single contact that must happen in their continuous trajectory. With CCD enabled,
the example above behaves as we would expect: the blue collider destroys the pyramids, the green sensor
recolors in dark-blue all the cubes it encounters on its continuous path:</p>
<p><img decoding="async" loading="lazy" alt="CCD" src="https://dimforge.com/assets/images/ccd-4b72bdb715f91c5abfd1527e258740e9.gif" width="1162" height="572" class="img_XsDP"></p>
<p>The <strong>CCD</strong> implementation in <strong>Rapier</strong>:</p>
<ul>
<li>Is <strong>non-linear</strong> because it takes into account both the translational and the rotational movements of the
rigid-bodies/colliders with CCD enabled. Most other physics engines use linear CCD which is slightly
more efficient but yields less realistic results (because rotation are ignored).</li>
<li>Works for <strong>colliders</strong> and <strong>sensor colliders</strong> (many other physics engines don't support CCD for
sensors).</li>
<li>Relies on <strong>motion clamping</strong>. It means that CCD will find the first time of impact between a fast-moving
collider and all the other colliders. The fast-moving rigid-body will be advanced to that time of
impact, and all the remaining time will be dropped for that rigid-body. In other words, its motion is
"clamped" to the first time it hits something.</li>
</ul>
<p>It is possible to let the CCD resolution run multiple simulation substeps (implying an increased computational
cost) in order to reduce the amount of time removed by the clamping procedure.</p>
<p>Currently, our CCD implementation will work with all collider shapes except heightfields and halfspaces. Support
for these two shape types will be added soon.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="large-colliders-support">Large colliders support<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#large-colliders-support" class="hash-link" aria-label="Direct link to Large colliders support" title="Direct link to Large colliders support">​</a></h3>
<p>Before Rapier 0.7, using a collider with a very large shape (for example a 1000x100x1000 3D heightfield)
would result in extremely poor performances. This would make <strong>Rapier</strong> unusable in situations
where large terrains were involved.</p>
<p>This is now fixed in <strong>Rapier 0.7</strong> thanks to a massive improvement of the way our Broad-Phase algorithm
(a variant of <a href="https://en.wikipedia.org/wiki/Sweep_and_prune" target="_blank" rel="noopener noreferrer">Sweep-And-Prune</a>) handles these large
shapes. This also means that shapes with virtually infinite bounds (like half-spaces, aka., planes)
can now be used as collider shapes without any performance issue.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next">​</a></h2>
<p>At the beginning of this year, we announced our
<a href="https://www.dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#rapier-roadmap-for-2021" target="_blank" rel="noopener noreferrer">2021 roadmap for Rapier</a>.
So far we implemented and released all the features that were announced to be available in April, with the addition of joint
motors. We have two main goals for next month:</p>
<ul>
<li>Const generics (<code>min_const_generics</code>) is now stabilized. Therefore we intend to integrate it to <strong>nalgebra</strong>.
This will allow us to use regular Rust arrays <code>[T; DIM]</code> parametrized by integers instead of <code>GenericArrays</code>
parametrized by type-level integers from <code>typenum</code>.</li>
<li>Implement <strong>joint limits</strong> for the revolute joints and ball joints, allowing the user to restrict the
range of possible relative orientation of the rigid-bodies attached by these joints. Joint limits are already
implemented for prismatic joints.</li>
</ul>
<p>In addition to this, we would like to:</p>
<ul>
<li>Improve the <strong>JS bindings</strong> of Rapier by making it possible to read contact information in JS, and by allowing the
use of JS closures as <code>PhysicsHooks</code>.</li>
<li>Start the implementation of an <strong>Inverse Kinematics</strong> algorithm (probably the FABRIK method).</li>
</ul>
<p>We are aware that the user-guides for <strong>Rapier</strong> really need to be improved now that it has a lot of new
<em>advanced</em> features like CCD, dominance, contact modification, etc. Unfortunately we didn't have the time
to improve the docs during the past two months. We intend to start addressing this in details in May.</p>
<hr>
<h1>Thanks</h1>
<p>We would like to thank the whole community and code contributors. In particular, thanks to the code contributors from
the past two months<sup><a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#user-content-fn-1-757068" id="user-content-fnref-1-757068" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/alec-deason" target="_blank" rel="noopener noreferrer">alec-deason</a></li>
<li><a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andlon</a></li>
<li><a href="https://github.com/aweinstock314" target="_blank" rel="noopener noreferrer">aweinstock314</a></li>
<li><a href="https://github.com/bastikr" target="_blank" rel="noopener noreferrer">bastikr</a></li>
<li><a href="https://github.com/ChristopherRabotin" target="_blank" rel="noopener noreferrer">ChristopherRabotin</a></li>
<li><a href="https://github.com/Cupnfish" target="_blank" rel="noopener noreferrer">Cupnfish</a></li>
<li><a href="https://github.com/apps/dependabot" target="_blank" rel="noopener noreferrer">dependabot[bot]</a></li>
<li><a href="https://github.com/emilk" target="_blank" rel="noopener noreferrer">emilk</a></li>
<li><a href="https://github.com/extrawurst" target="_blank" rel="noopener noreferrer">extrawurst</a></li>
<li><a href="https://github.com/guissalustiano" target="_blank" rel="noopener noreferrer">guissalustiano</a></li>
<li><a href="https://github.com/iMplode-nZ" target="_blank" rel="noopener noreferrer">iMplode-nZ</a></li>
<li><a href="https://github.com/joseluis" target="_blank" rel="noopener noreferrer">joseluis</a></li>
<li><a href="https://github.com/mookerji" target="_blank" rel="noopener noreferrer">mookerji</a></li>
<li><a href="https://github.com/paq" target="_blank" rel="noopener noreferrer">paq</a></li>
<li><a href="https://github.com/Ralith" target="_blank" rel="noopener noreferrer">Ralith</a></li>
<li><a href="https://github.com/Recmo" target="_blank" rel="noopener noreferrer">Recmo</a></li>
<li><a href="https://github.com/rezural" target="_blank" rel="noopener noreferrer">rezural</a></li>
<li><a href="https://github.com/russellb23" target="_blank" rel="noopener noreferrer">russellb23</a></li>
<li><a href="https://github.com/taiki-e" target="_blank" rel="noopener noreferrer">taiki-e</a></li>
<li><a href="https://github.com/Waridley" target="_blank" rel="noopener noreferrer">Waridley</a></li>
</ul>
<ul>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on open-source exclusively.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-757068">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2021/04/04/this-month-in-dimforge#user-content-fnref-1-757068" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in Dimforge \#4 (Dec. 2020 - Jan. 2021)]]></title>
            <link>https://dimforge.com/blog/2021/01/29/this-month-in-dimforge</link>
            <guid>https://dimforge.com/blog/2021/01/29/this-month-in-dimforge</guid>
            <pubDate>Fri, 29 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the fourth edition of This month in Dimforge! This newsletter provides you with a]]></description>
            <content:encoded><![CDATA[<p>Welcome to the fourth edition of <em>This month in Dimforge</em>! This newsletter provides you with a
summary of important updates that occurred within the Dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>Salva</strong></a> (fluid simulation),
<a href="https://parry.rs/" target="_blank" rel="noopener noreferrer"><strong>Parry</strong></a> (collision-detection), <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>Simba</strong></a> (abstract algebra) crates. This fourth edition will contain updates for
the months of December 2020 and January 2021.</p>
<p>Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord</a>!<br>
You can support us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a> ♥</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="announcing-parry-010">Announcing Parry 0.1.0<a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#announcing-parry-010" class="hash-link" aria-label="Direct link to Announcing Parry 0.1.0" title="Direct link to Announcing Parry 0.1.0">​</a></h2>
<p>During the past two months we have been working on a new crate. Say hello to <a href="https://parry.rs/" target="_blank" rel="noopener noreferrer">Parry</a>:</p>
<center><a href="https://parry.rs/"><img src="https://parry.rs/img/logo_parry.svg" width="301px"></a></center>
<p><strong>Parry</strong> is a complete remake of our <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer"><strong>ncollide</strong> crate</a>. It is declined in
four crates: <code>parry2d</code>, <code>parry3d</code>, <code>parry2d-f64</code>, <code>parry3d-f64</code>, depending on whether you want,
2D or 3D geometry, and <code>f32</code> or <code>f64</code> accuracy. <strong>Parry</strong> is born from the merge of most of the
geometry code we had in <strong>Rapier</strong>, and some of the geometric code we ported from <strong>ncollide</strong>.</p>
<p>As of today, <strong>Parry</strong> is the geometric library used by our <strong>Rapier</strong> physics engine (and
<strong>Rapier</strong> itself includes much less geometry code than before). It is the crate we will continue
to improve in the long-term. The <strong>ncollide</strong> crate is now in passive maintenance mode.</p>
<p><strong>Parry</strong> doesn't have any user-guide right now, but we intend to write one in February.
Here is a table comparing the features of <strong>ncollide</strong> to the features of <strong>Parry</strong>:</p>
<table><thead><tr><th>Features</th><th>Parry</th><th>ncollide</th></tr></thead><tbody><tr><td>Bounding volumes</td><td>✅</td><td>✅</td></tr><tr><td>Distance computation</td><td>✅</td><td>✅</td></tr><tr><td>Intersection test</td><td>✅</td><td>✅</td></tr><tr><td>Sweep test</td><td>✅</td><td>✅</td></tr><tr><td>Contact computation</td><td>✅</td><td>✅</td></tr><tr><td>Contact manifolds computation</td><td>✅</td><td>✅</td></tr><tr><td>Ray-casting</td><td>✅</td><td>✅</td></tr><tr><td>Point-projection</td><td>✅</td><td>✅</td></tr><tr><td>Approximate Convex Decomposition</td><td>VHACD</td><td>HACD</td></tr><tr><td>Voxelization</td><td>✅</td><td>❌</td></tr><tr><td>Mass properties computation</td><td>✅</td><td>❌</td></tr><tr><td>All shapes are serializable</td><td>✅</td><td>❌</td></tr><tr><td>Generic wrt. the scalar type</td><td>❌</td><td>✅</td></tr><tr><td>Procedural mesh generation</td><td>❌</td><td>✅</td></tr><tr><td><code>NarrowPhase</code>, <code>BroadPhase</code>, <code>CollisionWorld</code></td><td>❌</td><td>✅</td></tr></tbody></table>
<p>In addition, <strong>Parry</strong> implements much more efficient algorithms for contact
manifold generation, and a more robust 3D convex-hull implementation.</p>
<p>The pipelining features of <strong>ncollide</strong> like the <code>CollisionWorld</code> have not been included in <strong>Parry</strong>
because we are still unsure where we want this to go. We don't want it to just be an inferior
version of the pipelining we already have in <strong>Rapier</strong>, so we need more time to think
about it.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-050">Rapier 0.5.0<a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#rapier-050" class="hash-link" aria-label="Direct link to Rapier 0.5.0" title="Direct link to Rapier 0.5.0">​</a></h2>
<p>Similar to <strong>Parry</strong>, we released two new creates for <strong>Rapier</strong>: <code>rapier2d-f64</code> and <code>rapier3d-f64</code>. These crates
are for 2D and 3D physics simulation using 64-bit floats.</p>
<p>Thanks to the switch to <strong>Parry</strong>, the version of 0.5.0 of <strong>Rapier</strong> comes with a fair
amount of new features. Here are some of the most important ones:</p>
<ul>
<li>The <code>QueryPipeline</code> is now able to perform scene-wide <strong>shape-casts</strong> (aka. sweep tests),
<strong>point projections</strong>, and <strong>shape intersection</strong> tests. Note that shape-casting is
essential for writing a character controller based on kinematic bodies.</li>
<li>It is now possible to use <strong>custom shapes</strong> with <strong>Rapier</strong>.</li>
<li>It is now possible to use a <strong>convex polygon</strong> (in 2D) or <strong>convex polyhedron</strong> (in 3D) as
a collider shape.</li>
<li>It is now possible to use <strong>concave shapes</strong> after they have been decomposed into convex
parts. A convenient <code>ColliderBuilder::convex_decomposition</code> is provided to perform an
approximate convex decomposition automatically.</li>
<li>It is now possible to use different rules (average, min, max, multiply) for
<strong>combining two friction and restitution coefficients</strong>.</li>
<li>It is now possible to <strong>scale the gravity</strong> applied to each rigid-body. Setting this scale
factor to zero will effectively make the rigid-body unaffected by gravity.</li>
</ul>
<p>You may see the <a href="https://github.com/dimforge/rapier/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer">CHANGELOG of Rapier</a> for more
details on other changes we made in 0.5.0.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="js-bindings-03-for-rapier-05">JS bindings 0.3 for Rapier 0.5<a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#js-bindings-03-for-rapier-05" class="hash-link" aria-label="Direct link to JS bindings 0.3 for Rapier 0.5" title="Direct link to JS bindings 0.3 for Rapier 0.5">​</a></h2>
<p>Because <strong>Rapier</strong> 0.5.0 contained so many new features, we updated our JS bindings to expose most of
these new features. You may see the
<a href="https://github.com/dimforge/rapier.js/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer">CHANGELOG of rapier.js</a> for the details
on all changes we made in 0.3.0 to expose these new features.</p>
<p>In addition, we released two new NPM packages for the JS bindings of rapier: <code>@dimforge/rapier2d-compat</code> and
<code>@dimforge/rapier3d-compat</code>. Thanks to <a href="https://github.com/maun" target="_blank" rel="noopener noreferrer">Manuel Adameit</a> for making this possible. These
two packages are designed to be easier to integrate into any build system (with or without bundler).
Instead of containing a <code>.js</code> and a <code>.wasm</code> file, these <code>-compat</code> packages only contain one <code>.js</code> which itself
contains the WASM encoded in Base64.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next<a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next">​</a></h2>
<p>At the beginning of this year, we announced our
<a href="https://www.dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#rapier-roadmap-for-2021" target="_blank" rel="noopener noreferrer">2021 roadmap for Rapier</a>.
So far we implemented and released all the features that were announced to be available in February. So we will
continue to follow this roadmap with the following objectives for next month:</p>
<ul>
<li>Add the support of <strong>contact modification</strong> in <strong>Rapier</strong>. This will allow you to easily simulate, e.g., conveyor
belts and one-way platforms.</li>
<li>Add the support for <strong>dominance</strong> in <strong>Rapier</strong>. This will make some object (typically the player modeled as a dynamic
body) immune to forces applied by a selection of other objects.</li>
</ul>
<p>These two features should actually be fairly quick to implement considering we already made some modifications
to prepare for this future work. Therefore, we have a few more objective for next month:</p>
<ul>
<li>Improve the <strong>user-guides of Rapier</strong> and make a user-guide for <strong>Parry</strong>.</li>
<li>Start the SIMD optimization work on <strong>Salva</strong>.</li>
<li>Review, and publish a new crate: <code>nalgebra-sparse</code> for sparse matrix computation. Currently, <code>nalgebra</code> has a limited
support of sparse matrices when its <code>sparse</code> feature is enabled. Thanks to the
<a href="https://github.com/dimforge/nalgebra/pull/823" target="_blank" rel="noopener noreferrer">huge contribution</a> of <a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andreas Longva</a>,
our sparse matrix support will be completely rewritten and extracted into a new crate.</li>
</ul>
<hr>
<h1>Thanks</h1>
<p>We would like to thank <a href="https://embark-studios.com/" target="_blank" rel="noopener noreferrer">Embark Studio</a> for being our new donor on
<a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>! This helps us tremendously to sustain our 100% free and
open-source work.</p>
<p></p>
<p>We would like to thank the whole community and code contributors. In particular, thanks to the code contributors from
the past two months<sup><a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#user-content-fn-1-22b948" id="user-content-fnref-1-22b948" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/Bobox214" target="_blank" rel="noopener noreferrer">Bobox214</a></li>
<li><a href="https://github.com/chinedufn" target="_blank" rel="noopener noreferrer">chinedufn</a></li>
<li><a href="https://github.com/Fedcomp" target="_blank" rel="noopener noreferrer">Fedcomp</a></li>
<li><a href="https://github.com/maun" target="_blank" rel="noopener noreferrer">maun</a></li>
<li><a href="https://github.com/rezural" target="_blank" rel="noopener noreferrer">rezural</a></li>
<li><a href="https://github.com/SimonWoodburyForget" target="_blank" rel="noopener noreferrer">SimonWoodburyForget</a></li>
<li><a href="https://github.com/smokku" target="_blank" rel="noopener noreferrer">smokku</a></li>
<li><a href="https://github.com/tomitheninja" target="_blank" rel="noopener noreferrer">tomitheninja</a></li>
<li>Troels Peter Jessen</li>
</ul>
<ul>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on open-source exclusively.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-22b948">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2021/01/29/this-month-in-dimforge#user-content-fnref-1-22b948" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Physics simulation with Rapier: 2021 roadmap]]></title>
            <link>https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap</link>
            <guid>https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap</guid>
            <pubDate>Fri, 01 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[🎉🎉🎉 Happy new year everyone! 🎉🎉🎉]]></description>
            <content:encoded><![CDATA[<p><strong>🎉🎉🎉 Happy new year everyone! 🎉🎉🎉</strong></p>
<p>The year 2020 is over, so it is time to see what we did so far on our <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a> physics engine,
and what are our plans for 2021!</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-in-2020">Rapier in 2020<a href="https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#rapier-in-2020" class="hash-link" aria-label="Direct link to Rapier in 2020" title="Direct link to Rapier in 2020">​</a></h3>
<p><img decoding="async" loading="lazy" alt="rapier logo" src="https://dimforge.com/assets/images/rapier_logo_color_textpath_dark-67093214cb8594cb6bf7b952ff3e3027.svg" width="527" height="131" class="img_XsDP"></p>
<p><a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a> is a free and open-source physics engine for games, animation and robotics, written
entirely with the <a href="https://rust-lang.org/" target="_blank" rel="noopener noreferrer">Rust</a> programming language. It focuses on performance, portability,
and (optional) cross-platform determinism. We currently provide four Rust crates for Rapier and two NPM packages:</p>
<ul>
<li><a href="https://crates.io/crates/rapier2d" target="_blank" rel="noopener noreferrer">rapier2d</a> is optimized for 2D physics.</li>
<li><a href="https://crates.io/crates/rapier3d" target="_blank" rel="noopener noreferrer">rapier3d</a> is optimized for 3D physics.</li>
<li><a href="https://crates.io/crates/bevy_rapier2d" target="_blank" rel="noopener noreferrer">bevy_rapier2d</a> for using <strong>rapier2d</strong> with the <a href="https://bevyengine.org/" target="_blank" rel="noopener noreferrer">Bevy</a> game engine.</li>
<li><a href="https://crates.io/crates/bevy_rapier3d" target="_blank" rel="noopener noreferrer">bevy_rapier3d</a> for using <strong>rapier3d</strong> with the <a href="https://bevyengine.org/" target="_blank" rel="noopener noreferrer">Bevy</a> game engine.</li>
<li><a href="https://www.npmjs.com/package/@dimforge/rapier2d" target="_blank" rel="noopener noreferrer">@dimforge/rapier2d</a> for using the WASM version of <strong>rapier2d</strong> in your browser with JavaScript.</li>
<li><a href="https://www.npmjs.com/package/@dimforge/rapier3d" target="_blank" rel="noopener noreferrer">@dimforge/rapier3d</a> for using the WASM version of <strong>rapier3d</strong> in your browser with JavaScript.</li>
</ul>
<p>We announced Rapier <a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine" target="_blank" rel="noopener noreferrer">for the first time</a> at
the end of August 2020. Since then, we implemented some essential features like <strong>ray-casting</strong>,
<strong>collision filters</strong>, access to <strong>contact information</strong>, <strong>rotation locking</strong>, and the support of shapes like
<strong>cylinders and cones</strong>. We made sure our cross-platform determinism feature works properly on the new Apple M1
ARM processor. And we set up <strong>continuous benchmarking</strong> visible on the <a href="https://www.rapier.rs/benchmarks/" target="_blank" rel="noopener noreferrer">Rapier website</a>
to make sure incremental changes don't destroy performances.</p>
<p>During December 2020 we started working on a large refactoring of the geometry-related code existing
partly inside of <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer">ncollide</a> and partly inside of <strong>Rapier</strong> itself. This refactoring is still
work-in-progress, as part of the <a href="https://github.com/sebcrozet/cdl" target="_blank" rel="noopener noreferrer">cdl</a> repository (the name isn't definitive, don't
hesitate to share your opinion <a href="https://github.com/sebcrozet/cdl/issues/1" target="_blank" rel="noopener noreferrer">on that issue</a>). This work will be ready for
the beginning of February 2021, and will allow us to proceed with our 2021 goals.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-roadmap-for-2021">Rapier roadmap for 2021<a href="https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#rapier-roadmap-for-2021" class="hash-link" aria-label="Direct link to Rapier roadmap for 2021" title="Direct link to Rapier roadmap for 2021">​</a></h3>
<p>We have very exciting goals for Rapier in 2021! Basically, at the end of 2021 we want Rapier to have all the features
one would expect from a physics engine for games. This implies achieving feature-parity with popular C++ physics engines
like <a href="https://github.com/erincatto/box2d" target="_blank" rel="noopener noreferrer">Box2d</a>, <a href="https://github.com/bulletphysics/bullet3" target="_blank" rel="noopener noreferrer">Bullet Physics</a>, and
<a href="https://github.com/NVIDIAGameWorks/PhysX" target="_blank" rel="noopener noreferrer">PhysX</a>. There is one exception though: we don't plan to support running
physics simulations on the GPU yet. Though this may become a focus at some point in the next years.</p>
<p>Here is a list of some of the most important features we are missing today. This includes when they should become
available (ETA):</p>
<table><thead><tr><th>Feature</th><th>Description</th><th>ETA</th></tr></thead><tbody><tr><td><strong>64-bits floats</strong></td><td>A <code>f64</code> version of Rapier for greater accuracy.</td><td><strong>February</strong></td></tr><tr><td><strong>Sweep tests</strong></td><td>Similar to ray-cast, except that we are casting a whole shape instead of just a ray. This is often used to design character controllers.</td><td><strong>February</strong></td></tr><tr><td><strong>Intersection queries</strong></td><td>To retrieve all colliders intersecting a given shape.</td><td><strong>February</strong></td></tr><tr><td><strong>Convex polyhedron</strong></td><td>To use an arbitrary convex polyhedron as a collider shape.</td><td><strong>February</strong></td></tr><tr><td><strong>Custom shapes</strong></td><td>To allow the user to define their own shape types.</td><td><strong>February</strong></td></tr><tr><td><strong>Contact modification</strong></td><td>To allow the user to modify/delete a contact before it is handed over to the constraints solver.</td><td><strong>March</strong></td></tr><tr><td><strong>Dominance</strong></td><td>To make one dynamic rigid-body act like a kinematic body wrt. another dynamic rigid-body.</td><td><strong>March</strong></td></tr><tr><td><strong>CCD</strong></td><td>To prevent fast-moving objects from missing collisions.</td><td><strong>April</strong></td></tr><tr><td><strong>Joint limits, motors</strong></td><td>To simulate more realistic vehicles, ragdolls, etc.</td><td><strong>May</strong></td></tr><tr><td><strong>Reduced-coordinates articulations</strong></td><td>To simulate more realistic robots with no joint drift.</td><td><strong>August</strong></td></tr></tbody></table>
<p>Note that the <strong>contact modification</strong> feature is what will allow you to simulate <strong>one-way platforms</strong>,
<strong>conveyor belts</strong>, as well as colliders with <strong>non-uniform restitution and friction</strong> coefficients.</p>
<p>We also intend to implement some higher-level features like a <strong>character controller</strong> and a <strong>vehicle controller</strong>.
Both should be available starting <strong>October</strong>. Most games will need controllers obeying their specific custom rules, so
it is impossible to design a universal solution. Our goal is to provide something useful to start with, to serve as a
basis to more specific character and vehicle controllers.</p>
<p>Finally, the last months of 2021 should be mostly dedicated to improving documentations and fixing bugs.
Our bevy plugins and JS bindings will be updated progressively through the year in order to always use the latest
version of Rapier.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="what-about-fluids-simulation">What about fluids simulation?<a href="https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#what-about-fluids-simulation" class="hash-link" aria-label="Direct link to What about fluids simulation?" title="Direct link to What about fluids simulation?">​</a></h3>
<center><img src="https://dimforge.com/img/logo_salva_square.svg" title="Salva logo." height="200px"></center>
<p>We also develop <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer">Salva</a>, a 2D and 3D fluids simulation engine written in Rust. Salva implements <strong>two-ways
coupling</strong> with Rapier. This means that fluids from Salva can be affected by contact forces originating from
Rapier, and rigid-bodies from Rapier can be affected by forces originating from fluids. Our three 2021 objectives for Salva are:</p>
<ol>
<li><strong>Cross-platform determinism:</strong> just like Rapier, we want to make Salva optionally cross-platform deterministic
(under the same assumption of IEEE 754-2008 compliance).</li>
<li><strong>Performance improvements:</strong> we need to apply to Salva what we leaned from Rapier with explicit SIMD
optimizations.</li>
<li><strong>Stability improvements:</strong> to improve the quality of the fluids simulation itself and of the two-ways coupling
with Rapier.</li>
</ol>
<p>We intend to work on the first two objectives from <strong>February</strong> to <strong>May</strong> 2021. The stability improvements
will be a progressive work during the rest of the year.</p>
<p>As of today we don't plan to create JavaScript bindings for Salva. However, this can happen if there is enough demand
from the community.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="conclusion">Conclusion<a href="https://dimforge.com/blog/2021/01/01/physics-simulation-with-rapier-2021-roadmap#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h3>
<p>The Rust game-development community is growing every days and the  ecosystem is maturing steadily with major crates like
the <a href="https://amethyst.rs/" target="_blank" rel="noopener noreferrer">Amethyst</a> and <a href="https://bevyengine.org/" target="_blank" rel="noopener noreferrer">Bevy</a>
game engine, <a href="https://github.com/EmbarkStudios/rust-gpu" target="_blank" rel="noopener noreferrer">rust-gpu</a> project, and many other incredible projects. By working on
<a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer">Rapier</a> (and some of its dependencies) full-time we aim to provide a high-quality free, open-source,
community-friendly, cross-platform game physics simulation library. The year 2021 will allow us to make Rapier reach a
level of feature-completeness comparable to its main C++ alternatives.</p>
<p>If you would like to support us with the development of <strong>Rapier</strong>, please consider sponsoring us on
<a href="https://github.com/sponsors/dimforge" target="_blank" rel="noopener noreferrer">GitHub sponsor</a>. Thank again to all our existing, past, and
future sponsors for making all of this possible.</p>
<p><strong>Have a great year 2021! 🥳</strong></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in Dimforge \#3 (November 2020)]]></title>
            <link>https://dimforge.com/blog/2020/12/01/this-month-in-dimforge</link>
            <guid>https://dimforge.com/blog/2020/12/01/this-month-in-dimforge</guid>
            <pubDate>Tue, 01 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the third edition of This month in Dimforge! This is the third edition of this newsletter that replaces the]]></description>
            <content:encoded><![CDATA[<p>Welcome to the third edition of <em>This month in Dimforge</em>! This is the third edition of this newsletter that replaces the
<em>This month in rustsim</em> we published before <em>Dimforge</em> was created. This will provide you with a
summary of important updates that occurred within the dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>salva</strong></a> (fluid simulation), <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer"><strong>ncollide</strong></a> (collision-detection),
<a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>simba</strong></a> (abstract algebra) crates. This third edition will contain updates for
the month of November 2020.</p>
<p>Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord</a> and on our <a href="https://discourse.nphysics.org/" target="_blank" rel="noopener noreferrer">user forum</a>!<br>
You can support us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-040">Rapier 0.4.0<a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#rapier-040" class="hash-link" aria-label="Direct link to Rapier 0.4.0" title="Direct link to Rapier 0.4.0">​</a></h2>
<p>The version of Rapier 0.4.0 includes a few important new features:</p>
<ul>
<li>The ability to <strong>read contact and proximity information</strong> from the <code>NarrowPhase</code>. In particular, it is possible to retrieve
one specific contact pair (given two collider handles), or to retrieve all the contact pairs involving
one specific  collider.</li>
<li>The ability to <strong>lock translations and/or rotations</strong> caused by forces on a rigid-body. For example, it is possible to lock all
the rotations of a rigid-body except along one or two coordinate axes, without using joints. Locking rotations
has been a common feature request from our community, for games with a player modeled as a dynamic rigid-body which
should not rotate.</li>
</ul>
<p>In the <a href="https://github.com/dimforge/rapier/blob/master/examples3d/locked_rotations3.rs" target="_blank" rel="noopener noreferrer">following demo</a>, you can see
a blue cuboid with all its translations locked, and all its rotations locked except along the <code>x</code> coordinate axis. The
capsule (initialized in a tilted position) on the other hand has all its rotations locked. All this is achieved without
any joints:</p>
<center><img src="https://dimforge.com/img/locked_rotations.gif" alt="Locked rotations demo"></center>
<p>Finally, we tested Rapier on the new <strong>Apple M1</strong> chip. It worked very well except for some cases where the <strong>cross-platform
determinism</strong> of Rapier broke. We fixed this problem, which means that enabling the <code>enhanced-determinism</code> of Rapier will allow
you to get the exact same results for the same simulations running on, e.g., MacOs with an Apple M1 ARM processor, and Ubuntu with
an AMD Ryzen 9 X86 processor!</p>
<p>You may see the <a href="https://github.com/dimforge/rapier/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer">CHANGELOG of Rapier</a> for more details
on other changes we made in Rapier 0.4.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="bevy-rapier-plugin-060">Bevy rapier plugin 0.6.0<a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#bevy-rapier-plugin-060" class="hash-link" aria-label="Direct link to Bevy rapier plugin 0.6.0" title="Direct link to Bevy rapier plugin 0.6.0">​</a></h2>
<p>We released the version 0.6.0 of our Bevy plugin for Rapier <a href="https://github.com/dimforge/bevy_rapier" target="_blank" rel="noopener noreferrer">bevy_rapier</a>.
This includes:</p>
<ul>
<li>The automatic removal of rigid-bodies, colliders, and joints from the Rapier structures when the entity they are
attached to are removed from the Bevy ECS. Thanks to <a href="https://github.com/superdump" target="_blank" rel="noopener noreferrer">Robert Swain</a> for this
contribution!</li>
<li>The ability to attach multiple colliders to a single rigid-body using Bevy hierarchy: one just has to spawn an
entity with a <code>RigidBodyBuilder</code> component, and multiple children entities with one <code>ColliderBuild</code> component each.
Thanks to <a href="https://github.com/blamelessgames" target="_blank" rel="noopener noreferrer">@blamelessgames</a> for this contribution!</li>
<li>The adaptive change of number of timesteps executed by the Rapier plugin at each render loop iteration
is now disabled by default: you can re-enable it by setting <code>RapierConfiguration.time_dependent_number_of_timesteps</code>
to <code>true</code>.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="salva-050">Salva 0.5.0<a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#salva-050" class="hash-link" aria-label="Direct link to Salva 0.5.0" title="Direct link to Salva 0.5.0">​</a></h2>
<p>The integration of Rapier with our particle-based fluids simulation engine <a href="https://github.com/dimforge/salva" target="_blank" rel="noopener noreferrer">Salva</a> has been completed and released
in Salva v0.5.0. With this release, Salva no longer supports nphysics. In the following demo, you can see three
fluids from Salva: two with a high elasticity (acting like jelly), and one with no elasticity (acting like water).
These fluids interact with four rigid-bodies: the ground with a <code>Polyline</code> shape, and three dynamic bodies with <code>Ball</code>,
<code>Cuboid</code>, and <code>Capsule</code> shapes.</p>
<center><img src="https://dimforge.com/img/salva_rapier_coupling.gif" alt="Salva rapier integration demo"></center>
<p>We also added to Salva the ability to retrieve all the fluid particles located inside an AABB or a shape
defined in our ncollide crate. This can be useful for, e.g., spawning new particles ensuring there isn't anything there already.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapierjs-0213">Rapier.js 0.2.13<a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#rapierjs-0213" class="hash-link" aria-label="Direct link to Rapier.js 0.2.13" title="Direct link to Rapier.js 0.2.13">​</a></h2>
<p>Our Typescript/JS bindings for Rapier have been significantly improved. They have as many features as
the Rust version of Rapier now! In particular, we added bindings to support:</p>
<ul>
<li><strong>Heightfield</strong> and <strong>triangle-mesh</strong> colliders.</li>
<li><strong>Collision groups</strong> and solver groups.</li>
<li>Rotation and/or translation <strong>locking</strong> for rigid-bodies.</li>
<li>Linear and angular <strong>damping</strong> for dynamic rigid-bodies.</li>
<li>The ability to <strong>remove joints</strong>.</li>
<li><strong>Prismatic</strong> and <strong>fixed</strong> joints.</li>
<li>The ability to <strong>set the velocity</strong> of a rigid-body after its creation.</li>
</ul>
<p>You may see the <a href="https://github.com/dimforge/rapier.js/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer">CHANGELOG of rapier.js</a> for more
details on other changes we made since its version 0.2.6.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next<a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next">​</a></h2>
<p>Last month, we said we would add the support of arbitrary convex polyhedron shapes during November. This has been
postponed to make it part to a larger piece of work: during December (and possibly January 2021), we will
work on a significant refactoring of all the geometry-related code used by Rapier.</p>
<p>Right now, the geometry-related code (including collision detection and ray-casting) used by Rapier is partially located inside
of the Rapier crate itself, and partially inside of our <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer">ncollide</a> crate. We intend to move all the
geometry code out of Rapier completely for better separation of concerns. We are not sure yet if all this will be moved inside
of ncollide, or if we will create a new crate that will be the successor of ncollide (similarly to when
we created Rapier as a successor of <a href="https://nphysics.org/" target="_blank" rel="noopener noreferrer">nphysics</a>.</p>
<p>This refactoring is the first step before adding some essential features, like CCD (continuous collision-detection) and
the support of custom collider shapes.</p>
<hr>
<h1>Thanks</h1>
<p>We would like to thank the whole community and code contributors. In particular, thanks to the code contributors from
the past month<sup><a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#user-content-fn-1-a1237f" id="user-content-fnref-1-a1237f" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/alec-deason" target="_blank" rel="noopener noreferrer">alec-deason</a></li>
<li><a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andlon</a></li>
<li><a href="https://github.com/AutomatonSystems" target="_blank" rel="noopener noreferrer">AutomatonSystems</a></li>
<li><a href="https://github.com/filnet" target="_blank" rel="noopener noreferrer">filnet</a></li>
<li><a href="https://github.com/heinousjay" target="_blank" rel="noopener noreferrer">heinousjay</a></li>
<li><a href="https://github.com/mark-schultz" target="_blank" rel="noopener noreferrer">mark-schultz</a></li>
<li><a href="https://github.com/mvlabat" target="_blank" rel="noopener noreferrer">mvlabat</a></li>
<li><a href="https://github.com/robert-hrusecky" target="_blank" rel="noopener noreferrer">robert-hrusecky</a></li>
<li><a href="https://github.com/ryo33" target="_blank" rel="noopener noreferrer">ryo33</a></li>
<li><a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a></li>
<li><a href="https://github.com/superdump" target="_blank" rel="noopener noreferrer">superdump</a></li>
<li><a href="https://github.com/yutannihilation" target="_blank" rel="noopener noreferrer">yutannihilation</a></li>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on open-source exclusively.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-a1237f">
<p><em>The list of contributors is automatically generated from the past months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2020/12/01/this-month-in-dimforge#user-content-fnref-1-a1237f" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in Dimforge \#2 (October 2020)]]></title>
            <link>https://dimforge.com/blog/2020/11/01/this-month-in-dimforge</link>
            <guid>https://dimforge.com/blog/2020/11/01/this-month-in-dimforge</guid>
            <pubDate>Sun, 01 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the second edition of This month in dimforge! This is the second edition of this newsletter that replaces the]]></description>
            <content:encoded><![CDATA[<p>Welcome to the second edition of <em>This month in dimforge</em>! This is the second edition of this newsletter that replaces the
<em>This month in rustsim</em> we published before <em>Dimforge</em> was created. This will provide you with a
summary of important update that occurred within the dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>salva</strong></a> (fluid simulation), <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer"><strong>ncollide</strong></a> (for collision-detection),
<a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (for linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>simba</strong></a> (for abstract algebra) crates. This second edition will contain updates for
the month of October 2020.</p>
<p>Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord</a> and on our <a href="https://discourse.nphysics.org/" target="_blank" rel="noopener noreferrer">user forum</a>!<br>
You can support us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-new-shapes-collision-filtering-and-user-defined-data">Rapier: new shapes, collision filtering, and user-defined data<a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#rapier-new-shapes-collision-filtering-and-user-defined-data" class="hash-link" aria-label="Direct link to Rapier: new shapes, collision filtering, and user-defined data" title="Direct link to Rapier: new shapes, collision filtering, and user-defined data">​</a></h2>
<p>The new version of Rapier 0.3.0 includes a few important new features:</p>
<ul>
<li>The support of <strong>cylinders and cones</strong> as collider shapes.</li>
<li>The support of <strong>collision groups</strong> (i.e. bit masks) for deciding what pair of colliders can collide based on some
hard-coded rules combining bit masks. These collision groups can also be used for deciding what collider a ray should
or shouldn't hit during a ray-cast.</li>
</ul>
<center><img src="https://dimforge.com/img/cone_cylinder_collision_groups_demo.gif" alt="Collision groups demo"></center>
<ul>
<li>The support of <strong>collision filters</strong> (i.e. custom callbacks) for deciding what pair of colliders can collide based
on user-defined trait-objects. This can also be used to allow the computation of contacts between two colliders
attached to non-dynamic rigid-bodies.</li>
<li>The ability to <strong>set the mass</strong>, center-of-mass, and angular inertia, of a rigid-body at creation time.</li>
<li>The support of linear and angular <strong>damping</strong> for progressively slowing down a rigid-body. This is often used to
simulate some sort of air friction.</li>
<li>The addition of <strong>user-defined data</strong> stored into each rigid-bodies and each collider. This user-defined data is
specified as a <code>u128</code> which value can be freely set by the user. This can for example be used to store an Entity
identifier from and ECS.</li>
</ul>
<p>Another notable change is that shapes are no longer represented as an <code>enum</code>. Instead, they are represented
as trait-objects. This is a first change towards making it possible to support user-defined shapes for colliders.</p>
<p>You may see the <a href="https://github.com/dimforge/rapier/blob/master/CHANGELOG" target="_blank" rel="noopener noreferrer">CHANGELOG of Rapier</a> for more details
on other changes we made in Rapier 0.3.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="bevy_rapier-version-040">bevy_rapier: version 0.4.0<a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#bevy_rapier-version-040" class="hash-link" aria-label="Direct link to bevy_rapier: version 0.4.0" title="Direct link to bevy_rapier: version 0.4.0">​</a></h2>
<p>We released the version 0.4.0 of our Bevy plugin for Rapier <a href="https://github.com/dimforge/bevy_rapier" target="_blank" rel="noopener noreferrer">bevy_rapier</a>.
This includes:</p>
<ul>
<li>The use of the latest version of Rapier 0.3 with the addition of an <code>InteractionPairFilters</code> resource that may be
modified in order to register user-defined collision pair filters and proximity pair filters.</li>
<li>The implementation of rigid-body position interpolation for rendering, thanks to the contribution from
<a href="https://github.com/superdump" target="_blank" rel="noopener noreferrer">Robert Swain</a>. This follows the advices of the popular blog post by
Glenn Fiedler: <a href="https://www.gafferongames.com/post/fix_your_timestep/" target="_blank" rel="noopener noreferrer">https://www.gafferongames.com/post/fix_your_timestep/</a></li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="salva-work-in-progress-integration-with-rapier">Salva: work-in-progress integration with Rapier<a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#salva-work-in-progress-integration-with-rapier" class="hash-link" aria-label="Direct link to Salva: work-in-progress integration with Rapier" title="Direct link to Salva: work-in-progress integration with Rapier">​</a></h2>
<p>We started the integration of Rapier with Salva. With the <a href="https://github.com/dimforge/salva/tree/rapier" target="_blank" rel="noopener noreferrer">rapier branch</a>
of the Salva repository, it is possible to have two-way coupling between Rapier rigid-bodies and Salva fluids. This means
that Rapier rigid-bodies with colliders attached will apply forces to fluids they interact with, and fluids with also be
able to apply forces to rigid-bodies from Rapier.</p>
<p>This integration will likely be released at the end of November.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next<a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next">​</a></h2>
<p>During November, we will mostly focus on:</p>
<ol>
<li>Adding the support of arbitrary convex polyhedra colliders.</li>
<li>Improving the JavaScript bindings so that they can cover most of the features of the Rust version. Currently, the
JavaScript bindings are lacking access to a lot of recently introduced features.</li>
<li>Completing the Rapier/Salva integration.</li>
</ol>
<hr>
<h1>Thanks</h1>
<p>We would like to thank the whole community and contributors. In particular, thanks to the contributors from the past month<sup><a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#user-content-fn-1-a6bf71" id="user-content-fnref-1-a6bf71" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/avl" target="_blank" rel="noopener noreferrer">avl</a></li>
<li><a href="https://github.com/Bobox214" target="_blank" rel="noopener noreferrer">Bobox214</a></li>
<li><a href="https://github.com/filnet" target="_blank" rel="noopener noreferrer">filnet</a></li>
<li><a href="https://github.com/msmorgan" target="_blank" rel="noopener noreferrer">msmorgan</a></li>
<li><a href="https://github.com/neachdainn" target="_blank" rel="noopener noreferrer">neachdainn</a></li>
<li><a href="https://github.com/sdleffler" target="_blank" rel="noopener noreferrer">sdleffler</a></li>
<li><a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a></li>
<li><a href="https://github.com/superdump" target="_blank" rel="noopener noreferrer">superdump</a></li>
<li>Terence</li>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on open-source exclusively.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-a6bf71">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2020/11/01/this-month-in-dimforge#user-content-fnref-1-a6bf71" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in Dimforge \#1 (September 2020)]]></title>
            <link>https://dimforge.com/blog/2020/10/01/this-month-in-dimforge</link>
            <guid>https://dimforge.com/blog/2020/10/01/this-month-in-dimforge</guid>
            <pubDate>Thu, 01 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the first edition of This month in dimforge! This is the first edition of this newsletter that replaces the]]></description>
            <content:encoded><![CDATA[<p>Welcome to the first edition of <em>This month in dimforge</em>! This is the first edition of this newsletter that replaces the
<em>This month in rustsim</em> we published before <em>Dimforge</em> was created. This will provide you with a
summary of important update that occurred within the dimforge community. This includes in particular updates about
the <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>rapier</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>salva</strong></a> (fluid simulation), <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer"><strong>ncollide</strong></a> (for collision-detection),
<a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (for linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>simba</strong></a> (for abstract algebra) crates. This first edition will contain updates for the month of September 2020.</p>
<p>Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord</a> and on our <a href="https://discourse.nphysics.org/" target="_blank" rel="noopener noreferrer">user forum</a>!<br>
Support us on <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-continuous-benchmarking">Rapier: continuous benchmarking<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#rapier-continuous-benchmarking" class="hash-link" aria-label="Direct link to Rapier: continuous benchmarking" title="Direct link to Rapier: continuous benchmarking">​</a></h2>
<p>Here are two facts:</p>
<ol>
<li>Rapier is still in early development and lacks lots of features.</li>
<li>By adding new features to Rapier, we take the risk of making it slower.</li>
</ol>
<p>But we want to make sure the addition of new features don't degrade performances of Rapier. This is why we stated
working on a continous-benchmarking setup that will allow us to see performance impact of each pull-request targeting
the <code>master</code> branch and each commit landing on the <code>master</code> branch.</p>
<p>Each relevant CI pipeline triggers the execution of a set of stress-test
we used to compare Rapier to other physics engine
<a href="https://www.dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine" target="_blank" rel="noopener noreferrer">when we first announced Rapier</a>.
Because CI runners can have unreliable performances, we are running these benchmarks on a dedicated server that
does nothing but compile the code, run the benchmarks, and upload the result to a database.
Once these benchmarks finished, they can be seen in the Rapier website <a href="https://www.rapier.rs/benchmarks/" target="_blank" rel="noopener noreferrer">there</a>.
In that page, we can select what commit we want to compare with what other commit. We can also include other
physics engines (PhysX and nphysics) for comparison.</p>
<p>Right now, only the 3D version of Rapier is included on these benchmarks. We will add the 2D version in the future. The
3D version alone already allows us to spot any performance regression between two versions of Rapier because the 2D version
of Rapier uses mostly the same code. The code of our benchmark setup can be found in our
<a href="https://github.com/dimforge/dimforge-bench" target="_blank" rel="noopener noreferrer">dimforge-bench repository</a>.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-ray-casting-support">Rapier: ray-casting support<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#rapier-ray-casting-support" class="hash-link" aria-label="Direct link to Rapier: ray-casting support" title="Direct link to Rapier: ray-casting support">​</a></h2>
<p>One of the most important features Rapier was missing is ray-casting, which can be essential for, e.g., writing
character controllers.</p>
<p>Ray-casting is now supported by Rapier, but in a very different way than what we did in nphysics. Here we have a
new stucture called <code>QueryPipeline</code> which will be responsible for executing all scene-wide queries. Only ray-cast is
implemented right now, but it will also support queries like convex-casting, point-projection, or volume-interferences
in the future.</p>
<p>The <code>QueryPipeline</code> can be used alongside the <code>PhysicsPipeline</code>, or even without the <code>PhysicsPipeline</code> if you don't
care about physics simulation and just want to run some geometic queries. Just like the physics pipeline <code>.step()</code> method,
the query pipeline has an <code>.update()</code> method that updates its internal state. This update method may not necessarily be
executed at each iteration of the game loop. So you are not forced to update it if you don't do queries for some times.</p>
<p>The <code>QueryPipeline</code> uses its own acceleration structure internally, completely independently from the
<code>BroadPhase</code> and <code>NarrowPhase</code>. Right now this structure is re-built from scratch each time the quey pipeline is
updated. In the future, it will be updated incrementally for better performances.</p>
<p>You may see the <a href="https://github.com/dimforge/rapier/blob/master/CHANGELOG" target="_blank" rel="noopener noreferrer">CHANGELOG of Rapier</a> for more details on other changes
we made in Rapier 0.2.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapierjs-new-bindings-less-memory-management">Rapier.js: new bindings, less memory management<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#rapierjs-new-bindings-less-memory-management" class="hash-link" aria-label="Direct link to Rapier.js: new bindings, less memory management" title="Direct link to Rapier.js: new bindings, less memory management">​</a></h2>
<p>We worked on brand new JavaScript bindings for Rapier. In the version 0.1, the bindings were automatically generated
by <code>wasm-bindgen</code>. This is useful but has its limitations including:</p>
<ul>
<li>The necessity for the end-user to do manual memory management (by calling <code>.free()</code> on objects returned by the bindings).</li>
<li>Places where the API does not feel quite idiomatic. In particular, we couldn't really apply the <em>builder pattern</em> because
this would have resulted in <code>wasm-bindgen</code> generating a new JS objects each time a property of the builder is changed.</li>
</ul>
<p>The new version 0.2 add a layer of Typescript wrappers on top of the bindings generated by <code>wasm-bindgen</code>. This extra layer
takes care of the memory management for all transient objects (vectors, rotations, rigid-bodies, colliders, etc.) This means
that the end-user only has to call <code>.free()</code> on:</p>
<ul>
<li><code>World</code> and <code>EventQueue</code>.</li>
<li>Or, if the <code>World</code> is not used directly, on
<code>RigidBodySet</code>, <code>ColliderSet</code>, <code>JointSet</code>, <code>IntegrationParameters</code>, <code>PhysicsPipeline</code>, <code>QueryPipeline</code>, <code>SerializationPipeline</code>, and <code>EventQueue</code>.</li>
</ul>
<p>This version 0.2 of <a href="https://www.npmjs.com/package/@dimforge/rapier2d" target="_blank" rel="noopener noreferrer">@dimforge/rapier2d</a> and
<a href="https://www.npmjs.com/package/@dimforge/rapier3d" target="_blank" rel="noopener noreferrer">@dimforge/rapier3d</a> also makes the API closer to Rapier's by defining
each part of the physics world individually.</p>
<p>Finally, the <code>ColliderDesc</code> and <code>RigidBodyDesc</code> used for creating colliders and rigid-bodies now use the builder-pattern
because they are now completely implemented in Typescript.</p>
<p>See the <a href="https://github.com/dimforge/rapier.js/blob/master/CHANGELOG" target="_blank" rel="noopener noreferrer">CHANGELOG of rapier.js</a> of the version 0.2.1 for
details on all the changes we made.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="bevy_rapier-version-031">bevy_rapier: version 0.3.1<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#bevy_rapier-version-031" class="hash-link" aria-label="Direct link to bevy_rapier: version 0.3.1" title="Direct link to bevy_rapier: version 0.3.1">​</a></h2>
<p>We released the version 0.3.1 of our Bevy plugin for Rapier <a href="https://github.com/dimforge/bevy_rapier" target="_blank" rel="noopener noreferrer">bevy_rapier</a>.
This includes:</p>
<ul>
<li>The use of the latest version of Rapier 0.2 with the automatic addition (and update) of the <code>QueryPipeline</code> as a Bevy
component.</li>
<li>The update to Bevy 0.2 thanks to the great contributions from <a href="https://github.com/CleanCut" target="_blank" rel="noopener noreferrer">CleanCut</a>.</li>
<li>The replacement of the <code>Gravity</code> and <code>RapierPhysicsScale</code> resources by a <code>RapierConfiguration</code> resource. This new resource
will also allow you to temporarily pause the physics simulation by setting its <code>physics_pipeline_active</code> flag to <code>false</code>. We
thank <a href="https://github.com/Bobox214" target="_blank" rel="noopener noreferrer">Bobox214</a> for these great contributions.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="salva-a-progressive-rewrite">salva: a progressive rewrite<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#salva-a-progressive-rewrite" class="hash-link" aria-label="Direct link to salva: a progressive rewrite" title="Direct link to salva: a progressive rewrite">​</a></h2>
<p>We started working on Salva, our fluids simulation library, in order to:</p>
<ul>
<li>Remove the generics wrt. the scalar type. This will allow faster incremental compilation times of end-user code, and
allow the compilation of Salva with optimizations while keeping the end-user binary in debug mode.</li>
<li>Add SIMD optimizations, applying what we learned with Rapier.</li>
<li>Add coupling between fluids from Salva and rigid-bodies/colliders from Rapier.</li>
</ul>
<p>Right now we only worked the first step, which is removing the generics wrt. the scalar type. We will work on the
rest progressively, though it is not our top priority right now.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="whats-next">What's next<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#whats-next" class="hash-link" aria-label="Direct link to What's next" title="Direct link to What's next">​</a></h2>
<p>There are at least two important Rapier features we intend to work on during October:</p>
<ol>
<li>The support for cylinder colliders. Not all physics engines support cylinders: nphysics and PhysX don't! But they can
be extremely valuable for simulating objects like, e.g., wheels. The typical workaround is to represent them as polyhedron, but
this can make the simulation less accurate because of the approximation introducing "bumps".</li>
<li>The support for collision filtering. We want to make it possible for the user to prevent collisions between some
pair of shapes. The typical way of handling this is through collision groups (with bit masks) and this is the first
approach we will work on. We will consider other approaches as well based on community feedbacks on issues <a href="https://github.com/dimforge/rapier/issues/2" target="_blank" rel="noopener noreferrer">#2</a>,
<a href="https://github.com/dimforge/rapier/issues/3" target="_blank" rel="noopener noreferrer">#3</a>, <a href="https://github.com/dimforge/rapier/issues/15" target="_blank" rel="noopener noreferrer">#15</a>, and <a href="https://github.com/dimforge/rapier/issues/24" target="_blank" rel="noopener noreferrer">#24</a>.</li>
</ol>
<hr>
<h1>Thanks</h1>
<p>We would like to thank the whole community and contributors. In particular, thanks to the contributors from the past two months<sup><a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#user-content-fn-1-4d0ccc" id="user-content-fnref-1-4d0ccc" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/Bobox214" target="_blank" rel="noopener noreferrer">Bobox214</a></li>
<li><a href="https://github.com/CleanCut" target="_blank" rel="noopener noreferrer">CleanCut</a></li>
<li><a href="https://github.com/ColonelThirtyTwo" target="_blank" rel="noopener noreferrer">ColonelThirtyTwo</a></li>
<li><a href="https://github.com/farnoy" target="_blank" rel="noopener noreferrer">farnoy</a></li>
<li>FenQiDian</li>
<li><a href="https://github.com/neachdainn" target="_blank" rel="noopener noreferrer">neachdainn</a></li>
<li><a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a></li>
<li><a href="https://github.com/skairunner" target="_blank" rel="noopener noreferrer">skairunner</a></li>
<li><a href="https://github.com/toasteater" target="_blank" rel="noopener noreferrer">toasteater</a></li>
<li><a href="https://github.com/zalo" target="_blank" rel="noopener noreferrer">zalo</a></li>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new supporters through <a href="https://github.com/sponsors/dimforge/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows us to continue working on open-source exclusively.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-4d0ccc">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2020/10/01/this-month-in-dimforge#user-content-fnref-1-4d0ccc" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing the Rapier physics engine]]></title>
            <link>https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine</link>
            <guid>https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine</guid>
            <pubDate>Tue, 25 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[In our announcement last week, we briefly mentioned this new physics engine we have been working on during the past 5 months.]]></description>
            <content:encoded><![CDATA[<p>In our announcement last week, we briefly mentioned this new physics engine we have been working on during the past 5 months.
Today we are officially releasing it for the first time: the project <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><strong>Rapier</strong></a>; a set of two 100%
rust libraries <strong>rapier2d</strong> and <strong>rapier3d</strong> for 2D and 3D physics simulations for games, animation, and robotics.</p>
<p><img decoding="async" loading="lazy" alt="rapier logo" src="https://dimforge.com/assets/images/rapier_logo_color_textpath_dark-67093214cb8594cb6bf7b952ff3e3027.svg" width="527" height="131" class="img_XsDP"></p>
<p>This post will be quite long, so here are all the different sections:</p>
<ul>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#presenting-rapier">Presenting Rapier</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#reaching-out-to-other-communities-bevy-and-javascript">Reaching out to other communities: Bevy and JavaScript</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#feature-comparison-with-nphysics">Feature comparison with nphysics</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#benchmarks">Benchmarks</a>
<ul>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#3d-benchmark-rapier-vs-physx-vs-nphysics">3D Benchmark: Rapier vs. PhysX vs. nphysics</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#3d-benchmark-conclusion">3D Benchmark: Conclusion</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#2d-benchmark-rapier-vs-box2d-vs-nphysics">2D Benchmark: Rapier vs. Box2D vs. nphysics</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#2d-benchmark-conclusion">2D Benchmark: Conclusion</a></li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#running-the-benchmarks-yourself">Running the benchmarks yourself</a></li>
</ul>
</li>
<li><a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#conclusion">Conclusion</a></li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="presenting-rapier">Presenting Rapier<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#presenting-rapier" class="hash-link" aria-label="Direct link to Presenting Rapier" title="Direct link to Presenting Rapier">​</a></h3>
<p><strong>Rapier</strong> is the successor of <a href="https://nphysics.org/" target="_blank" rel="noopener noreferrer">nphysics</a> and focuses on performance first.
Just like <strong>nphysics</strong> it is split into two crates: <strong>rapier2d</strong> and <strong>rapier3d</strong> for 2D and 3D physics respectively. It
is designed to be fast and multithreaded right from the beginning. It is also designed to require less incremental compilation
times because the data structures it defines are not generic.</p>
<p>In release mode, <strong>Rapier</strong> runs 5 to 8 times faster than <strong>nphysics</strong> , making it close to the performance of (the CPU version of) NVidia PhysX
and slightly faster than Box2D as you will see in the <a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#benchmarks">benchmark sections</a>. <strong>Rapier</strong> is only at its beginning, so many features
are still missing. However some performance optimizations like parallelism, and SIMD have been integrated right from the start.</p>
<p>There already are a few key features that makes Rapier stand out. Since they may affect compilation times and/or performance,
they are disabled by default and need to be enabled explicitly through cargo features:</p>
<ol>
<li><strong>Serialization</strong>: if the <code>serde-serialize</code> feature of <strong>Rapier</strong> is enabled, every physics component will be serializable using <code>serde</code>.
This means that you can take a deep snapshot of the physics state and restore it later. This snapshot can even be saved on
disk or sent through network.</li>
<li><strong>Cross-platform determinism</strong>: if the <code>enhanced-determinism</code> feature of <strong>Rapier</strong> is enabled, it will behave in
a <em>bit-level cross-platform deterministic</em> way in all platforms that comply with the IEEE 754-2008 floating point standard.
This means that if you run the same simulation with the same initial states on two different machines (or browsers)
you will get the exact same results. Here "bit-level" determinism means that if you serialize the physics state after the
same number of timesteps on two different machines, you will obtain the exact same byte array for both: you may compute a checksum
of both snapshots and they will be identical. All this doesn't apply to platforms with pointer size smaller than 32-bit, and on
platforms that don't comply to IEEE&nbsp;754-2008 strictly.</li>
</ol>
<p>See <a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#feature-comparison-with-nphysics">that section</a> for a comparison between Rapier and nphysics features.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="reaching-out-to-other-communities-bevy-and-javascript">Reaching out to other communities: Bevy and JavaScript<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#reaching-out-to-other-communities-bevy-and-javascript" class="hash-link" aria-label="Direct link to Reaching out to other communities: Bevy and JavaScript" title="Direct link to Reaching out to other communities: Bevy and JavaScript">​</a></h3>
<p><img decoding="async" loading="lazy" alt="Bevy WASM JS" src="https://dimforge.com/assets/images/bevy_wasm_js-8ed8614ae436605153deb37f9163a8ee.svg" width="2309" height="651" class="img_XsDP"></p>
<p>Writing a physics engine is hard. There are not a lot of choices out there and most of them are written in C++. With
<strong>nphysics</strong> we wanted to provide an open-source 100% rust physics solution for the Rust community.
With <strong>Rapier</strong> we want to go one step further by contributing to as many communities in need of a physics engine as we can. This is why we are
starting, right at the beginning of the <strong>Rapier</strong> story, by providing:</p>
<ul>
<li>Official <strong>JavaScript bindings</strong> for the WASM version of <strong>Rapier</strong>. These binding are generated using <code>wasm_bindgen</code> and
are published to NPM as the packages <a href="https://www.npmjs.com/package/@dimforge/rapier3d" target="_blank" rel="noopener noreferrer">@dimforge/rapier3d</a> and
<a href="https://www.npmjs.com/package/@dimforge/rapier2d" target="_blank" rel="noopener noreferrer">@dimforge/rapier2d</a>. While multiple physics solutions already exist
for JavaScript they are either slow (because they are manually written in JS like <strong>cannon.js</strong> or <strong>oimo.js</strong>), or not
officially maintained by their original developers (because they are ported from C++ using Emscripten, like <strong>box2d.wasm</strong>,
<strong>ammo.wasm</strong>, or <strong>physx.wasm</strong>). By providing official wasm builds and JS bindings, we are making sure to provide the
best support, documentation, and continuous updates to the JS community.</li>
<li>Official <strong>plugins for the <a href="https://bevyengine.org/" target="_blank" rel="noopener noreferrer">Bevy</a></strong> game engine. They are available as the
<a href="https://crates.io/crates/bevy_rapier2d" target="_blank" rel="noopener noreferrer">bevy_rapier2d</a> and <a href="https://crates.io/crates/bevy_rapier3d" target="_blank" rel="noopener noreferrer">bevy_rapier3d</a>
crates. The <strong>Bevy</strong> game engine has recently been released as an efficient, fast-to-compile, and easy to use, data-oriented
game engine. It is still at its early state and is lacking any physics feature. We believe physics support is a very high-value
feature to have in a game engine. By providing official plugins we want to make sure the <strong>Bevy</strong> community can benefit from the
<strong>Rapier</strong> physics engines quickly and easily.</li>
</ul>
<p>There are so many more communities we would like to contribute to but don't have manpower to support all of them just now.
Other integrations and languages will come in the future.</p>
<p>We also plan to create official plugins for the <strong>Amethyst</strong> game engine but have not started yet. We are waiting
for the migration of <strong>Amethyst</strong> to the <a href="https://crates.io/crates/legion" target="_blank" rel="noopener noreferrer">legion</a> ECS solution before starting to work
on this.</p>
<div class="theme-admonition theme-admonition-note admonition_v1XZ alert alert--secondary"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_nS2X"><p>Examples using the 2D JS bindings are available on GitHub:
<a href="https://github.com/dimforge/rapier.js/tree/master/testbed2d/src/demos" target="_blank" rel="noopener noreferrer">2D</a> and
<a href="https://github.com/dimforge/rapier.js/tree/master/testbed3d/src/demos" target="_blank" rel="noopener noreferrer">3D</a>. You can see these demos running
<a href="https://rapier.rs/demos2d/index.html" target="_blank" rel="noopener noreferrer">there for 2D</a> and <a href="https://rapier.rs/demos3d/index.html" target="_blank" rel="noopener noreferrer">there for 3D</a>.
In these demos, the physics simulation runs inside of a web worker and the rendering is performed by
<a href="https://www.pixijs.com/" target="_blank" rel="noopener noreferrer">PixiJS</a> and <a href="https://threejs.org/" target="_blank" rel="noopener noreferrer">Three.js</a>.</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="feature-comparison-with-nphysics">Feature comparison with nphysics<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#feature-comparison-with-nphysics" class="hash-link" aria-label="Direct link to Feature comparison with nphysics" title="Direct link to Feature comparison with nphysics">​</a></h3>
<p><strong>Rapier</strong> does not have as many features as <strong>nphysics</strong> yet, but it also has a few features <strong>nphysics</strong> does not have.
Here are comparative tables of both physics engines:</p>
<center><table><thead><tr><th>Dynamics features</th><th>Rapier</th><th>nphysics</th></tr></thead><tbody><tr><td>Rigid-body physics</td><td>✅</td><td>✅</td></tr><tr><td>Kinematic bodies</td><td>✅</td><td>✅</td></tr><tr><td>Rigid-body islands and sleeping</td><td>✅</td><td>✅</td></tr><tr><td>Joint constraints</td><td>✅</td><td>✅</td></tr><tr><td>Joint constraint limits and motors</td><td>❌</td><td>❌</td></tr><tr><td>Reduced-coordinate joints</td><td>❌</td><td>✅</td></tr><tr><td>Reduced-coordinates joint limits and motors</td><td>❌</td><td>✅</td></tr><tr><td>Conveyor belts</td><td>❌</td><td>✅</td></tr><tr><td>Deformable bodies</td><td>❌</td><td>✅</td></tr><tr><td>Fluids (integration with <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer">Salva</a>)</td><td>❌</td><td>✅</td></tr></tbody></table></center>
<center><table><thead><tr><th>Geometry features</th><th>Rapier</th><th>nphysics</th></tr></thead><tbody><tr><td>Colliders</td><td>✅</td><td>✅</td></tr><tr><td>Sensors</td><td>✅</td><td>✅</td></tr><tr><td>Contact/proximity events</td><td>✅</td><td>✅</td></tr><tr><td>Contact graph</td><td>✅</td><td>✅</td></tr><tr><td>Continuous Collision Detection</td><td>❌</td><td>✅</td></tr><tr><td>Ray-casting</td><td>❌</td><td>✅</td></tr><tr><td>Convex-casting</td><td>❌</td><td>✅</td></tr></tbody></table></center>
<center><table><thead><tr><th>Performance and portability features</th><th>Rapier</th><th>nphysics</th></tr></thead><tbody><tr><td>Floating-point cross-platform determinism</td><td>✅</td><td>❌</td></tr><tr><td>Parallelization</td><td>✅</td><td>❌</td></tr><tr><td>SIMD</td><td>✅</td><td>❌</td></tr><tr><td>Serialization</td><td>✅</td><td>❌</td></tr><tr><td><strong>JavaScript</strong> bindings</td><td>✅</td><td>❌</td></tr><tr><td>Integration to <strong>Bevy</strong></td><td>✅</td><td>❌</td></tr><tr><td>Integration to <strong>Amethyst</strong></td><td>❌</td><td>❌</td></tr><tr><td>Fixed-point cross-platform determinism</td><td>❌</td><td>✅</td></tr><tr><td>64-bits physics</td><td>❌</td><td>✅</td></tr></tbody></table></center>
<p>Today <strong>nphysics</strong> is more mature than <strong>Rapier</strong>. Our first goal during the next few months is to bring <strong>Rapier</strong> at the
same level as <strong>nphysics</strong> featurewise, while keeping the significant performance improvements and better accuracy.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="benchmarks">Benchmarks<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#benchmarks" class="hash-link" aria-label="Direct link to Benchmarks" title="Direct link to Benchmarks">​</a></h3>
<p>Alright, we claimed that <strong>Rapier</strong> is nearly as fast as the CPU version of PhysX, 5 to 10 times faster than nphysics, and
slightly faster than Box2D. It is now time to prove these claims using benchmarks.</p>
<div class="theme-admonition theme-admonition-info admonition_v1XZ alert alert--info"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_nS2X"><p>Keep in mind that <strong>Rapier</strong> is still at a early development stage. It does not have as many features as the ofther
physics engines involved in this benchmark. However, our objective is to ensure that the future addition of new features
to <strong>Rapier</strong> don't reduce the level of perfomance you see here.</p></div></div>
<p>In the subsequent benchmarks we ran a set of stress tests using four different physics engines:</p>
<ol>
<li><strong>Rapier</strong> using our <a href="https://crates.io/crates/rapier3d" target="_blank" rel="noopener noreferrer">rapier3d</a> crate for 3D and <a href="https://crates.io/crates/rapier2d" target="_blank" rel="noopener noreferrer">rapier2d</a> for 2D.</li>
<li><strong>PhysX 4</strong> using the <a href="https://crates.io/crates/physx" target="_blank" rel="noopener noreferrer">physx</a> crate.</li>
<li><strong>Box2d</strong> using the <a href="https://crates.io/crates/wrapped2d" target="_blank" rel="noopener noreferrer">wrapped2d</a> crate.</li>
<li><strong>nphysics</strong> using our <a href="https://crates.io/crates/nphysics3d" target="_blank" rel="noopener noreferrer">nphysics3d</a> crate for 3D and <a href="https://crates.io/crates/nphysics2d" target="_blank" rel="noopener noreferrer">nphysics2d</a> for 2D</li>
</ol>
<p>Independently of the chosen physics engine, all scenes are always initialized in the
exact same way (same bodies, same colliders at the same initial positions) and with the following
parameters:</p>
<ul>
<li><strong>Rust compiler and flags</strong>: <code>rustc 1.46.0-nightly</code>, <code>--release</code>, <code>--features simd-nightly</code>, <code>codegen-units = 1</code>.</li>
<li><strong>Timestep length</strong>: 0.016 (i.e. 16 milliseconds).</li>
<li><strong>Number of velocity iterations</strong>: 4 for Rapier, nphysics, and Box2D. 1 for PhysX.</li>
<li><strong>Number of position iterations</strong>: 1 from Rapier, nphysics, and Box2D. 4 for PhysX.</li>
<li><strong>Targets</strong>: native CPU (WebAssembly versions and PhysX on GPU have not been benchmarked.)</li>
<li><strong>Solvers</strong>: variations of PGS. (The PhysX 4.0 TGS solver has not been benchmarked. We used the default <code>ePGS</code> solver.)</li>
<li><strong>Number of threads</strong>: 1.</li>
</ul>
<div class="theme-admonition theme-admonition-note admonition_v1XZ alert alert--secondary"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_nS2X"><p>In this benchmark we don't use multithreading. A benchmark with multithreading enabled, involving only multithread physics
engine will be the subject of another blog post.</p></div></div>
<p>Each 3D benchmark is run on two different machines because we observed performance differences between
PhysX and Rapier depending on the processor:</p>
<ol>
<li>A desktop computer, running Ubuntu, equipped with an AMD Ryzen 9 3900X CPU, 3.8GHz.</li>
<li>A MacBook Pro (plugged to a power outlet), running Mac OS, equipped with an Intel Core i7 7920HQ, 3.1GHz.</li>
</ol>
<p>The 2D benchmarks are run only on the AMD Ryzen 9 3900X CPU (the relative performance remain the same with
the Inter Core i7 CPU).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="3d-benchmark-rapier-vs-physx-vs-nphysics">3D Benchmark: Rapier vs. PhysX vs. nphysics<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#3d-benchmark-rapier-vs-physx-vs-nphysics" class="hash-link" aria-label="Direct link to 3D Benchmark: Rapier vs. PhysX vs. nphysics" title="Direct link to 3D Benchmark: Rapier vs. PhysX vs. nphysics">​</a></h3>
<p>A few notes are in order regarding PhysX in this benchmark. First, we don't use the same number of iterations for Rapier and PhysX.
For Rapier and nphysics we use 4 velocity iterations and 1 position iteration. It is the other way round for PhysX: 1 velocity
iteration and 4 position iterations. This is the most sensible configuration because:</p>
<ul>
<li>PhysX developers <a href="http://www.codercorner.com/blog/?p=2072" target="_blank" rel="noopener noreferrer">advise to increase</a> the number of position iterations for
better stability, and leave to 1 the number of velocity iterations.</li>
<li>PhysX itself (independently from this benchmark) uses 1 velocity iteration and 4 position iterations by default.
It yields more stable simulations than using 4 velocity and 1 position without performance difference.</li>
<li>Rapier and nphysics use a solver different from PhysX's. With our solver, it is recommended to increase the number of
velocity iterations instead of position iterations, and leave the number of position iterations to 1.</li>
</ul>
<p>The PhysX benchmarks will include two performance curves:</p>
<ol>
<li>One performance curve using their default <code>ePATH</code> friction model. This is a simplified friction model, faster to
compute, but less realistic. Rapier and nphysics don't implement a similar model yet.</li>
<li>One performance curve using their <code>eTWO_DIRECTIONAL</code> friction model. This is similar to the friction model used by Rapier
and nphysics.</li>
</ol>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="8000-stacked-balls">8.000 stacked balls<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#8000-stacked-balls" class="hash-link" aria-label="Direct link to 8.000 stacked balls" title="Direct link to 8.000 stacked balls">​</a></h4>
<p>In this benchmark there are 8000 balls falling on a ground also composed of balls. In the end, they form 400
independent small stacks of balls.
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_balls-9fea15d944687a0cb2177562bcecc6c8.png" width="1718" height="856" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_ryzen_balls-7f1998698558b8946a8bb80917a9749a.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_intel_balls-ad267cdf226bff9093cb2bd36eb9579d.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="3000-falling-boxes">3.000 falling boxes<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#3000-falling-boxes" class="hash-link" aria-label="Direct link to 3.000 falling boxes" title="Direct link to 3.000 falling boxes">​</a></h4>
<p>In this benchmark, there are about 3000 small cubes falling on a large cube floor in a completely unordered way.
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_boxes-1420d8e93aa50615eecb21b82dce2eb9.png" width="2574" height="869" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_ryzen_boxes-b1e48a6316a00b8779cc37ff08303148.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_intel_boxes-f33dea28cd5d966b06262162e0e2d59e.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="pyramid-of-4900-boxes">Pyramid of 4.900 boxes<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#pyramid-of-4900-boxes" class="hash-link" aria-label="Direct link to Pyramid of 4.900 boxes" title="Direct link to Pyramid of 4.900 boxes">​</a></h4>
<p>In this benchmark, there is a set of 4900 boxes falling in such a way that they form a single large pyramid in the end.
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_pyramid-aeb5682f72fa3c82749a1594f56df71d.png" width="2106" height="711" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_ryzen_pyramid-5102921ac8f8ee8fbc466dd6d0f9d5ca.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_intel_pyramid-c869bb3f9ac6963d1a3f07f8bf28f0c1.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="triangle-mesh-with-1500-falling-boxes-and-balls">Triangle mesh with 1.500 falling boxes and balls<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#triangle-mesh-with-1500-falling-boxes-and-balls" class="hash-link" aria-label="Direct link to Triangle mesh with 1.500 falling boxes and balls" title="Direct link to Triangle mesh with 1.500 falling boxes and balls">​</a></h4>
<p>In this benchmark, the floor is modelled as a triangle mesh composed of 800 triangles. There are 1500 small boxes and
1500 small balls falling on this mesh.
<img decoding="async" loading="lazy" alt="bench trimesh" src="https://dimforge.com/assets/images/bench_trimesh-c970ea6102d87b64f7fe88ccbc0cc2ea.png" width="2871" height="860" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench trimesh" src="https://dimforge.com/assets/images/bench_ryzen_trimesh-05447cf364ea1c763d22b32c52ad4ce4.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench trimesh" src="https://dimforge.com/assets/images/bench_intel_trimesh-32f3daff1113e018e018e4b97ac309d0.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="keva-planks-tower-with-5320-planks">KEVA planks tower with 5.320 planks<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#keva-planks-tower-with-5320-planks" class="hash-link" aria-label="Direct link to KEVA planks tower with 5.320 planks" title="Direct link to KEVA planks tower with 5.320 planks">​</a></h4>
<p>In this benchmark, 5230 rectangular rigid bodies are used to form a tower, much like what can be achieved with real-world
KEVA wood planks. During the simulation, the tower breaks down to end up with a large pile. Note that the tower breaks down
because only 4 velocity iterations are used for this simulation. With about 15 velocity iterations, the tower would remain
stable when using Rapier.
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_keva_tower-d0ad5385b562c14b690611e6711a53e2.png" width="2432" height="945" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench keva tower" src="https://dimforge.com/assets/images/bench_ryzen_keva_tower-f5b5f7465367225c0ccc5449aefd978e.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench keva tower" src="https://dimforge.com/assets/images/bench_intel_keva_tower-42b1da6859a6cec02fd5404de3554649.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="19800-interconnected-ball-joints">19.800 interconnected ball joints<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#19800-interconnected-ball-joints" class="hash-link" aria-label="Direct link to 19.800 interconnected ball joints" title="Direct link to 19.800 interconnected ball joints">​</a></h4>
<p>In this benchmark, we have little less than 20.000 ball joints (aka. spherical joints). These joint connect rigid
bodies in such a way that we end up with a single large fabric-like sheet.
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_ball_joints-fcdc5a9ac41c340f16a80b30976f9909.png" width="1783" height="685" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench ball joints" src="https://dimforge.com/assets/images/bench_ryzen_ball_joints-70fcfaed2e3e0e36de336d87fae3eba9.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench ball joints" src="https://dimforge.com/assets/images/bench_intel_ball_joints-5da93a3d8c803686737b4305d50c6e14.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="20000-fixed-joints">20.000 fixed joints<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#20000-fixed-joints" class="hash-link" aria-label="Direct link to 20.000 fixed joints" title="Direct link to 20.000 fixed joints">​</a></h4>
<p>In this benchmark, we have 20.000 fixed joints keeping all balls from moving wrt. each other.
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_fixed_joints-b94e1af69b2766aab4614fade9193bd0.png" width="1920" height="1080" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_ryzen_fixed_joints-5c3dd011286da2aef9ca178d7d4b1024.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_intel_fixed_joints-f09b888eeae9200a8aa8057c2af02dc2.svg" width="934" height="505" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="8000-revolute-joints">8.000 revolute joints<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#8000-revolute-joints" class="hash-link" aria-label="Direct link to 8.000 revolute joints" title="Direct link to 8.000 revolute joints">​</a></h4>
<p>In this benchmark, we have 8.000 revolute joints attached in a way that forms several independent chains.
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_revolute_joints-209c604b216abdfc926d50ff86e1697f.png" width="2338" height="970" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_ryzen_revolute_joints-d8a222459ca035bc8f92c2b03c4b2c10.svg" width="934" height="505" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_intel_revolute_joints-f5508c9644110e62f77bdfe81a7b12d8.svg" width="934" height="505" class="img_XsDP"></p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="3d-benchmark-conclusion">3D Benchmark: Conclusion<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#3d-benchmark-conclusion" class="hash-link" aria-label="Direct link to 3D Benchmark: Conclusion" title="Direct link to 3D Benchmark: Conclusion">​</a></h3>
<p>From these benchmark we can see that:</p>
<ul>
<li><strong>PhysX</strong> and <strong>Rapier</strong> are both 4 to 8 times faster than <strong>nphysics</strong>. The gap would be greater (5 to 10 times faster) with
multithreading enabled.</li>
<li><strong>Rapier</strong> and <strong>PhysX</strong> have close performance. When targeting the Ryzen 9 CPU, <strong>Rapier</strong> ends up being slightly faster
in several cases. However, when targeting the Intel CPU <strong>PhysX</strong> ends up being slightly faster than Rapier.</li>
<li>In terms of simulation quality, <strong>PhysX</strong> and <strong>Rapier</strong> are quite similar. Joints from <strong>PhysX</strong> look slightly stiffer because
convergence for fixed joints are more quickly achieved. Joints from <strong>Rapier</strong> and <strong>PhysX</strong> are both much more stable than
joint constraints from <strong>nphysics</strong>.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="2d-benchmark-rapier-vs-box2d-vs-nphysics">2D Benchmark: Rapier vs. Box2D vs. nphysics<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#2d-benchmark-rapier-vs-box2d-vs-nphysics" class="hash-link" aria-label="Direct link to 2D Benchmark: Rapier vs. Box2D vs. nphysics" title="Direct link to 2D Benchmark: Rapier vs. Box2D vs. nphysics">​</a></h3>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="12500-stacked-balls">12.500 stacked balls<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#12500-stacked-balls" class="hash-link" aria-label="Direct link to 12.500 stacked balls" title="Direct link to 12.500 stacked balls">​</a></h4>
<p>In this benchmark there are 12.500 balls falling on a ground composed of balls.
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_2d_balls-9035f4fe6e31a71b2c1283351a1a9e50.png" width="1442" height="898" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_2d_balls-69f821734d138c6d529cc78a08925b2b.svg" width="931" height="512" class="img_XsDP">
The Box2D times are very noisy here. We suspect this is caused by their broad-phase implementation.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="3380-falling-boxes">3.380 falling boxes<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#3380-falling-boxes" class="hash-link" aria-label="Direct link to 3.380 falling boxes" title="Direct link to 3.380 falling boxes">​</a></h4>
<p>In this benchmark, there are about 3.380 small cubes falling on a large cubic "cup" in a completely unordered way.
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_2d_boxes-f632464956e74d2a2e2fbf7f4af9ea02.png" width="1684" height="1027" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_2d_boxes-28f7ad791e036d40baae4f254b7cd488.svg" width="931" height="512" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="pyramid-of-5050-boxes">Pyramid of 5.050 boxes<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#pyramid-of-5050-boxes" class="hash-link" aria-label="Direct link to Pyramid of 5.050 boxes" title="Direct link to Pyramid of 5.050 boxes">​</a></h4>
<p>In this benchmark, there is a set of 5.050 boxes falling in such a way that they form a single large pyramid in the end.
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_2d_pyramid-2f54014364b9481e73467244dc055100.png" width="1063" height="535" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_2d_pyramid-c62a6525a65f07c57abe8c5ce4c83693.svg" width="931" height="512" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="19800-interconnected-ball-joints-1">19.800 interconnected ball joints<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#19800-interconnected-ball-joints-1" class="hash-link" aria-label="Direct link to 19.800 interconnected ball joints" title="Direct link to 19.800 interconnected ball joints">​</a></h4>
<p>In this benchmark, we have little less than 20.000 ball joints (which are the same as revolute joints in 2D). These joint
connect rigid bodies in such a way that we end up with a single large fabric-like sheet. The performance of Box2D go really
crazy on this benchmark because its simulation breaks down (lack of numerical stability).
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_2d_ball_joints-4b3cbc42e62d25f89f016ab11ddcd060.png" width="1823" height="966" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench ball joints" src="https://dimforge.com/assets/images/bench_2d_ball_joints-9374a419e56b7a6e06ed87fee201d4c7.svg" width="931" height="512" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="28840-fixed-joints">28.840 fixed joints<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#28840-fixed-joints" class="hash-link" aria-label="Direct link to 28.840 fixed joints" title="Direct link to 28.840 fixed joints">​</a></h4>
<p>In this benchmark, we have 28.840 fixed joints keeping all balls from moving wrt. each other.
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_2d_fixed_joints-bfd43c5ddcb4f556e382dfb3f9af47d6.png" width="915" height="922" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_2d_fixed_joints-2f7f46c36d80d21ee7538683a0ca32af.svg" width="931" height="512" class="img_XsDP"></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="12500-prismatic-joints">12.500 prismatic joints<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#12500-prismatic-joints" class="hash-link" aria-label="Direct link to 12.500 prismatic joints" title="Direct link to 12.500 prismatic joints">​</a></h4>
<p>In this benchmark, we have 12.500 prismatic joints attached in a way that forms several independent chains.
Lower joint limits have been enabled.
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_2d_prismatic_joints-349d789fbd97f60f4bd999df628620cc.png" width="2174" height="1001" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_2d_prismatic_joints-ab2a0f3cd8969d3e6403ea07a933a875.svg" width="931" height="512" class="img_XsDP"></p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="2d-benchmark-conclusion">2D Benchmark: Conclusion<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#2d-benchmark-conclusion" class="hash-link" aria-label="Direct link to 2D Benchmark: Conclusion" title="Direct link to 2D Benchmark: Conclusion">​</a></h3>
<p>From these benchmarks we can see that.</p>
<ul>
<li>Rapier is generally slightly faster than Box2d in these benchmarks, especially when joints are involved.</li>
<li>Joint constraints from Rapier are much more stable than Box2d. In particular, prismatic joints from Box2d are subject to
lots of jitter, and the ball joints scenario completely exploded.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="running-the-benchmarks-yourself">Running the benchmarks yourself<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#running-the-benchmarks-yourself" class="hash-link" aria-label="Direct link to Running the benchmarks yourself" title="Direct link to Running the benchmarks yourself">​</a></h3>
<p>If you would like to see how these benchmarks perform on your own computer, you may run them manually:</p>
<ul>
<li>For 2D benchmarks, execute the command <code>cargo run --release --features simd-nightly --features other-backends -- --bench</code> on the
<code>examples2d</code> directory of the <a href="https://github.com/dimforge/rapier" target="_blank" rel="noopener noreferrer">rapier repository</a>.</li>
<li>For 3D benchmarks, execute the command <code>cargo run --release --features simd-nightly --features other-backends -- --bench</code> on the
<code>examples3d</code> directory of the <a href="https://github.com/dimforge/rapier" target="_blank" rel="noopener noreferrer">rapier repository</a>.</li>
</ul>
<p>If you are using a stable version of the Rust compiler, you will have to replace <code>--features simd-nightly</code> by
<code>--features simd-stable</code> so it compiles properly.</p>
<p>The benchmark will run and the outputs will be writen as CSV files created on the current directory. There will be one
CSV file per simulated scenario. A CSV file will contain multiple columns, one per running physics engine.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="conclusion">Conclusion<a href="https://dimforge.com/blog/2020/08/25/announcing-the-rapier-physics-engine#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h3>
<p>The development of Rapier started only five months ago and already shows very promising results. Its performance make it
a great 100% Rust alternative to <strong>PhysX</strong> as long as you don't need a GPU-based solution. For 2D it is often slightly better than
<strong>Box2D</strong> performance-wise, but it still lacks some features to be able to completely replace it. Compared to <strong>nphysics</strong>, <strong>Rapier</strong>
is at a whole different level both in terms of performance and joint constraint stability. Finally, thanks to its <strong>JavaScript</strong>
bindings, <strong>Rapier</strong> is both the most efficient and numerically stable Web physics engine
<a href="https://www.npmjs.com/package/@dimforge/rapier3d" target="_blank" rel="noopener noreferrer">available on NPM</a>.</p>
<p>Optional features like snapshotting and bit-level cross-platform determinism make <strong>Rapier</strong> appealing for multiplayer and
collaborative uses.</p>
<p>During the next ~8 months, our goal will be to implement in <strong>Rapier</strong> all the features that currently exist on <strong>nphysics</strong>,
including CCD, reduced-coordinates joints, and soft-bodies. If you need some specific features (even that did not exist
on nphysics), please feel free to <a href="mailto:contact@dimforge.com" target="_blank" rel="noopener noreferrer">contact us</a>.</p>
<p>If you would like to support us with the development of <strong>Rapier</strong>, please consider sponsoring us on
<a href="https://github.com/sponsors/dimforge" target="_blank" rel="noopener noreferrer">GitHub sponsor</a>.</p>
<p><strong>Thank you for your support!</strong></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Rustsim becomes Dimforge]]></title>
            <link>https://dimforge.com/blog/2020/08/18/rustsim-becomes-dimforge</link>
            <guid>https://dimforge.com/blog/2020/08/18/rustsim-becomes-dimforge</guid>
            <pubDate>Tue, 18 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Three years ago, I created Rustsim in order to group all the Rust projects I have been working on and maintaining since 2013.]]></description>
            <content:encoded><![CDATA[<p>Three years ago, I created Rustsim in order to group all the Rust projects I have been working on and maintaining since 2013.
Creating this organization on GitHub was one step further towards securing the future existence and maintenance of these Rust crates,
some of them being quite popular today like <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer">nalgebra</a> or <a href="https://nphysics.org/" target="_blank" rel="noopener noreferrer">nphysics</a>. Today,
I am going one step further and create my company named <strong>Dimforge</strong>.</p>
<center><img src="https://dimforge.com/img/logo/logo_dimforge_full.svg" alt="Dimforge logo"></center>
<p><strong>Dimforge</strong> is a French EURL (Entreprise Unipersonnelle à Responsabilité Limitée), which
can be translated to "single-member limited liability company".
It aims to be an <strong>open-source company</strong> which develops high-quality crates for linear algebra
and physics simulation. The decision to create <strong>Dimforge</strong> comes from both personal
and communitarial motivations:</p>
<ul>
<li>Creating this company is a way for me to further show my dedication to the Open-Source
Rust community by strengthening my involvement through a legal entity.
I always desired to work on my Open-Source projects full-time. This company creation
is one step further towards making this happen in a near future.</li>
<li>I will be able to setup partnerships with other companies to fund
the development of new features, and perhaps setup paid support plans.</li>
<li>If this becomes financially possible in the future, I will hire other Rust developers
to either work on my current projects, or on new projects they like if they are relevant to our objectives.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="how-is-dimforge-funded">How is Dimforge funded?<a href="https://dimforge.com/blog/2020/08/18/rustsim-becomes-dimforge#how-is-dimforge-funded" class="hash-link" aria-label="Direct link to How is Dimforge funded?" title="Direct link to How is Dimforge funded?">​</a></h2>
<p>Right now, Dimforge is entirely funded by me. In the short term I see the main sources of revenue
for the company to be:</p>
<ul>
<li>Donation crowdfunding through GitHub sponsor.</li>
<li>Development of a partnership with one of the industrial users of <strong>Rapier</strong> <em>(more about
this new project in the last section)</em>.</li>
</ul>
<p>If you supported me, <a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">@sebcrozet</a> directly through GitHub sponsor or Patreon, thank you again!
None of this would be possible without your help!
Please consider switching to <a href="https://github.com/sponsors/dimforge" target="_blank" rel="noopener noreferrer">the Dimforge GitHub sponsor account</a>.
That would be extremely helpful, especially for the first few years after this creation.</p>
<p>I will close my personal Patreon and GitHub Sponsor account at the end of this month.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="what-does-this-change">What does this change?<a href="https://dimforge.com/blog/2020/08/18/rustsim-becomes-dimforge#what-does-this-change" class="hash-link" aria-label="Direct link to What does this change?" title="Direct link to What does this change?">​</a></h2>
<p>From your point of view, as a end-user, this does not change anything. You can still use our crates freely. This should
actually reassure you that I am deeply committed to these crates, and will continue to maintain and improve them for
a long time in the future. There is however one exception: <strong>nphysics</strong>.</p>
<p>I you read Dimforge's landing page thoroughly, you may be surprised to see that <a href="https://nphysics.org/" target="_blank" rel="noopener noreferrer"><strong>nphysics</strong></a>, the 2D and 3D
physics engine I have been developing for the past 6 years, is now in passive maintenance mode. And it is even
more surprising considering I made <a href="https://www.patreon.com/posts/about-future-of-28917514" target="_blank" rel="noopener noreferrer">a post</a>
last year showing how I intended to develop <strong>nphysics</strong> for several years to come.</p>
<p>Did I lie? No. My desire to continue the development of <strong>nphysics</strong> was real, and still is but in a
different form. <strong>nphysics</strong> has a fair share of virtues and problems. Some of them are plain unsolvable considering
the current design of nphysics. Performance and lack of serialization for example are two recurring problems. This is why I am stopping the active
development of <strong>nphysics</strong> in order to work on its much needed successor <strong>Rapier</strong>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="rapier-the-flagship-project-of-dimforge">Rapier: the flagship project of Dimforge<a href="https://dimforge.com/blog/2020/08/18/rustsim-becomes-dimforge#rapier-the-flagship-project-of-dimforge" class="hash-link" aria-label="Direct link to Rapier: the flagship project of Dimforge" title="Direct link to Rapier: the flagship project of Dimforge">​</a></h2>
<p><a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer"><img decoding="async" loading="lazy" alt="rapier logo" src="https://dimforge.com/assets/images/rapier_logo_color_notext-0e6e7116a478cd845bc635a1867c1a99.svg" width="527" height="97" class="img_XsDP"></a></p>
<p><strong>Rapier</strong> is the new physics engine I have been working on secretly during the past 5 months. You can see its work-in-progress
website there: <a href="https://rapier.rs/" target="_blank" rel="noopener noreferrer">https://rapier.rs</a>.</p>
<div class="theme-admonition theme-admonition-note admonition_v1XZ alert alert--secondary"><div class="admonitionHeading_Nuk1"><span class="admonitionIcon_CHYS"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_nS2X"><p><strong>Rapier</strong> will be open-sourced in a few days, and will be properly announced
on a dedicated blog post that includes benchmarks.</p></div></div>
<p>Just like <strong>nphysics</strong> it is split into two crates: <strong>rapier2d</strong> and <strong>rapier3d</strong> for 2D and 3D physics respectively. It is designed
to be fast and multithreaded right from the beginning. It is also designed to require less incremental compilation times
because the data structures it defines are not generic.</p>
<p><strong>Rapier</strong> runs 5 to 10 times faster than <strong>nphysics</strong>, making it close to the performance of (the CPU version of) NVidia PhysX
and slightly faster than Box2D.</p>
<p>In addition, <strong>Rapier</strong> aims to be cross-platform, including web targets. That's why I am maintaining JavaScript bindings
right from the beginning. NPM packages already exist: <a href="https://www.npmjs.com/package/@dimforge/rapier3d" target="_blank" rel="noopener noreferrer">@dimforge/rapier3d</a>
and <a href="https://www.npmjs.com/package/@dimforge/rapier2d" target="_blank" rel="noopener noreferrer">@dimforge/rapier2d</a>.</p>
<p>I am still at the beginning of the implementation of <strong>Rapier</strong> though, so many features are still missing. However
some long-requested features like (optional) parallelism, and
(optional) SIMD have already been integrated to ensure their long-term maintenance and improvement.</p>
<p>There already are a few key features that makes Rapier stand out. Since they may affect compilation times and/or performance,
they are disabled by default and need to be enabled explicitly through cargo features. They are however both enabled on
our official NPM packages.</p>
<ol>
<li><strong>Serialization</strong>: every physics component is serializable using <code>serde</code>, meaning you can take a deep snapshot of the physics
state and restore it later. This snapshot can even be saved on disk or sent through network.</li>
<li><strong>Cross-platform determinism</strong>: if the <code>enhanced-determinism</code> feature of <strong>Rapier</strong> is enabled, you it will behave in
a <em>bit-level cross-platform deterministic</em> way in all platforms that comply with the IEEE 754-2008 floating point standard.
This means that if you run the same simulation with the same initial states on two different machines (or on a browser)
you will get the exact same results. Here "bit-level" determinism means that if you serialize the physics state after the
same number of timesteps on two different machines, you will obtain the exact same byte array for both: you may compute a checksum
of both snapshots and they will match. All this doesn't apply to 8- and 16-bits platforms, and on
platforms that don't comply to IEEE&nbsp;754-2008 strictly.</li>
</ol>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="the-start-of-a-new-adventure">The start of a new adventure<a href="https://dimforge.com/blog/2020/08/18/rustsim-becomes-dimforge#the-start-of-a-new-adventure" class="hash-link" aria-label="Direct link to The start of a new adventure" title="Direct link to The start of a new adventure">​</a></h2>
<p>This creation marks a milestone in my personal life, and it strengthens my dedication to Rust Open-Source development. This new
adventure is not without risks but also has its fair share of opportunities. I am convinced that Rust, the language, is doomed to succeed,
and that it has one of the best community one can hope for. So it is a privilege to be part of this community and do my
best to provide high-quality FOSS crates.</p>
<p><strong>Thank you for your support!</strong></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in rustsim \#11 (April - May 2020)]]></title>
            <link>https://dimforge.com/blog/2020/06/01/this-month-in-rustsim</link>
            <guid>https://dimforge.com/blog/2020/06/01/this-month-in-rustsim</guid>
            <pubDate>Mon, 01 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the tenth edition of This month in rustsim! This newsletter will provide you with a]]></description>
            <content:encoded><![CDATA[<p>Welcome to the tenth edition of <em>This month in rustsim</em>! This newsletter will provide you with a
summary of important update that occurred within the rustsim community. This includes in particular updates about
the <a href="https://nphysics.org/" target="_blank" rel="noopener noreferrer"><strong>nphysics</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>salva</strong></a> (fluid simulation), <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer"><strong>ncollide</strong></a> (for collision-detection),
<a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (for linear algebra), and
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>simba</strong></a> (for abstract algebra) crates. This eleventh edition will contain updates for the months of April and May 2020.</p>
<p>Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord</a> and on our <a href="https://discourse.nphysics.org/" target="_blank" rel="noopener noreferrer">user forum</a>!</p>
<p>Starting with the version 0.16, <strong>nphysics2d</strong> and <strong>nphysics3d</strong> can be used with <strong>fixed-point numbers</strong> as their scalar
type. This allows you to use fixed-point numbers from the <a href="https://crates.io/crates/simba" target="_blank" rel="noopener noreferrer"><code>simba</code> crate</a> (which wraps
fixed-points numbers from the <a href="https://crates.io/crates/fixed" target="_blank" rel="noopener noreferrer"><code>fixed</code> crate</a>) as the scalar type <code>N</code> of all the <strong>nphysics</strong>
entities. This will result in <strong>cross-platform determinism</strong> of the simulation.</p>
<p><em>This work was made possible by a <a href="https://github.com/sponsors/sebcrozet/" target="_blank" rel="noopener noreferrer"><strong>GitHub sponsorship</strong></a> dedicated to the implementation of this feature.</em></p>
<p><em>Cross-platform determinism</em> means that two scenes initialized in the exact same ways (including the same insertion order
of bodies/colliders) on two different machines/platforms will result in the exact same simulation result. This is generally not
possible with conventional hardware-accelerated floating point numbers like <code>f32</code> or <code>f64</code> because different
processors may process float operations with different levels of internal accuracy. This problem is avoided by using
fixed-point numbers. In order to make the simulation work with fixed-point numbers it is necessary to:</p>
<ol>
<li>Enable the <code>improved_fixed_point_support</code> cargo feature of <strong>nphysics</strong>. This will enable some numerical stability improvements
that can have a slight negative performance impact when enabled. They are necessary for fixed-point numbers to work.</li>
<li>Enable the <code>partial_fixed_point_support</code> cargo feature of <strong>simba</strong>, otherwise you won't have access to the simba fixed-point types.</li>
<li>Use at least 24 bits for the decimal part of the number. I tested mostly with
<a href="https://docs.rs/simba/0.1.4/simba/scalar/type.FixedI40F24.html" target="_blank" rel="noopener noreferrer"><code>simba::scalar::FixedI40F24</code></a> and
<a href="https://docs.rs/simba/0.1.4/simba/scalar/type.FixedI32F32.html" target="_blank" rel="noopener noreferrer"><code>simba::scalar::FixedI32F32</code></a>.</li>
<li>Be careful with the size of the colliders and the mass of the bodies. These should not be too large or too small to
avoid overflow or underflow of the fixed-point numbers. The exact valid range depends on the actual fixed-point numbers
you use. See the <strong>nphysics</strong> demos on the <a href="https://github.com/rustsim/nphysics/tree/master/examples2d" target="_blank" rel="noopener noreferrer">examples2d</a> and
<a href="https://github.com/rustsim/nphysics/tree/master/examples3d" target="_blank" rel="noopener noreferrer">examples3d</a> directories to get an idea of what dimensions
work. It is possible to experiment with various scalar types on the <strong>nphysics</strong> demos by changing the type alias <code>type Real = ...;</code> on the
<a href="https://github.com/rustsim/nphysics/blob/1ee5225cb1b57a676b1432fedad8a80a0c4a7c55/examples2d/all_examples2.rs#L69" target="_blank" rel="noopener noreferrer"><code>all_examples2.rs</code></a> and
<a href="https://github.com/rustsim/nphysics/blob/1ee5225cb1b57a676b1432fedad8a80a0c4a7c55/examples3d/all_examples3.rs#L72" target="_blank" rel="noopener noreferrer"><code>all_examples3.rs</code></a> demo files.</li>
</ol>
<p>The support of fixed-point numbers is considered experimental because it needs more testing in real-world applications.
So far most of the testing was done with the <strong>nphysics</strong> demos. Any non-deterministic behavior (even cross-platform) will
be considered a bug when using fixed-point numbers.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="about-the-new-cordic-crate">About the new <strong>cordic</strong> crate<a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#about-the-new-cordic-crate" class="hash-link" aria-label="Direct link to about-the-new-cordic-crate" title="Direct link to about-the-new-cordic-crate">​</a></h3>
<p>In order to make <strong>nphysics</strong> work with fixed-points numbers, it was necessary to implement various special function, namely
<code>sin, cos, tan, asin, acos, atan, atan2, exp, sqrt</code> for fixed-point numbers. They have been implemented using algorithms based on
the CORDIC method, available on the new <a href="https://crates.io/crates/cordic" target="_blank" rel="noopener noreferrer">cordic crate</a>.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="fixed-point-compatibility-of-simba-ncollide-and-nalgebra">Fixed-point compatibility of simba, ncollide, and nalgebra<a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#fixed-point-compatibility-of-simba-ncollide-and-nalgebra" class="hash-link" aria-label="Direct link to Fixed-point compatibility of simba, ncollide, and nalgebra" title="Direct link to Fixed-point compatibility of simba, ncollide, and nalgebra">​</a></h3>
<ul>
<li>The <strong>simba</strong> crate has the <code>partial_fixed_point_support</code> cargo feature. This will allow you to use all the <code>simba::scalar::Fixed*</code>
types. These aliases follow the <a href="https://docs.rs/fixed/1.0.0/fixed/types/index.html" target="_blank" rel="noopener noreferrer">naming convention</a> of the type the
wrap on the <strong>fixed crate</strong>. Note however that this fixed-point number support is only <strong>partial</strong>. Even though the <code>simba::scalar::RealField</code>
trait is implemented for these numbers, most of their special functions are just filled with <code>undefined!()</code>. The methods that are not
<code>undefined!()</code> are these needed by <strong>nphysics</strong> itself and implemented in the new <a href="https://crates.io/crates/cordic" target="_blank" rel="noopener noreferrer">cordic crate</a>.</li>
<li>The <strong>ncollide2d/ncollide3</strong> crates now have an <code>improved_fixed_point_support</code> cargo feature is well. This will also
enable some numerical stability improvements for fixed-point numbers.</li>
</ul>
<p>Note that this also means that <strong>nalgebra</strong> itself is now compatible with fixed-point numbers. Most transformation types, as
well as matrix decompositions will work too (as long as your input do not cause any overflow/underflow).</p>
<hr>
<h1>Other changes unrelated to deterministic physics</h1>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="changes-in-nalgebra">Changes in nalgebra<a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#changes-in-nalgebra" class="hash-link" aria-label="Direct link to Changes in nalgebra" title="Direct link to Changes in nalgebra">​</a></h3>
<p>A few features were added to <strong>nalgebra</strong> v0.21.1:</p>
<ul>
<li>It is now possible to build a Cholesky decomposition without checking that its input is positive-definite using
<code>Choleksy::new_unchecked</code>. Not having these checks also remove all branching from the Cholesky decomposition, making it
suitable to the use with SIMD types for, e.g., building the Cholesky decompositions of four matrices at once using a <code>Matrix4&lt;simba::simd::f32x4&gt;</code>.</li>
<li>Thanks to the contribution of <a href="https://github.com/m-ou-se" target="_blank" rel="noopener noreferrer">m-ou-se</a>, the <code>Default</code> trait is now implemented for matrices,
and quaternions. They are all filled with zeros, except for UnitQuaternion which is initialized with the identity.</li>
<li>Thanks to the contribution of <a href="https://github.com/fredrik-jansson-se" target="_blank" rel="noopener noreferrer">fredrik-jansson-se</a>, it is now posible to compute the
matrix exponential with <code>matrix.exp()</code>.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="changes-in-the-nphysics">Changes in the nphysics<a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#changes-in-the-nphysics" class="hash-link" aria-label="Direct link to Changes in the nphysics" title="Direct link to Changes in the nphysics">​</a></h3>
<ul>
<li>It is now possible to retrieve the number of <code>BodyPart</code> that compose a <code>Body</code> using <code>body.num_parts()</code>. This allows you to
iterate through all the parts on a loop like <code>for i in 0..body.num_parts() { let part = body.part(i); ... }</code>.</li>
<li>Thanks to the contribution of <a href="https://github.com/m-ou-se" target="_blank" rel="noopener noreferrer">m-ou-se</a> the testbeds of nphysics <strong>nphysics_testbed2d</strong> and
<strong>nphysics_testbed3d</strong> can now be used with scalar types other than <code>f32</code>.</li>
</ul>
<hr>
<h1>Thanks</h1>
<p>I would like to thank the whole community and contributors. In particular, thanks to the contributors from the past two months<sup><a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#user-content-fn-1-b025fa" id="user-content-fnref-1-b025fa" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/chiache-msft" target="_blank" rel="noopener noreferrer">chiache-msft</a></li>
<li><a href="https://github.com/fredrik-jansson-se" target="_blank" rel="noopener noreferrer">fredrik-jansson-se</a></li>
<li><a href="https://github.com/Hodapp87" target="_blank" rel="noopener noreferrer">Hodapp87</a></li>
<li><a href="https://github.com/jannickj" target="_blank" rel="noopener noreferrer">jannickj</a></li>
<li><a href="https://github.com/LiquidityC" target="_blank" rel="noopener noreferrer">LiquidityC</a></li>
<li><a href="https://github.com/m-ou-se" target="_blank" rel="noopener noreferrer">m-ou-se</a></li>
<li><a href="https://github.com/mxxo" target="_blank" rel="noopener noreferrer">mxxo</a></li>
<li><a href="https://github.com/Nateckert" target="_blank" rel="noopener noreferrer">Nateckert</a></li>
<li><a href="https://github.com/oisincar" target="_blank" rel="noopener noreferrer">oisincar</a></li>
<li><a href="https://github.com/philippeitis" target="_blank" rel="noopener noreferrer">philippeitis</a></li>
<li><a href="https://github.com/ProfFan" target="_blank" rel="noopener noreferrer">ProfFan</a></li>
<li><a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a></li>
</ul>
<ul>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new patrons supporting me, <a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a>, the
lead developer of the current crates part of this organization on <a href="http://patreon.com/sebcrozet" target="_blank" rel="noopener noreferrer">patreon</a> or <a href="https://github.com/sponsors/sebcrozet/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows me do spend a significant amount of time developing those crates.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-b025fa">
<p><em>The list of contributors is automatically generated from the past two months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2020/06/01/this-month-in-rustsim#user-content-fnref-1-b025fa" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in rustsim \#10 (March 2020)]]></title>
            <link>https://dimforge.com/blog/2020/04/01/this-month-in-rustsim</link>
            <guid>https://dimforge.com/blog/2020/04/01/this-month-in-rustsim</guid>
            <pubDate>Wed, 01 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the tenth edition of This month in rustsim! This newsletter will provide you with a]]></description>
            <content:encoded><![CDATA[<p>Welcome to the tenth edition of <em>This month in rustsim</em>! This newsletter will provide you with a
summary of important update that occurred within the rustsim community. This includes in particular updates about
the <a href="https://nphysics.org/" target="_blank" rel="noopener noreferrer"><strong>nphysics</strong></a> (physics engine),  <a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><strong>salva</strong></a> (fluid simulation), <a href="https://ncollide.org/" target="_blank" rel="noopener noreferrer"><strong>ncollide</strong></a> (for collision-detection),
<a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer"><strong>nalgebra</strong></a> (for linear algebra),
<a href="https://github.com/rustsim/simba" target="_blank" rel="noopener noreferrer"><strong>simba</strong></a>, and <a href="https://github.com/rustsim/alga" target="_blank" rel="noopener noreferrer"><strong>alga</strong></a> (for abstract algebra) crates. This tenth edition will contain updates for the month of March 2020.</p>
<p>Join us on <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord</a> and on our <a href="https://discourse.nphysics.org/" target="_blank" rel="noopener noreferrer">user forum</a>!</p>
<center><p><img decoding="async" loading="lazy" src="https://rustsim.org/img/logo_simba_wide_wide.svg" alt="simba logo" class="img_XsDP"></p></center>
<p>I am thrilled to announce the release of the new <a href="https://crates.io/crates/simba" target="_blank" rel="noopener noreferrer">simba</a> crate! <strong>Simba</strong> is a crate that defines
a set of traits for writing code that can be generic with regard to the number of lanes of the input numeric value.
Those traits are implemented by <code>f32</code>, <code>u32</code>, <code>i16</code>, <code>bool</code> as well as SIMD types like <code>f32x4, u32x8, i16x2</code>, etc.
Here is a diagram showing most of the traits of <strong>Simba</strong>:</p>
<center><p><img decoding="async" loading="lazy" src="https://rustsim.org/img/simba_trait_hierarchy.svg" alt="simba logo" class="img_XsDP"></p></center>
<p>Each solid arrow illustrates trait inheritance, e.g., <code>SimdRealField</code> is a subtrait of <code>SimdSigned</code>. Dashed arrows
illustrate blanket impls, e.g., any type implementing <code>RealField</code> also automatically implements <code>SimdRealField</code>.
All the <code>Simd*</code> traits (as well as <code>Field</code>) are implemented for SIMD types like <code>f32x8</code>, <code>f64x4</code> as well as scalar types like <code>f32</code> and <code>f64</code>.
Non-Simd traits on the other hand (except <code>Field</code>) are only implemented for scalar types.
by scalar types like <code>f32</code> and <code>f64</code> (and the blanket impls make them implement the <code>Simd*</code> traits too).
<strong>Simba</strong> is both much simpler and more easily extensible than our <a href="https://crates.io/crates/alga" target="_blank" rel="noopener noreferrer">alga</a> crate which has
a much deeper and complex trait hierarchy.</p>
<p>One example of use-case applied by the <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer">nalgebra crate</a> is to define generic methods
like vector normalization that will work for <code>Vector3&lt;f32&gt;</code> as well as <code>Vector3&lt;f32x4&gt;</code>.
This makes it easier leverage the power of <a href="https://www.rustsim.org/blog/2020/03/23/simd-aosoa-in-nalgebra/" target="_blank" rel="noopener noreferrer">SIMD Array-of-Struct-of-Array (AoSoA)</a>
with less code duplication.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="two-optional-cargo-features-can-be-enabled">Two optional cargo features can be enabled:<a href="https://dimforge.com/blog/2020/04/01/this-month-in-rustsim#two-optional-cargo-features-can-be-enabled" class="hash-link" aria-label="Direct link to Two optional cargo features can be enabled:" title="Direct link to Two optional cargo features can be enabled:">​</a></h4>
<ul>
<li>With the <strong><code>packed_simd</code></strong> feature enabled, the <code>simba::simd</code> module will export several SIMD types like <code>f32x2</code>,
<code>f64x4</code>, <code>i32i8</code>, <code>u16i16</code>, etc. There types are wrappers around the SIMD types from the <a href="https://docs.rs/packed_simd" target="_blank" rel="noopener noreferrer"><strong>packed_simd</strong>
crate</a>. <strong>This requires a nightly compiler.</strong></li>
<li>With the <strong><code>wide</code></strong> feature enabled, the <code>simba::simd</code> module will export the <code>WideF32x4</code> and <code>WideBoolF32x4</code>
types. These types are wrapper around the <code>wide::f32x4</code> type from the <a href="https://docs.rs/wide" target="_blank" rel="noopener noreferrer"><strong>wide</strong> crate</a>.
<strong>This will work with both stable and nightly compilers.</strong></li>
</ul>
<p>If none of those features are enabled, <strong>simba</strong> will define all the scalar and SIMD traits (and will be
compatible with both stable an nightly compilers). However, the SIMD traits won't be implemented for any
SIMD types. Therefore library developers writing generic code are not required to enable those features.
However, users who will pick concrete SIMD numeric types are recommended to:</p>
<ul>
<li>Enable the <code>packed_simd</code> feature and use the types like <code>simba::simd::{f32x4, i32x2, ...}</code> if they want the most complete
platform/numeric type coverage, and can afford to use a nightly compiler.</li>
<li>Enable the <code>wide</code> feature and use the <code>simba::simd::{WideF32x4, WideBoolF32x4}</code> if they only need 4-lanes
32-bits floats, and can't afford to use a nightly compiler.</li>
</ul>
<h1>Use of the Simba crate by nalgebra 0.21</h1>
<p>The use of Simba in the new version of <strong>nalgebra</strong> is what makes it possible to leverage the strengths of
SIMD AoSoA to obtain great performance boosts:</p>
<table><thead><tr><th>benchmark</th><th>nalgebra</th><th>nalgebra_f32x4</th><th>nalgebra_f32x8</th><th>nalgebra_f32x16</th></tr></thead><tbody><tr><td>euler 2d x10000</td><td>9.674 us</td><td>3.05 us</td><td>2.224 us</td><td><strong>2.076 us</strong></td></tr><tr><td>euler 3d x10000</td><td>18.18 us</td><td>4.791 us</td><td><strong>2.809 us</strong></td><td>3.014 us</td></tr><tr><td>isometry transform point2</td><td>22.8197 ns</td><td>7.8197 ns</td><td><strong>5.6563 ns</strong></td><td><strong>5.7179 ns</strong></td></tr><tr><td>isometry transform point3</td><td>60.0877 ns</td><td>15.4410 ns</td><td><strong>10.1237 ns</strong></td><td>10.5417 ns</td></tr><tr><td>isometry2 mul isometry2</td><td>34.5250 ns</td><td>10.1867 ns</td><td>9.2351 ns</td><td><strong>8.1413 ns</strong></td></tr><tr><td>isometry3 mul isometry3</td><td>97.8058 ns</td><td>26.0439 ns</td><td><strong>16.5287 ns</strong></td><td>29.0822 ns</td></tr><tr><td>matrix2 mul matrix2</td><td>24.7601 ns</td><td>10.3309 ns</td><td><strong>9.0379 ns</strong></td><td>10.6500 ns</td></tr><tr><td>matrix2 mul vector2</td><td>22.9934 ns</td><td>6.7758 ns</td><td><strong>5.2159 ns</strong></td><td>5.7680 ns</td></tr><tr><td>matrix3 mul matrix3</td><td>83.2946 ns</td><td>27.7722 ns</td><td><strong>19.6932 ns</strong></td><td>70.6877 ns</td></tr><tr><td>matrix3 mul vector3</td><td>46.1231 ns</td><td>13.6117 ns</td><td><strong>10.7913 ns</strong></td><td><strong>10.6031 ns</strong></td></tr><tr><td>matrix4 mul matrix4</td><td>0.1247 us</td><td>0.07657 us</td><td><strong>0.06835 us</strong></td><td>0.2354 us</td></tr><tr><td>matrix4 mul vector4</td><td>30.6785 ns</td><td>20.7324 ns</td><td><strong>15.4389 ns</strong></td><td>39.0102 ns</td></tr><tr><td>quaternion mul quaternion</td><td>30.0095 ns</td><td>12.3669 ns</td><td><strong>9.4567 ns</strong></td><td><strong>9.3504 ns</strong></td></tr><tr><td>quaternion mul vector3</td><td>49.3278 ns</td><td>13.3755 ns</td><td><strong>7.7526 ns</strong></td><td>8.5309 ns</td></tr><tr><td>vector3 cross</td><td>26.0655 ns</td><td>6.3479 ns</td><td>4.5852 ns</td><td><strong>4.4663 ns</strong></td></tr><tr><td>vector3 dot</td><td>25.3941 ns</td><td>6.4285 ns</td><td><strong>4.5232 ns</strong></td><td><strong>4.4944 ns</strong></td></tr><tr><td>vector3 length</td><td>20.7343 ns</td><td>5.4675 ns</td><td><strong>3.5936 ns</strong></td><td><strong>3.5110 ns</strong></td></tr><tr><td>vector3 normalize</td><td>61.5877 ns</td><td>15.4976 ns</td><td>8.3383 ns</td><td><strong>7.8013 ns</strong></td></tr></tbody></table>
<p>Refer to the <a href="https://www.rustsim.org/blog/2020/03/23/simd-aosoa-in-nalgebra/" target="_blank" rel="noopener noreferrer">full benchmark</a> for details about those
numbers and comparison with other linear algebra crates.</p>
<ul>
<li>Before the version 0.21, <strong>nalgebra</strong> relied on the traits from the <strong>alga</strong> crate (e.g. <code>RealField</code>, <code>ComplexField</code>, etc).
Those traits have now been replaced by the traits from the <strong>simba</strong> crate which have similar names.
For example the equivalent of <code>alga::general::{RealField, ComplexField}</code> is <code>simba::scalar::{RealField, ComplexField}</code>.</li>
<li>In many places, you will see the <code>SimdRealField</code> or <code>SimdComplexField</code> traits which are slightly more general than
<code>RealField</code> and <code>ComplexField</code> because they are also implemented for SIMD types like <code>f32x4</code>, <code>f64x2</code>, etc.</li>
<li>The dependency to <strong>alga</strong> is now completely optional. All the implementations of <strong>alga</strong> traits are still present,
though the <code>alga</code> cargo feature must be enabled to get them.</li>
</ul>
<p>The <code>linalg</code> and <code>sparse</code> modules don't use the <code>SimdRealField</code> and <code>SimdComplexField</code> traits at all. This is because the
algorithms they implement are full of branching, and thus are difficult to rewrite in an SIMD AoSoA friendly manner.
Finally, note that:</p>
<ol>
<li>If you are not using any generics with nalgebra, chances are that your code will still compile as-is.</li>
<li>If you are using some generics, chances are that simply replacing all occurrences of
<code>alga::general::{RealField, ComplexField}</code> by <code>simba::scalar::{RealField, ComplexField}</code> will likely do the trick.</li>
</ol>
<h1>The status of alga</h1>
<p>Starting today, the <strong>alga</strong> crate switches to passive maintenance mode. Unfortunately, the traits structure of <strong>alga</strong>
is very complicated, and makes it hardly accessible to users without strong knowledge about set theory. Moreover it does
not seem to be much used within the community. Thoses are other reasons why <strong>nalgebra</strong> is now relies on traits from
<strong>simba</strong> instead of <strong>alga</strong>.</p>
<h1>Thanks</h1>
<p>We would like to thank the whole community and contributors. In particular, thanks to the contributors from the past month<sup><a href="https://dimforge.com/blog/2020/04/01/this-month-in-rustsim#user-content-fn-1-c32206" id="user-content-fnref-1-c32206" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/Aaron1011" target="_blank" rel="noopener noreferrer">Aaron1011</a></li>
<li><a href="https://github.com/Andlon" target="_blank" rel="noopener noreferrer">Andlon</a></li>
<li><a href="https://github.com/DasEtwas" target="_blank" rel="noopener noreferrer">DasEtwas</a></li>
<li><a href="https://github.com/ProfFan" target="_blank" rel="noopener noreferrer">ProfFan</a></li>
<li><a href="https://github.com/SBrandeis" target="_blank" rel="noopener noreferrer">SBrandeis</a></li>
<li><a href="https://github.com/alexbool" target="_blank" rel="noopener noreferrer">alexbool</a></li>
<li><a href="https://github.com/aweinstock314" target="_blank" rel="noopener noreferrer">aweinstock314</a></li>
<li><a href="https://github.com/azriel91" target="_blank" rel="noopener noreferrer">azriel91</a></li>
<li><a href="https://github.com/cuviper" target="_blank" rel="noopener noreferrer">cuviper</a></li>
<li><a href="https://github.com/daingun" target="_blank" rel="noopener noreferrer">daingun</a></li>
<li><a href="https://github.com/eclipseo" target="_blank" rel="noopener noreferrer">eclipseo</a></li>
<li><a href="https://github.com/hmunozb" target="_blank" rel="noopener noreferrer">hmunozb</a></li>
<li><a href="https://github.com/ignatenkobrain" target="_blank" rel="noopener noreferrer">ignatenkobrain</a></li>
<li><a href="https://github.com/ilya-epifanov" target="_blank" rel="noopener noreferrer">ilya-epifanov</a></li>
<li>Kristof Lünenschloß</li>
<li><a href="https://github.com/kubkon" target="_blank" rel="noopener noreferrer">kubkon</a></li>
<li><a href="https://github.com/m-ou-se" target="_blank" rel="noopener noreferrer">m-ou-se</a></li>
<li><a href="https://github.com/nestordemeure" target="_blank" rel="noopener noreferrer">nestordemeure</a></li>
<li><a href="https://github.com/nnmm" target="_blank" rel="noopener noreferrer">nnmm</a></li>
<li><a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a></li>
<li><a href="https://github.com/waywardmonkeys" target="_blank" rel="noopener noreferrer">waywardmonkeys</a></li>
</ul>
<ul>
<li>Thanks to users reporting spelling mistakes on the documentation. This is always appreciated.</li>
<li>Thanks to users joining us on our <a href="https://discord.gg/vt9DJSW" target="_blank" rel="noopener noreferrer">discord server</a> to provide feedbacks,
discuss features, and get assistance!</li>
</ul>
<p>Finally, thanks to all the former, current and new patrons supporting me, <a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a>, the
lead developer of the current crates part of this organization on <a href="http://patreon.com/sebcrozet" target="_blank" rel="noopener noreferrer">patreon</a> or <a href="https://github.com/sponsors/sebcrozet/" target="_blank" rel="noopener noreferrer">GitHub sponsors</a>!
This help is greatly appreciated and allows me do spend a significant amount of time developing those crates.</p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorWithHideOnScrollNavbar_jgva sr-only" id="footnote-label">Footnotes<a href="https://dimforge.com/blog/2020/04/01/this-month-in-rustsim#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes">​</a></h2>
<ol>
<li id="user-content-fn-1-c32206">
<p><em>The list of contributors is automatically generated from the past months' github commit history.
Don't hesitate to let us know if your name should have been mentioned here.</em> <a href="https://dimforge.com/blog/2020/04/01/this-month-in-rustsim#user-content-fnref-1-c32206" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
    </channel>
</rss>