<?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>Sun, 05 Apr 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[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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#![cfg_attr(target_arch = </span><span class="token attribute attr-name string" style="color:rgb(195, 232, 141)">"spirv"</span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">, no_std)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal_std</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">glamx</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">UVec3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal_std</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">macros</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">spirv_bindgen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> spirv</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[spirv_bindgen]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[spirv(compute(threads(64)))]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">gpu_add_assign</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[spirv(global_invocation_id)]</span><span class="token plain"> invocation_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">UVec3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[spirv(storage_buffer, descriptor_set = 0, binding = 0)]</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[spirv(storage_buffer, descriptor_set = 0, binding = 1)]</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> thread_id </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> invocation_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> thread_id </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">len</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">thread_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">thread_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">backend</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token class-name" style="color:rgb(255, 203, 107)">Backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Encoder</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuBackend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuBackendError</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">WebGpu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">re_exports</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">include_dir</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token class-name" style="color:rgb(255, 203, 107)">Dir</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> include_dir</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token class-name" style="color:rgb(255, 203, 107)">BufferUsages</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Shader</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal_example_shaders</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">AddAssign</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">SPIRV_DIR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Dir</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token lifetime-annotation symbol">'static</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token macro property">include_dir!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"$CARGO_MANIFEST_DIR/shaders-spirv"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[derive(Shader)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">GpuKernels</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    add_assign</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuAddAssign</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[async_std::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> webgpu </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">WebGpu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">unwrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> backend </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuBackend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">WebGpu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">webgpu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Run the operation and display the result.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">10000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">map</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token closure-params">i</span><span class="token closure-params closure-punctuation punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">collect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vec</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">_</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> b </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">10000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">map</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token closure-params">i</span><span class="token closure-params closure-punctuation punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">10.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">collect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vec</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">_</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">compute_sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">unwrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token macro property">println!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Computed sum: {result:?}"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">compute_sum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuBackend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Result</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vec</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuBackendError</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Generate the GPU buffers.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">init_buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">BufferUsages</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">STORAGE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">BufferUsages</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">COPY_SRC</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> b </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">init_buffer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">BufferUsages</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">STORAGE</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Dispatch the operation on the gpu.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> kernels </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">GpuKernels</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">from_backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> encoder </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">begin_encoding</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> pass </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> encoder</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">begin_pass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"add_assign"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    kernels</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">add_assign</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">call</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> pass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">len</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">drop</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">pass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">submit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">encoder</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Read the result (slower but convenient version).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">slow_read_vec</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-sh codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Install the cargo subcommands</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cargo install cargo-gpu --version 0.10.0-alpha.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cargo install cargo-cuda</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Install the toolchains used by both commands</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cargo gpu install</span><br></span><span class="token-line" style="color:#bfc7d5"><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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">khal_builder</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">KhalBuilder</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> shader_crate </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"../khal-example-shaders"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> output_dir </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"shaders-spirv"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">KhalBuilder</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">shader_crate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">build</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">output_dir</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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.rs/" 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.rs/examples#ui" target="_blank" rel="noopener noreferrer">egui</a>,  <a href="https://www.kiss3d.rs/examples#instancing3d" target="_blank" rel="noopener noreferrer">instancing</a> and <a href="https://www.kiss3d.rs/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>
<center><table style="border:none;border-collapse:collapse"><tbody><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-1" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-1.png" width="300" title="3D primitives"></a><br>3D primitives</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-2" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-2.png" width="300" title="Multiple lights"></a><br>Multiple lights</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-4" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-4.png" width="300" title="Meshes, lines, points"></a><br>Meshes, lines, points</td></tr><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-5" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-5.png" width="300" title="Obj and textures"></a><br>Obj and textures</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-6" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-6.png" width="300" title="Post-processing effects"></a><br>Post-processing effects</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-7" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-7.png" width="300" title="Instancing 10.000 2D rectangles"></a><br>Instancing 10.000 2D rectangles</td></tr><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-8" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-8.png" width="300" title="Instancing 1.000.000 3D cubes"></a><br>Instancing 1.000.000 3D cubes</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-9" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-9.png" width="300" title="3D Polylines"></a><br>3D Polylines</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/reviving-kiss3d-a-simple-3d-and-2d-graphics-engine#lightbox-10" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/kiss3d-demo-10.png" width="300" title="egui support"></a><br>egui support</td></tr></tbody></table></center><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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">kiss3d</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">prelude</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[kiss3d::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> window </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Kiss3d: cube"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> camera </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">OrbitCamera3d</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> scene </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SceneNode3d</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">empty</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    scene</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">add_light</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Light</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">point</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">100.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">set_position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vec3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">0.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> cube </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> scene</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">add_cube</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">set_color</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">RED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> rot </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Quat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">from_axis_angle</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vec3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">Y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.014</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// axis-angle in radians</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">render_3d</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> scene</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        cube</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">rotate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rot</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">kiss3d</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token namespace" style="color:rgb(178, 204, 214)">prelude</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[kiss3d::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> window </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Kiss3d: rectangle"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> camera </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">PanZoomCamera2d</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vec2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">ZERO</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">5.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> scene </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SceneNode2d</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">empty</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> cube </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> scene</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">add_rectangle</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">100.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">150.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">set_color</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">RED</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> rot </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.014</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// radians</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">while</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">render_2d</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> scene</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        cube</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">rotate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rot</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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.rs/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.rs/" target="_blank" rel="noopener noreferrer">https://kiss3d.rs</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" 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.rs/" 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>
<center><table style="border:none;border-collapse:collapse"><tbody><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#voxels-1" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/voxels2d.png" width="500" title="2D voxels and primitives"></a><br>2D voxels and primitives</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#voxels-2" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/voxels3d.png" width="500" title="3D voxels and primitives"></a><br>3D voxels and primitives</td></tr></tbody></table></center><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>
<center><table style="border:none;border-collapse:collapse"><tbody><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-1" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/bench1.png" width="300" title="8000 balls"></a><br>8000 balls</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-2" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/bench2.png" width="300" title="19.800 spherical joints"></a><br>19.800 spherical joints</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-5" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/bench5.png" width="300" title="8000 revolute joints"></a><br>8000 revolute joints</td></tr><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-3" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/bench3.png" width="300" title="Falling stacks of 3027 cubes"></a><br>Falling stacks of 3027 cubes</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-4" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/bench4.png" width="300" title="Single tower made of 5320 planks"></a><br>Single tower made of 5320 planks</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#bench-6" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/bench6.png" width="300" title="40 pyramids with 210 cubes each"></a><br>40 pyramids with 210 cubes each</td></tr></tbody></table></center><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>
<center><table style="border:none;border-collapse:collapse"><tbody><tr><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgrapier-1" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/wgrapier3d-1.png" width="500" title="93.000 bodies and 120.000 joints"></a><br>93.000 bodies and 120.000 joints</td><td style="padding:4px;border:none;text-align:center"><a href="https://dimforge.com/blog/2026/01/09/the-year-2025-in-dimforge#wgrapier-2" style="cursor:pointer"><img src="https://dimforge.com/img/blog/2026-01-09/wgrapier3d-2.png" width="500" title="stack of 34.000 planks"></a><br>stack of 34.000 planks</td></tr></tbody></table></center><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" 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" 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" 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" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="MPM 2d" src="https://dimforge.com/assets/images/mpm_cuda_2d-60e0b5d478d9f3b626b7ea9858507f55.gif" 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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[derive(Bundle)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">RigidBodyBundle</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> body_type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyPosition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> velocity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyVelocity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> mass_properties</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyMassProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> forces</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyForces</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> activation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyActivation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> damping</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyDamping</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> dominance</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyDominance</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> ccd</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyCcd</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> changes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyChanges</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> ids</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyIds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> colliders</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">RigidBodyColliders</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 203, 107)">#[derive(Bundle)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">ColliderBundle</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> collider_type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> shape</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderShape</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderPosition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> material</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderMaterial</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> flags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderFlags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> mass_properties</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderMassProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> changes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderChanges</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> bf_data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ColliderBroadPhaseData</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">nalgebra</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">vector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> matrix</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> vec3 </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token macro property">vector!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Constructs a `Vector3`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> pt2 </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token macro property">point!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Constructs a `Point2`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> mat2x3 </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token macro property">matrix!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token number" style="color:rgb(247, 140, 108)">11.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">12.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">13.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// The ; delimits each row of the matrix.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token number" style="color:rgb(247, 140, 108)">21.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">22.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">23.0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Constructs a `Matrix2x3`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> dvec </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token macro property">dvector!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">MY_VECTOR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector2</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token macro property">vector!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Array</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">T</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">LENGTH</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    list</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token class-name" style="color:rgb(255, 203, 107)">T</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">LENGTH</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><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:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">nalgebra</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token class-name" style="color:rgb(255, 203, 107)">DimName</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MatrixMN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">VectorN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">DefaultAllocator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">allocator</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Integrator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">DimName</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">where</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">DefaultAllocator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  m</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MatrixMN</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  v</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">VectorN</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  p</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">DimName</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Integrator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">where</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">DefaultAllocator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// using `f64` intermediate results.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">pub</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">integrate_highp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> dt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">where</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token class-name" style="color:rgb(255, 203, 107)">MatrixMN</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Copy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token class-name" style="color:rgb(255, 203, 107)">VectorN</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Copy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Copy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token class-name" style="color:rgb(255, 203, 107)">DefaultAllocator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Allocator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// First cast all the operants to `f64`:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">m</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> p</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">m</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">v</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">p</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Perform the computation with f64 precision, then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// cast the result to f32.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">p </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> m </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> v </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> dt </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f64</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><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:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">nalgebra</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SMatrix</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SVector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Integrator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  m</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SMatrix</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  v</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SVector</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  p</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Integrator</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// using `f64` intermediate results.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">integrate_highp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> dt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// First cast all the operants to `f64`:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">m</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> p</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">m</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">v</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">p</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Perform the computation with f64 precision, then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// cast the result to f32.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">p </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> m </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> v </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token plain"> dt </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f64</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">cast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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" 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" 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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">use</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">nalgebra</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Matrix2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Quaternion</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Translation3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">VECTOR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector3</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">u32</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">POINT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point4</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Point4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">MATRIX</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Matrix2</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">i32</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Matrix2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                                          </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">QUATERNION</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Quaternion</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f64</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Quaternion</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">TRANSLATION</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Translation3</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">f32</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Translation3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token function" style="color:rgb(130, 170, 255)">new</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">impl</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">T</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">LENGTH</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">T</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">LENGTH</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">push</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">T</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">LENGTH</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token macro property">unimplemented!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">D</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">trait</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">trait</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">ToConst</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToConst</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToConst</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);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:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">//     limit (currently 127 in nalgebra).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">impl</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">R</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">usize</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">N</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">R</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">push</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">N</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Sum</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">R</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U1</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToConst</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">where</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">R</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">R</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Add</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U1</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token class-name" style="color:rgb(255, 203, 107)">Sum</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">Const</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token class-name" style="color:rgb(255, 203, 107)">R</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToTypenum</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token class-name" style="color:rgb(255, 203, 107)">Output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">typenum</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token constant" style="color:rgb(130, 170, 255)">U1</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ToConst</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token macro property">unimplemented!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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" 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" 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" 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" 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" 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" 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" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_ryzen_balls-7f1998698558b8946a8bb80917a9749a.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_intel_balls-ad267cdf226bff9093cb2bd36eb9579d.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_ryzen_boxes-b1e48a6316a00b8779cc37ff08303148.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_intel_boxes-f33dea28cd5d966b06262162e0e2d59e.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_ryzen_pyramid-5102921ac8f8ee8fbc466dd6d0f9d5ca.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_intel_pyramid-c869bb3f9ac6963d1a3f07f8bf28f0c1.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench trimesh" src="https://dimforge.com/assets/images/bench_ryzen_trimesh-05447cf364ea1c763d22b32c52ad4ce4.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench trimesh" src="https://dimforge.com/assets/images/bench_intel_trimesh-32f3daff1113e018e018e4b97ac309d0.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench keva tower" src="https://dimforge.com/assets/images/bench_ryzen_keva_tower-f5b5f7465367225c0ccc5449aefd978e.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench keva tower" src="https://dimforge.com/assets/images/bench_intel_keva_tower-42b1da6859a6cec02fd5404de3554649.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench ball joints" src="https://dimforge.com/assets/images/bench_ryzen_ball_joints-70fcfaed2e3e0e36de336d87fae3eba9.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench ball joints" src="https://dimforge.com/assets/images/bench_intel_ball_joints-5da93a3d8c803686737b4305d50c6e14.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_ryzen_fixed_joints-5c3dd011286da2aef9ca178d7d4b1024.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_intel_fixed_joints-f09b888eeae9200a8aa8057c2af02dc2.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_ryzen_revolute_joints-d8a222459ca035bc8f92c2b03c4b2c10.svg" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_intel_revolute_joints-f5508c9644110e62f77bdfe81a7b12d8.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench balls" src="https://dimforge.com/assets/images/bench_2d_balls-69f821734d138c6d529cc78a08925b2b.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench boxes" src="https://dimforge.com/assets/images/bench_2d_boxes-28f7ad791e036d40baae4f254b7cd488.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench pyramid" src="https://dimforge.com/assets/images/bench_2d_pyramid-c62a6525a65f07c57abe8c5ce4c83693.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench ball joints" src="https://dimforge.com/assets/images/bench_2d_ball_joints-9374a419e56b7a6e06ed87fee201d4c7.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench fixed joints" src="https://dimforge.com/assets/images/bench_2d_fixed_joints-2f7f46c36d80d21ee7538683a0ca32af.svg" 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" class="img_XsDP">
<img decoding="async" loading="lazy" alt="bench revolute joints" src="https://dimforge.com/assets/images/bench_2d_prismatic_joints-ab2a0f3cd8969d3e6403ea07a933a875.svg" 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" 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>
        <item>
            <title><![CDATA[SIMD Array-of-Structures-of-Arrays in nalgebra and comparison with ultraviolet]]></title>
            <link>https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra</link>
            <guid>https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra</guid>
            <pubDate>Mon, 23 Mar 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Hello everyone!]]></description>
            <content:encoded><![CDATA[<p><strong>Hello everyone!</strong></p>
<p>In this post I'd like to introduce the next major change that will be released in <strong><a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer">nalgebra</a></strong> at the end of this month (March 2020).
This change is about adding the support for SIMD AoSoA to <strong>nalgebra</strong>. I'll explain what I mean by SIMD AoSoA (Array-of-Structures-of-Arrays with explicit SIMD) and how it relates
to SoA (Structure-of-Arrays) and AoS (Array-of-Structures). To give you an idea, SIMD AoSoA is actually what the recent <strong><a href="https://crates.io/crates/ultraviolet" target="_blank" rel="noopener noreferrer">ultraviolet</a></strong>
crate has been using to achieve its amazing performance.</p>
<p>Here is a benchmark including the next (to-be-released) version of <strong>nalgebra</strong>. The best times within a 2.5% range of the minimum of each row are highlighted.
Here, the <strong>ultraviolet</strong> column uses the non-<em>wide</em> types
of <code>ultraviolet</code> (<code>Vec2</code>, <code>Mat2</code>, <code>Isometry3</code>, etc.) while the column <strong>ultraviolet_f32x4</strong> uses its <em>wide</em> types (<code>Wec2</code>, <code>Wat2</code>, <code>WIsometry3</code>, etc.):</p>
<table><thead><tr><th>benchmark</th><th>nalgebra_f32x4</th><th>ultraviolet_f32x4</th><th>nalgebra</th><th>ultraviolet</th><th>glam</th><th>vek</th><th>cgmath</th><th>euclid</th></tr></thead><tbody><tr><td>euler 2d x10000</td><td><strong>2.992 us</strong></td><td><strong>3.014 us</strong></td><td>9.028 us</td><td>5.28 us</td><td>5.166 us</td><td>5.258 us</td><td>5.259 us</td><td>8.631 us</td></tr><tr><td>euler 3d x10000</td><td><strong>4.546 us</strong></td><td><strong>4.587 us</strong></td><td>17.84 us</td><td>18.34 us</td><td>6.311 us</td><td>17.57 us</td><td>18.04 us</td><td>17.97 us</td></tr><tr><td>isometry transform point2 x1</td><td><strong>8.1024 ns</strong></td><td>8.6412 ns</td><td>23.4637 ns</td><td>54.5840 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point2 x100</td><td><strong>2.801 us</strong></td><td><strong>2.837 us</strong></td><td>3.109 us</td><td>4.918 us</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point3 x1</td><td><strong>16.1052 ns</strong></td><td>20.6723 ns</td><td>61.8824 ns</td><td>330.1143 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point3 x100</td><td><strong>4.515 us</strong></td><td>4.794 us</td><td>6.546 us</td><td>18.19 us</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry2 inverse</td><td><strong>7.3004 ns</strong></td><td>7.7692 ns</td><td>24.8090 ns</td><td>59.3838 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry2 mul isometry2</td><td><strong>12.3278 ns</strong></td><td>12.7816 ns</td><td>34.5714 ns</td><td>110.7837 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry3 inverse</td><td><strong>17.1929 ns</strong></td><td>21.4199 ns</td><td>63.9200 ns</td><td>212.2193 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry3 mul isometry3</td><td><strong>27.3814 ns</strong></td><td>40.3955 ns</td><td>100.4628 ns</td><td>447.4780 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>matrix2 determinant</td><td>N/A</td><td>N/A</td><td>16.0198 ns</td><td>N/A</td><td><strong>11.2070 ns</strong></td><td>15.8621 ns</td><td>16.0906 ns</td><td>N/A</td></tr><tr><td>matrix2 inverse</td><td>N/A</td><td>N/A</td><td>26.5165 ns</td><td>N/A</td><td><strong>18.9069 ns</strong></td><td>N/A</td><td>26.2478 ns</td><td>N/A</td></tr><tr><td>matrix2 mul matrix2</td><td>12.5352 ns</td><td><strong>10.7532 ns</strong></td><td>25.4533 ns</td><td>25.7148 ns</td><td>16.3060 ns</td><td>301.3775 ns</td><td>25.6988 ns</td><td>N/A</td></tr><tr><td>matrix2 mul vector2 x1</td><td><strong>7.1695 ns</strong></td><td>8.0907 ns</td><td>23.0932 ns</td><td>24.4506 ns</td><td>16.4141 ns</td><td>93.3601 ns</td><td>25.0774 ns</td><td>N/A</td></tr><tr><td>matrix2 mul vector2 x100</td><td><strong>2.684 us</strong></td><td><strong>2.698 us</strong></td><td>3.137 us</td><td>3.174 us</td><td>2.828 us</td><td>9.558 us</td><td>3.122 us</td><td>N/A</td></tr><tr><td>matrix2 transpose</td><td><strong>6.4984 ns</strong></td><td>N/A</td><td>11.0205 ns</td><td>N/A</td><td>10.9890 ns</td><td>10.8180 ns</td><td>10.3812 ns</td><td>N/A</td></tr><tr><td>matrix3 determinant</td><td>N/A</td><td>N/A</td><td>33.1252 ns</td><td>N/A</td><td><strong>22.2592 ns</strong></td><td>31.8128 ns</td><td>31.7086 ns</td><td>N/A</td></tr><tr><td>matrix3 inverse</td><td>N/A</td><td><strong>26.7493 ns</strong></td><td>92.8270 ns</td><td>284.1032 ns</td><td>93.5328 ns</td><td>N/A</td><td>82.3820 ns</td><td>N/A</td></tr><tr><td>matrix3 mul matrix3</td><td>0.02883 us</td><td><strong>0.02638 us</strong></td><td>0.09077 us</td><td>0.08728 us</td><td>0.0474 us</td><td>1.005 us</td><td>0.08579 us</td><td>N/A</td></tr><tr><td>matrix3 mul vector3 x1</td><td><strong>13.7548 ns</strong></td><td><strong>13.6309 ns</strong></td><td>46.4205 ns</td><td>46.5016 ns</td><td>21.5466 ns</td><td>317.8168 ns</td><td>47.3542 ns</td><td>N/A</td></tr><tr><td>matrix3 mul vector3 x100</td><td><strong>4.835 us</strong></td><td><strong>4.917 us</strong></td><td>6.138 us</td><td>6.261 us</td><td>6.633 us</td><td>32.93 us</td><td>6.297 us</td><td>N/A</td></tr><tr><td>matrix3 transpose</td><td><strong>15.7501 ns</strong></td><td><strong>15.4925 ns</strong></td><td>52.7300 ns</td><td>53.0845 ns</td><td>24.1975 ns</td><td>55.4793 ns</td><td>52.0874 ns</td><td>N/A</td></tr><tr><td>matrix4 determinant</td><td>N/A</td><td>N/A</td><td>690.7027 ns</td><td>N/A</td><td><strong>85.5778 ns</strong></td><td>176.1770 ns</td><td>110.6990 ns</td><td>174.6754 ns</td></tr><tr><td>matrix4 inverse</td><td>N/A</td><td><strong>0.08342 us</strong></td><td>0.5282 us</td><td>0.3953 us</td><td>0.257 us</td><td>3.792 us</td><td>0.5096 us</td><td>0.651 us</td></tr><tr><td>matrix4 mul matrix4</td><td><strong>0.06897 us</strong></td><td><strong>0.07068 us</strong></td><td>0.1285 us</td><td>0.1493 us</td><td>0.07653 us</td><td>2.024 us</td><td>0.1185 us</td><td>0.1152 us</td></tr><tr><td>matrix4 mul vector4 x1</td><td><strong>21.1243 ns</strong></td><td><strong>20.6690 ns</strong></td><td>31.5352 ns</td><td>30.3570 ns</td><td>24.7876 ns</td><td>512.0570 ns</td><td>30.9776 ns</td><td>N/A</td></tr><tr><td>matrix4 mul vector4 x100</td><td><strong>7.595 us</strong></td><td><strong>7.662 us</strong></td><td>8.472 us</td><td>8.379 us</td><td>7.823 us</td><td>51.42 us</td><td>8.366 us</td><td>N/A</td></tr><tr><td>matrix4 transpose</td><td><strong>26.2948 ns</strong></td><td>27.1962 ns</td><td>103.0829 ns</td><td>101.3104 ns</td><td>29.2236 ns</td><td>105.6003 ns</td><td>98.1151 ns</td><td>N/A</td></tr><tr><td>quaternion conjugate</td><td><strong>6.6130 ns</strong></td><td><strong>6.6179 ns</strong></td><td>24.5468 ns</td><td>25.5657 ns</td><td>11.1447 ns</td><td>24.2229 ns</td><td>25.7246 ns</td><td>24.9413 ns</td></tr><tr><td>quaternion mul quaternion</td><td><strong>14.6380 ns</strong></td><td>16.6299 ns</td><td>39.3908 ns</td><td>274.4676 ns</td><td>27.3533 ns</td><td>62.0697 ns</td><td>35.0299 ns</td><td>59.5286 ns</td></tr><tr><td>quaternion mul vector3</td><td><strong>14.7579 ns</strong></td><td>18.5064 ns</td><td>52.7303 ns</td><td>170.8328 ns</td><td>44.1336 ns</td><td>81.1243 ns</td><td>52.5011 ns</td><td>54.1958 ns</td></tr><tr><td>transform point2 x1</td><td>N/A</td><td>N/A</td><td>36.6350 ns</td><td>N/A</td><td><strong>25.6516 ns</strong></td><td>337.3442 ns</td><td>30.5781 ns</td><td>28.5532 ns</td></tr><tr><td>transform point2 x100</td><td>N/A</td><td>N/A</td><td>5.475 us</td><td>N/A</td><td>5.732 us</td><td>33.81 us</td><td>5.118 us</td><td><strong>4.003 us</strong></td></tr><tr><td>transform point3 x1</td><td>N/A</td><td>N/A</td><td>66.3694 ns</td><td>N/A</td><td><strong>24.0601 ns</strong></td><td>517.9224 ns</td><td>67.8205 ns</td><td>68.0836 ns</td></tr><tr><td>transform point3 x100</td><td>N/A</td><td>N/A</td><td>9.403 us</td><td>N/A</td><td><strong>7.824 us</strong></td><td>52.5 us</td><td>9.559 us</td><td>10.07 us</td></tr><tr><td>transform vector2 x1</td><td>N/A</td><td>N/A</td><td>32.5667 ns</td><td>N/A</td><td><strong>21.3971 ns</strong></td><td>330.5713 ns</td><td>N/A</td><td>23.5693 ns</td></tr><tr><td>transform vector2 x100</td><td>N/A</td><td>N/A</td><td>5.392 us</td><td>N/A</td><td>5.579 us</td><td>33.45 us</td><td>N/A</td><td><strong>3.909 us</strong></td></tr><tr><td>transform vector3 x1</td><td>N/A</td><td>N/A</td><td>55.3600 ns</td><td>N/A</td><td><strong>24.3628 ns</strong></td><td>515.1730 ns</td><td>59.1129 ns</td><td>47.9383 ns</td></tr><tr><td>transform vector3 x100</td><td>N/A</td><td>N/A</td><td>9.185 us</td><td>N/A</td><td><strong>7.958 us</strong></td><td>52.39 us</td><td>8.992 us</td><td>8.665 us</td></tr><tr><td>transform2 inverse</td><td>N/A</td><td>N/A</td><td>87.2060 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>45.0272 ns</strong></td></tr><tr><td>transform2 mul transform2</td><td>N/A</td><td>N/A</td><td>87.5702 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>40.1995 ns</strong></td></tr><tr><td>transform3 inverse</td><td>N/A</td><td>N/A</td><td><strong>542.8401 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>748.2648 ns</td></tr><tr><td>transform3 mul transform3d</td><td>N/A</td><td>N/A</td><td><strong>118.0659 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>115.3294 ns</strong></td></tr><tr><td>vector3 cross</td><td>6.4232 ns</td><td><strong>6.2395 ns</strong></td><td>25.0006 ns</td><td>36.5961 ns</td><td>15.0303 ns</td><td>28.6082 ns</td><td>28.6343 ns</td><td>29.5467 ns</td></tr><tr><td>vector3 dot</td><td>6.6820 ns</td><td><strong>6.3391 ns</strong></td><td>25.5593 ns</td><td>26.1824 ns</td><td>13.6831 ns</td><td>25.4740 ns</td><td>25.9099 ns</td><td>26.1271 ns</td></tr><tr><td>vector3 length</td><td>5.3741 ns</td><td><strong>5.2332 ns</strong></td><td>20.5369 ns</td><td>34.2988 ns</td><td>20.5652 ns</td><td>20.6259 ns</td><td>20.9281 ns</td><td>20.6052 ns</td></tr><tr><td>vector3 normalize</td><td><strong>15.5892 ns</strong></td><td><strong>15.6585 ns</strong></td><td>59.1804 ns</td><td>60.9510 ns</td><td>35.7763 ns</td><td>61.3666 ns</td><td>36.7304 ns</td><td>61.3199 ns</td></tr></tbody></table>
<p>Please see the <a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#benchmarks-of-rust-linear-algebra-crates">last section</a> of this post for a more comprehensive benchmark (including the use of <code>f32x8</code> and <code>f32x16</code>
with nalgebra) and details about the benchmark conditions.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="what-is-aosoa-with-explicit-simd">What is AoSoA with explicit SIMD?<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#what-is-aosoa-with-explicit-simd" class="hash-link" aria-label="Direct link to What is AoSoA with explicit SIMD?" title="Direct link to What is AoSoA with explicit SIMD?">​</a></h2>
<p>The data layout I call here <strong>AoSoA with explicit SIMD</strong> (or <strong>SIMD AoSoA</strong> for short) is a straightforward variant of the <strong>AoSoA</strong> (Array-of-Structures-of-Arrays) layout which is itself a
combination of two more common layouts: <strong>SoA</strong> (Structure-of-Arrays) and <strong>AoS</strong> (Array-of-Structures). So let's see what is the difference
of all those layouts with the simple example using 3D vectors (vectors with three components <code>x, y, z</code>): given two arrays of
1024 3D vectors, we want to compute the sum of each pairs of vectors with the same index.</p>
<p><em>Note:</em> The explanations here are merely a superficial introduction of the AoS vs SoA vs AoSoA concepts. I just want to explain
some of the differences and some of their advantages/disadvantages. I won't give any detailed analysis of the generated
assembly code after compiling the examples provided. The benchmarks at the end of this post will show the performance difference
between AoS and SIMD AoSoA. You may be interested by <a href="https://software.intel.com/en-us/articles/memory-layout-transformations" target="_blank" rel="noopener noreferrer">that article too</a>.</p>
<p><em>Note 2:</em> For iterating through the arrays, I'll be using explicit indices <code>for i in 0..1024</code> instead of iterators. This
is on purpose to make the number of iterations explicit and to make the code easier to understand for readers that are not
used to Rust iterators.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="array-of-structures-aos">Array-of-Structures (AoS)<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#array-of-structures-aos" class="hash-link" aria-label="Direct link to Array-of-Structures (AoS)" title="Direct link to Array-of-Structures (AoS)">​</a></h3>
<p>The Array-of-Structures layout is the most common and intuitive layout. You define a structure as the aggregation of all its
fields. And multiple structures of the same type are simply stored one after the other inside of an array. Here is what our
3D vector would look like:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">Vector3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">f32</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/// An array containing 1024 vectors.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">SetOfVector3</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token class-name" style="color:rgb(255, 203, 107)">Vector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">add_arrays_of_vectors</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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>Here, we need to iterate through each pair of vectors, one from each set, and execute our sum. This is arguably the most
intuitive way of doing this, but not necessarily the most efficient. All Rust linear algebra crates from this benchmark can work with this layout.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="pros-of-aos">Pros of AoS<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#pros-of-aos" class="hash-link" aria-label="Direct link to Pros of AoS" title="Direct link to Pros of AoS">​</a></h4>
<ul>
<li>It is easy to read/write/modify each vector individually.</li>
<li>AoS are generally easier to reason with when designing algorithms.</li>
</ul>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="cons-of-aos">Cons of AoS<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#cons-of-aos" class="hash-link" aria-label="Direct link to Cons of AoS" title="Direct link to Cons of AoS">​</a></h4>
<ul>
<li>Not as efficient as other layouts when working on a large number of elements of the same type.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="structure-of-arrays-soa">Structure-of-Arrays (SoA)<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#structure-of-arrays-soa" class="hash-link" aria-label="Direct link to Structure-of-Arrays (SoA)" title="Direct link to Structure-of-Arrays (SoA)">​</a></h3>
<p>The Structure-of-Arrays layout is less intuitive to work with because it will store each field of a struct into its own
array. Thus, our set of vector set would look like that:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">SetOfVector3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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>These is no explicit <code>Vector3</code> structure here because they are all packed into the array. Accessing the components of the <code>i</code>-th
vector of the set means we access <code>set.x[i]</code>, <code>set.y[i]</code> and <code>set.z[i]</code>. With this structure, our vector sum becomes the following:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">add_arrays_of_vectors</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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>There is more code here than in our AoS example because we need to iterate on each components individually. However this
will be much more efficient than our AoS approach because this is extremely vectorization-friendly: the compiler will be
able to group consecutive vector entries for each component, and use SIMD instructions to perform the 2, 4, 8, or even 16
additions at a time instead of a single one.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="pros-of-soa">Pros of SoA<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#pros-of-soa" class="hash-link" aria-label="Direct link to Pros of SoA" title="Direct link to Pros of SoA">​</a></h4>
<ul>
<li>Extremely fast.</li>
</ul>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="cons-of-soa">Cons of SoA<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#cons-of-soa" class="hash-link" aria-label="Direct link to Cons of SoA" title="Direct link to Cons of SoA">​</a></h4>
<ul>
<li>Algorithms need to be explicitly designed with SoA in mind to be efficient.</li>
<li>Manipulating vectors individually is more difficult and can be less efficient than AoS.</li>
<li>It is more difficult to think in terms of SoA than in terms of AoS.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="array-of-structures-of-arrays-aosoa">Array-of-Structures-of-Arrays (AoSoA)<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#array-of-structures-of-arrays-aosoa" class="hash-link" aria-label="Direct link to Array-of-Structures-of-Arrays (AoSoA)" title="Direct link to Array-of-Structures-of-Arrays (AoSoA)">​</a></h3>
<p>Now let's combine both SoA and AoS to obtain: Array-of-Structures-of-Arrays (AoSoA). The idea is to first define a <em>wide</em>
3D vector, i.e., we pack several vectors into a single struct:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">WideVector3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">f32</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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 term <em>wide</em> 3D vector is inspired from the terminology used in the <a href="https://crates.io/crates/ultraviolet" target="_blank" rel="noopener noreferrer">ultraviolet</a> crate's documentation.
Here, our <code>WideVector3</code> actually represents 4 vectors laid out in a SoA fashion. If we want our set of vector to contain more than just
4 vectors, we can define an array of <code>WideVector3</code> (so we end up with an array of structure of array) with only <code>1024 / 4</code> elements
because each element already represent 4 vectors:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token class-name" style="color:rgb(255, 203, 107)">WideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</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>Our vector sum then becomes quite similar to the AoS approach, except that we have to add each 4 components in the inner
loop in an SoA fashion:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">add_arrays_of_vectors</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// NOTE: each of those groups of four sums can be executed as</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// a single SIMD instruction.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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>So with this data layout, we still achieve great performance because components are grouped by 4, and thus their sum can
easily be auto-vectorized to a single SIMD instruction. To manipulate an individual vector we first have to access the corresponding <em>wide</em>
vector, and then its components on the <code>x,y,z</code> arrays.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="pros-of-aosoa">Pros of AoSoA<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#pros-of-aosoa" class="hash-link" aria-label="Direct link to Pros of AoSoA" title="Direct link to Pros of AoSoA">​</a></h4>
<ul>
<li>Great performance compared to AoS.</li>
<li>Can even beat the performance of SoA considering AoSoA can be more cache-friendly in modern architecture.</li>
<li>Designing algorithms around AoSoA is somewhat easier than with plain SoA.</li>
<li>Using AoSoA, most linear-algebra operations can be easily vectorized as long as they don't rely too much on branching.</li>
</ul>
<h4 class="anchor anchorWithHideOnScrollNavbar_jgva" id="cons-of-aosoa">Cons of AoSoA<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#cons-of-aosoa" class="hash-link" aria-label="Direct link to Cons of AoSoA" title="Direct link to Cons of AoSoA">​</a></h4>
<ul>
<li>We still need to design our algorithms carefully to use AoSoA efficiently.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="array-of-structures-of-arrays-with-explicit-simd-simd-aosoa">Array-of-Structures-of-arrays with explicit SIMD (SIMD AoSoA)<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#array-of-structures-of-arrays-with-explicit-simd-simd-aosoa" class="hash-link" aria-label="Direct link to Array-of-Structures-of-arrays with explicit SIMD (SIMD AoSoA)" title="Direct link to Array-of-Structures-of-arrays with explicit SIMD (SIMD AoSoA)">​</a></h3>
<p>Finally, let's talk about what I call here <em>SIMD AoSoA</em>. This layout is actually exactly the same as AoSoA presented before,
except we that we use explicit SIMD primitives like, e.g., the types from
the <a href="https://crates.io/crates/packed_simd" target="_blank" rel="noopener noreferrer">packed_simd</a> crate instead of plain arrays. For example we can use 4-lanes SIMD
floats <code>packed_simd::f32x4</code> instead of <code>[f32; 4]</code>:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">WideVector3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">packed_simd</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">f32x4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">packed_simd</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">f32x4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">packed_simd</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">f32x4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token class-name" style="color:rgb(255, 203, 107)">WideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</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>Then our sum will be exactly the same as in the AoSoA approach, except that we don't have to deal with each 4 lanes
explicitly because <code>packed_simd::f32x4</code> implements the <code>Add</code> trait:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(130, 170, 255)">add_arrays_of_vectors</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token keyword" style="font-style:italic">mut</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// NOTE: each 4-lanes sum will be executed as a single SIMD operation.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        va</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> vb</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</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 we wanted to use 16-lanes vectors here (based on AVX instructions), we could simply do:</p>
<div class="language-rust codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-rust codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">WideVector3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    x</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">packed_simd</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">f32x16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    y</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">packed_simd</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">f32x16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    z</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token namespace" style="color:rgb(178, 204, 214)">packed_simd</span><span class="token namespace punctuation" style="color:rgb(199, 146, 234)">::</span><span class="token plain">f32x16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:rgb(255, 203, 107)">SetOfWideVector3</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token class-name" style="color:rgb(255, 203, 107)">WideVector3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1024</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</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>Another benefit of using SIMD types explicitly here is that we no longer rely on the compiler's auto-vectorization.
So we can get SIMD instructions even in debug mode, and in some situations where the compiler would fail to auto-vectorize
properly.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="using-simd-aosoa-for-linear-algebra-in-rust-ultraviolet-and-nalgebra">Using SIMD AoSoA for linear-algebra in Rust: ultraviolet and nalgebra<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#using-simd-aosoa-for-linear-algebra-in-rust-ultraviolet-and-nalgebra" class="hash-link" aria-label="Direct link to Using SIMD AoSoA for linear-algebra in Rust: ultraviolet and nalgebra" title="Direct link to Using SIMD AoSoA for linear-algebra in Rust: ultraviolet and nalgebra">​</a></h3>
<p>As far as I know, the first crate that implemented this concept for (gamedev) linear algebra in Rust is <a href="https://crates.io/crates/ultraviolet" target="_blank" rel="noopener noreferrer">ultraviolet</a>.
At the end of this month (March 2020), you will also be able to use this approach with <a href="https://nalgebra.org/" target="_blank" rel="noopener noreferrer">nalgebra</a>, in its upcoming version 0.21.0.</p>
<p>With <code>ultraviolet</code>, you have the choice between two families of types: regular types (<code>Vec2</code>, <code>Mat3</code>, <code>Isometry3</code>, etc.) and <em>wide</em> types (<code>Wec2</code>, <code>Wat3</code>, <code>WIsometry3</code>).
The regular types are designed to be usable with the common AoS layout, with vector/matrix components set to <code>f32</code>.
The <em>wide</em> types on the other hand are designed to be used with the SIMD AoSoA layout: each <em>wide</em> type packs the corresponding four non-wide types into a single structure
(e.g. one <code>Wec3</code> represents four <code>Vec3</code>), and the wide vector/wide matrix components are of type <code>f32x4</code>
from the <a href="https://crates.io/crates/wide" target="_blank" rel="noopener noreferrer">wide crate</a>. As of today, <code>ultraviolet</code> is limited to 32-bits floats, and 4-lanes 32-bits SIMD floats.
You can't use it with SIMD integers, nor with 64-bits floats or 32-bits SIMD floats with a number of lanes different from 4.</p>
<p>With <code>nalgebra</code>, all types of vectors/matrices/tansformations are generic wrt. their component type. Therefore, for a
AoS layout, you can use, e.g., the <code>Vector2&lt;f32&gt;</code> type. And if you want to leverage SIMD AoSoA, you can use <code>Vector2&lt;f32x4&gt;</code> instead and
that will give you four 2D vectors for the price of one. Note that the <code>f32x4</code> type here comes from the new <a href="https://crates.io/crates/simba" target="_blank" rel="noopener noreferrer">simba</a>
crate and is a newtype for the <code>f32x4</code> from <a href="https://crates.io/crates/packed_simd" target="_blank" rel="noopener noreferrer">packed_simd</a> (the upcoming standard safe SIMD implementation in Rust).
A newtype was required because of the orphan rules, and the need to implement some traits from the <strong>num</strong> crate for the SIMD types.
<strong>Simba</strong> is not limited to <code>f32x4</code> though as it defines a newtype for every single numeric type of <strong>packed_simd</strong>. Therefore <strong>nalgebra</strong>
will also support all the integer and float SIMD&nbsp;types, with 2, 4, 8, or 16 lanes. You can for example write and use <code>Isometry2&lt;simba::f32x16&gt;</code> as
a SoA set of 16 <code>Isometry2&lt;f32&gt;</code>.
Finally <strong>nalgebra</strong> has support for SIMD on all the platforms supported by <strong>packed_simd</strong> itself.</p>
<p>Here are some (subjective) pros and cons for <strong>ultraviolet</strong> and <strong>nalgebra</strong>:</p>
<ul>
<li><em>Pros of ultraviolet</em>: no generics so it is simple to use, and efficient even without compiler optimizations enabled. Works on stable Rust.</li>
<li><em>Pros of nalgebra</em>: generics allow the use of all SIMD types. More feature-complete and tested than <strong>ultraviolet</strong>. Based on <strong>packed_simd</strong> with great platform support
but we could make it work with the <strong>wide</strong> crate too.</li>
<li><em>Cons of ultraviolet</em>: cannot use 64-bits floats nor SIMD types other than 32-bit 4-lanes floats. It has a more limited feature set (but that may be enough for gamedev).</li>
<li><em>Cons of nalgebra</em>: generics make it harder to use, and make the doc harder to browse. Also <em>nalgebra</em> is much less efficient without compiler optimizations enabled. Because
SIMD AoSoA is based on <strong>packed_simd</strong>, the use of SIMD types will only work with the nightly compiler.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="benchmarks-of-rust-linear-algebra-crates">Benchmarks of Rust linear-algebra crates<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#benchmarks-of-rust-linear-algebra-crates" class="hash-link" aria-label="Direct link to Benchmarks of Rust linear-algebra crates" title="Direct link to Benchmarks of Rust linear-algebra crates">​</a></h2>
<p>Now is the time to see if SIMD AoSoA is useful at all. The benchmarks I run here are a modified version of the
<strong>mathbench-rs</strong> benchmark suite you may have already head of. For example it
was used when <code>glam</code> and <code>ultraviolet</code> were published.</p>
<p>If you want to run the benchmarks on your machine, you can <a href="https://github.com/sebcrozet/mathbench-rs" target="_blank" rel="noopener noreferrer">clone my fork</a> and
either run <code>cargo bench</code> or <code>RUSTFLAGS='-C target-cpu=native' cargo bench</code>.</p>
<p>The modifications I made to the benchmark were the following:</p>
<ul>
<li>I added <code>codegen-units = 1</code> to the <code>[profile.bench]</code> section. This allows to get as much optimization as we can get from
the compiler (this is typically what you want before releasing a binary). It turns out that this can affect the performance
of <strong>nalgebra</strong> which benefits significantly from compiler optimizations.</li>
<li>I added support for <strong>ultraviolet</strong> regular types (identified by the column <strong>ultraviolet</strong> in the benchmarks) as well
as its <em>wide</em> types (identified by the column <strong>ultraviolet_f32x4</strong>).</li>
<li>Because <strong>ultraviolet</strong> use the concepts of rotors instead of quaternions for its rotation, I used its <code>Rotor/WRotor</code> types for
all its <em>quaternion</em> benchmark rows.</li>
<li>I added support for using <strong>nalgebra</strong> with f32 SIMD with 4, 8, and 16 lanes identified by <strong>nalgebra_f32x4</strong>, <strong>nalgebra_f32x8</strong>
and <strong>nalgebra_f32x16</strong>.</li>
<li>I added benchmarks for 3D isometries of both <strong>ultraviolet</strong> and <strong>nalgebra</strong>.</li>
<li>I modified the benchmark of unary and binary operations so they measure the time to process 16 elements. For example
when benchmarking 2D matrix transposition, we are actually seeing the computation time for transposing 16 matrices (instead
of just one). This allows us to measure the gain of SIMD AoSoA without penalizing neither non-AoSoA crates nor AoSoA crates.</li>
</ul>
<p>This last modification follows the same principle as the one introduced for the benchmarks presented by <code>ultraviolet</code> in
their <a href="https://github.com/sebcrozet/mathbench-rs#benchmark-results" target="_blank" rel="noopener noreferrer">README</a>.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="benchmark-with--c-target-cpunative">Benchmark with <code>-C target-cpu=native</code><a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#benchmark-with--c-target-cpunative" class="hash-link" aria-label="Direct link to benchmark-with--c-target-cpunative" title="Direct link to benchmark-with--c-target-cpunative">​</a></h3>
<p>In this benchmark I am compiling with the <code>RUSTFLAGS='-C target-cpu=native</code> option so that the compiler emits AVX instructions
for <code>f32x8</code> and <code>f32x16</code>. It appears that some crates (namely <strong>glam</strong> and <strong>vek</strong>) are not as efficient as they could be
when this option is enabled so you will find a second benchmark without this option enabled in the next section.</p>
<p>Benchmark options:</p>
<ul>
<li>command line: <code>RUSTFLAGS='-C target-cpu=native' cargo bench</code></li>
<li>profiling option in <code>Cargo.toml</code>: <code>codegen-units = 1</code></li>
<li>CPU: <code>AMD Ryzen 9 3900X 12-Core Processor</code></li>
</ul>
<table><thead><tr><th>benchmark</th><th>nalgebra_f32x16</th><th>nalgebra_f32x8</th><th>nalgebra_f32x4</th><th>ultraviolet_f32x4</th><th>nalgebra</th><th>ultraviolet</th><th>glam</th><th>vek</th><th>cgmath</th><th>euclid</th></tr></thead><tbody><tr><td>euler 2d x10000</td><td><strong>2.076 us</strong></td><td>2.224 us</td><td>3.05 us</td><td>3.05 us</td><td>9.674 us</td><td>12.0 us</td><td>12.42 us</td><td>11.85 us</td><td>11.92 us</td><td>9.585 us</td></tr><tr><td>euler 3d x10000</td><td>3.014 us</td><td><strong>2.809 us</strong></td><td>4.791 us</td><td>4.639 us</td><td>18.18 us</td><td>17.58 us</td><td>6.27 us</td><td>18.12 us</td><td>18.05 us</td><td>17.91 us</td></tr><tr><td>isometry transform point2 x1</td><td><strong>5.7179 ns</strong></td><td><strong>5.6563 ns</strong></td><td>7.8197 ns</td><td>8.1874 ns</td><td>22.8197 ns</td><td>24.4878 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point2 x100</td><td><strong>2.582 us</strong></td><td><strong>2.587 us</strong></td><td>2.739 us</td><td>2.787 us</td><td>3.007 us</td><td>3.169 us</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point3 x1</td><td>10.5417 ns</td><td><strong>10.1237 ns</strong></td><td>15.4410 ns</td><td>19.5679 ns</td><td>60.0877 ns</td><td>64.7755 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point3 x100</td><td>4.704 us</td><td><strong>4.377 us</strong></td><td>4.64 us</td><td>4.941 us</td><td>6.567 us</td><td>6.68 us</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry2 inverse</td><td><strong>6.0317 ns</strong></td><td>6.4494 ns</td><td>6.9687 ns</td><td>7.4126 ns</td><td>24.2412 ns</td><td>24.8876 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry2 mul isometry2</td><td><strong>8.1413 ns</strong></td><td>9.2351 ns</td><td>10.1867 ns</td><td>10.2618 ns</td><td>34.5250 ns</td><td>33.1397 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry3 inverse</td><td>12.3065 ns</td><td><strong>11.2699 ns</strong></td><td>16.2452 ns</td><td>21.6418 ns</td><td>62.2947 ns</td><td>76.3882 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry3 mul isometry3</td><td>29.0822 ns</td><td><strong>16.5287 ns</strong></td><td>26.0439 ns</td><td>31.5684 ns</td><td>97.8058 ns</td><td>109.7477 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>matrix2 determinant</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>15.4800 ns</td><td>N/A</td><td><strong>9.9942 ns</strong></td><td>15.5422 ns</td><td>15.6876 ns</td><td>N/A</td></tr><tr><td>matrix2 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>25.0731 ns</td><td>N/A</td><td><strong>15.7486 ns</strong></td><td>N/A</td><td>25.8362 ns</td><td>N/A</td></tr><tr><td>matrix2 mul matrix2</td><td>10.6500 ns</td><td><strong>9.0379 ns</strong></td><td>10.3309 ns</td><td>10.4283 ns</td><td>24.7601 ns</td><td>24.9938 ns</td><td>16.1426 ns</td><td>291.7833 ns</td><td>25.0133 ns</td><td>N/A</td></tr><tr><td>matrix2 mul vector2 x1</td><td>5.7680 ns</td><td><strong>5.2159 ns</strong></td><td>6.7758 ns</td><td>6.9242 ns</td><td>22.9934 ns</td><td>24.4428 ns</td><td>15.5422 ns</td><td>85.4171 ns</td><td>23.7398 ns</td><td>N/A</td></tr><tr><td>matrix2 mul vector2 x100</td><td><strong>2.641 us</strong></td><td><strong>2.663 us</strong></td><td><strong>2.647 us</strong></td><td><strong>2.617 us</strong></td><td>3.14 us</td><td>3.182 us</td><td>2.953 us</td><td>8.998 us</td><td>3.232 us</td><td>N/A</td></tr><tr><td>matrix2 transpose</td><td><strong>5.8718 ns</strong></td><td>6.8760 ns</td><td>6.6906 ns</td><td>N/A</td><td>10.6439 ns</td><td>N/A</td><td>10.9130 ns</td><td>10.6631 ns</td><td>10.5080 ns</td><td>N/A</td></tr><tr><td>matrix3 determinant</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>31.9111 ns</td><td>N/A</td><td><strong>19.7343 ns</strong></td><td>31.3051 ns</td><td>32.2809 ns</td><td>N/A</td></tr><tr><td>matrix3 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>25.6965 ns</strong></td><td>83.4324 ns</td><td>82.1388 ns</td><td>120.2562 ns</td><td>N/A</td><td>79.4379 ns</td><td>N/A</td></tr><tr><td>matrix3 mul matrix3</td><td>70.6877 ns</td><td><strong>19.6932 ns</strong></td><td>27.7722 ns</td><td>26.8799 ns</td><td>83.2946 ns</td><td>83.9021 ns</td><td>44.3916 ns</td><td>944.3034 ns</td><td>80.8441 ns</td><td>N/A</td></tr><tr><td>matrix3 mul vector3 x1</td><td><strong>10.6031 ns</strong></td><td><strong>10.7913 ns</strong></td><td>13.6117 ns</td><td>13.7169 ns</td><td>46.1231 ns</td><td>47.5651 ns</td><td>20.6856 ns</td><td>315.4715 ns</td><td>45.3403 ns</td><td>N/A</td></tr><tr><td>matrix3 mul vector3 x100</td><td><strong>4.7 us</strong></td><td><strong>4.807 us</strong></td><td>4.845 us</td><td><strong>4.738 us</strong></td><td>6.163 us</td><td>6.142 us</td><td>6.701 us</td><td>32.47 us</td><td>6.091 us</td><td>N/A</td></tr><tr><td>matrix3 transpose</td><td>14.3912 ns</td><td><strong>12.8725 ns</strong></td><td>15.0385 ns</td><td>15.9171 ns</td><td>19.9624 ns</td><td>19.7458 ns</td><td>22.7494 ns</td><td>19.5610 ns</td><td>20.0838 ns</td><td>N/A</td></tr><tr><td>matrix4 determinant</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>1.489 us</td><td>N/A</td><td><strong>0.083 us</strong></td><td>0.1515 us</td><td>0.1021 us</td><td>0.1565 us</td></tr><tr><td>matrix4 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>0.09051 us</strong></td><td>0.5339 us</td><td>0.3744 us</td><td>0.2844 us</td><td>4.203 us</td><td>0.4745 us</td><td>0.5851 us</td></tr><tr><td>matrix4 mul matrix4</td><td>0.2354 us</td><td><strong>0.06835 us</strong></td><td>0.07657 us</td><td>0.07581 us</td><td>0.1247 us</td><td>0.135 us</td><td>0.07736 us</td><td>1.916 us</td><td>0.1146 us</td><td>0.1089 us</td></tr><tr><td>matrix4 mul vector4 x1</td><td>39.0102 ns</td><td><strong>15.4389 ns</strong></td><td>20.7324 ns</td><td>22.1028 ns</td><td>30.6785 ns</td><td>30.8711 ns</td><td>25.6006 ns</td><td>487.1873 ns</td><td>30.3248 ns</td><td>N/A</td></tr><tr><td>matrix4 mul vector4 x100</td><td>8.339 us</td><td><strong>7.419 us</strong></td><td><strong>7.437 us</strong></td><td><strong>7.428 us</strong></td><td>8.14 us</td><td>8.209 us</td><td>8.078 us</td><td>47.98 us</td><td>8.332 us</td><td>N/A</td></tr><tr><td>matrix4 transpose</td><td>95.1337 ns</td><td><strong>23.2408 ns</strong></td><td>25.8665 ns</td><td>25.7914 ns</td><td>97.9916 ns</td><td>101.3651 ns</td><td>30.0239 ns</td><td>103.5180 ns</td><td>102.0192 ns</td><td>N/A</td></tr><tr><td>quaternion conjugate</td><td><strong>6.0223 ns</strong></td><td>6.3760 ns</td><td>7.5628 ns</td><td>6.9775 ns</td><td>23.2724 ns</td><td>23.0902 ns</td><td>10.3465 ns</td><td>23.2522 ns</td><td>23.2696 ns</td><td>23.0664 ns</td></tr><tr><td>quaternion mul quaternion</td><td><strong>9.3504 ns</strong></td><td><strong>9.4567 ns</strong></td><td>12.3669 ns</td><td>12.6805 ns</td><td>30.0095 ns</td><td>38.4430 ns</td><td>25.8066 ns</td><td>42.2113 ns</td><td>42.6575 ns</td><td>40.9668 ns</td></tr><tr><td>quaternion mul vector3</td><td>8.5309 ns</td><td><strong>7.7526 ns</strong></td><td>13.3755 ns</td><td>16.7836 ns</td><td>49.3278 ns</td><td>56.7010 ns</td><td>41.2790 ns</td><td>71.9719 ns</td><td>48.9911 ns</td><td>48.2763 ns</td></tr><tr><td>transform point2 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>35.6464 ns</td><td>N/A</td><td><strong>23.5642 ns</strong></td><td>325.1071 ns</td><td>29.7918 ns</td><td>28.4816 ns</td></tr><tr><td>transform point2 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>5.386 us</td><td>N/A</td><td>5.612 us</td><td>33.66 us</td><td>5.255 us</td><td><strong>4.066 us</strong></td></tr><tr><td>transform point3 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>68.6997 ns</td><td>N/A</td><td><strong>23.9545 ns</strong></td><td>504.0400 ns</td><td>67.0988 ns</td><td>68.1284 ns</td></tr><tr><td>transform point3 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>9.393 us</td><td>N/A</td><td><strong>7.898 us</strong></td><td>49.31 us</td><td>9.282 us</td><td>10.0 us</td></tr><tr><td>transform vector2 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>32.5603 ns</td><td>N/A</td><td><strong>24.0791 ns</strong></td><td>327.3927 ns</td><td>N/A</td><td>24.8445 ns</td></tr><tr><td>transform vector2 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>5.385 us</td><td>N/A</td><td>5.649 us</td><td>33.51 us</td><td>N/A</td><td><strong>3.891 us</strong></td></tr><tr><td>transform vector3 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>52.9997 ns</td><td>N/A</td><td><strong>25.2423 ns</strong></td><td>487.6624 ns</td><td>55.1891 ns</td><td>46.3865 ns</td></tr><tr><td>transform vector3 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>9.083 us</td><td>N/A</td><td><strong>7.963 us</strong></td><td>49.47 us</td><td>8.994 us</td><td>8.771 us</td></tr><tr><td>transform2 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>83.1814 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>38.3216 ns</strong></td></tr><tr><td>transform2 mul transform2</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>79.8949 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>53.0397 ns</strong></td></tr><tr><td>transform3 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>509.3638 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>573.8688 ns</td></tr><tr><td>transform3 mul transform3d</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>116.3846 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>112.3300 ns</strong></td></tr><tr><td>vector3 cross</td><td><strong>4.4663 ns</strong></td><td>4.5852 ns</td><td>6.3479 ns</td><td>6.1689 ns</td><td>26.0655 ns</td><td>24.9554 ns</td><td>15.6013 ns</td><td>27.9000 ns</td><td>27.6733 ns</td><td>28.1612 ns</td></tr><tr><td>vector3 dot</td><td><strong>4.4944 ns</strong></td><td><strong>4.5232 ns</strong></td><td>6.4285 ns</td><td>6.2531 ns</td><td>25.3941 ns</td><td>24.9869 ns</td><td>13.6267 ns</td><td>24.5923 ns</td><td>25.9651 ns</td><td>25.8382 ns</td></tr><tr><td>vector3 length</td><td><strong>3.5110 ns</strong></td><td><strong>3.5936 ns</strong></td><td>5.4675 ns</td><td>5.4127 ns</td><td>20.7343 ns</td><td>21.0470 ns</td><td>20.4590 ns</td><td>21.0161 ns</td><td>20.7430 ns</td><td>20.5710 ns</td></tr><tr><td>vector3 normalize</td><td><strong>7.8013 ns</strong></td><td>8.3383 ns</td><td>15.4976 ns</td><td>15.3918 ns</td><td>61.5877 ns</td><td>61.3314 ns</td><td>35.6648 ns</td><td>59.7074 ns</td><td>35.7934 ns</td><td>61.2340 ns</td></tr></tbody></table>
<p>To get a better comparative view of the performance of AoSoA, here are the benchmarks restricted to ultraviolet's <em>wide</em> types
(<code>Wec2, Wat2, WIsometry2</code>, etc.) and nalgebra types paramaterized by SIMD types (<code>Vector2&lt;f32x4&gt;, Matrix2&lt;f32x8&gt;, Isometry2&lt;f32x16&gt;</code>, etc.):</p>
<table><thead><tr><th>benchmark</th><th>ultraviolet_f32x4</th><th>nalgebra_f32x4</th><th>nalgebra_f32x8</th><th>nalgebra_f32x16</th></tr></thead><tbody><tr><td>euler 2d x10000</td><td>3.05 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>4.639 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 x1</td><td>8.1874 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 point2 x100</td><td>2.787 us</td><td>2.739 us</td><td><strong>2.587 us</strong></td><td><strong>2.582 us</strong></td></tr><tr><td>isometry transform point3 x1</td><td>19.5679 ns</td><td>15.4410 ns</td><td><strong>10.1237 ns</strong></td><td>10.5417 ns</td></tr><tr><td>isometry transform point3 x100</td><td>4.941 us</td><td>4.64 us</td><td><strong>4.377 us</strong></td><td>4.704 us</td></tr><tr><td>isometry2 inverse</td><td>7.4126 ns</td><td>6.9687 ns</td><td>6.4494 ns</td><td><strong>6.0317 ns</strong></td></tr><tr><td>isometry2 mul isometry2</td><td>10.2618 ns</td><td>10.1867 ns</td><td>9.2351 ns</td><td><strong>8.1413 ns</strong></td></tr><tr><td>isometry3 inverse</td><td>21.6418 ns</td><td>16.2452 ns</td><td><strong>11.2699 ns</strong></td><td>12.3065 ns</td></tr><tr><td>isometry3 mul isometry3</td><td>31.5684 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>10.4283 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 x1</td><td>6.9242 ns</td><td>6.7758 ns</td><td><strong>5.2159 ns</strong></td><td>5.7680 ns</td></tr><tr><td>matrix2 mul vector2 x100</td><td><strong>2.617 us</strong></td><td><strong>2.647 us</strong></td><td><strong>2.663 us</strong></td><td><strong>2.641 us</strong></td></tr><tr><td>matrix2 transpose</td><td>N/A</td><td>6.6906 ns</td><td>6.8760 ns</td><td><strong>5.8718 ns</strong></td></tr><tr><td>matrix3 inverse</td><td><strong>25.6965 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>matrix3 mul matrix3</td><td>26.8799 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 x1</td><td>13.7169 ns</td><td>13.6117 ns</td><td><strong>10.7913 ns</strong></td><td><strong>10.6031 ns</strong></td></tr><tr><td>matrix3 mul vector3 x100</td><td><strong>4.738 us</strong></td><td>4.845 us</td><td><strong>4.807 us</strong></td><td><strong>4.7 us</strong></td></tr><tr><td>matrix3 transpose</td><td>15.9171 ns</td><td>15.0385 ns</td><td><strong>12.8725 ns</strong></td><td>14.3912 ns</td></tr><tr><td>matrix4 inverse</td><td><strong>90.5105 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>matrix4 mul matrix4</td><td>75.8094 ns</td><td>76.5675 ns</td><td><strong>68.3461 ns</strong></td><td>235.3853 ns</td></tr><tr><td>matrix4 mul vector4 x1</td><td>22.1028 ns</td><td>20.7324 ns</td><td><strong>15.4389 ns</strong></td><td>39.0102 ns</td></tr><tr><td>matrix4 mul vector4 x100</td><td><strong>7.428 us</strong></td><td><strong>7.437 us</strong></td><td><strong>7.419 us</strong></td><td>8.339 us</td></tr><tr><td>matrix4 transpose</td><td>25.7914 ns</td><td>25.8665 ns</td><td><strong>23.2408 ns</strong></td><td>95.1337 ns</td></tr><tr><td>quaternion conjugate</td><td>6.9775 ns</td><td>7.5628 ns</td><td>6.3760 ns</td><td><strong>6.0223 ns</strong></td></tr><tr><td>quaternion mul quaternion</td><td>12.6805 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>16.7836 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>6.1689 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>6.2531 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>5.4127 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>15.3918 ns</td><td>15.4976 ns</td><td>8.3383 ns</td><td><strong>7.8013 ns</strong></td></tr></tbody></table>
<p>As we can see, both <code>ultraviolet_f32x4</code> and <code>nalgebra_f32x4</code> yield roughly the same computation times. The most efficient
option for my processor is <strong>nalgebra</strong> with <code>f32x8</code>: it often reaches the best performance, and <code>f32x16</code> comes
with little performance gain, and even significant regressions for some tests.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_jgva" id="benchmark-without--c-target-cpunative">Benchmark without <code>-C target-cpu=native</code><a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#benchmark-without--c-target-cpunative" class="hash-link" aria-label="Direct link to benchmark-without--c-target-cpunative" title="Direct link to benchmark-without--c-target-cpunative">​</a></h3>
<p>It appears some rust linear algebra crates do not perform as well as they could if <code>-C target-cpu=native</code> is passed
to the compiler. This is for example the case of <code>glam</code> and <code>vek</code>. However, it appears that not using <code>-C target-cpu=native</code>
makes some methods of non-wide types of <strong>ultraviolet</strong> much less efficient.</p>
<p>Because we don't use <code>-C target-cpu=native</code> here, both <code>f32x8</code> and <code>f32x16</code> won't emit 8- and 16-lanes AVX instructions, making
them only as efficient as <code>f32x4</code>.</p>
<p>Here is the same benchmark with:</p>
<ul>
<li>command line: <code>cargo bench</code></li>
<li>options in <code>Cargo.toml</code>: <code>codegen-units = 1</code>.</li>
<li>CPU: <code>AMD Ryzen 9 3900X 12-Core Processor</code></li>
</ul>
<table><thead><tr><th>benchmark</th><th>nalgebra_f32x16</th><th>nalgebra_f32x8</th><th>nalgebra_f32x4</th><th>ultraviolet_f32x4</th><th>nalgebra</th><th>ultraviolet</th><th>glam</th><th>vek</th><th>cgmath</th><th>euclid</th></tr></thead><tbody><tr><td>euler 2d x10000</td><td><strong>3.057 us</strong></td><td>3.069 us</td><td><strong>2.992 us</strong></td><td><strong>3.014 us</strong></td><td>9.028 us</td><td>5.28 us</td><td>5.166 us</td><td>5.258 us</td><td>5.259 us</td><td>8.631 us</td></tr><tr><td>euler 3d x10000</td><td><strong>4.585 us</strong></td><td><strong>4.587 us</strong></td><td><strong>4.546 us</strong></td><td><strong>4.587 us</strong></td><td>17.84 us</td><td>18.34 us</td><td>6.311 us</td><td>17.57 us</td><td>18.04 us</td><td>17.97 us</td></tr><tr><td>isometry transform point2 x1</td><td>7.7226 ns</td><td><strong>6.7828 ns</strong></td><td>8.1024 ns</td><td>8.6412 ns</td><td>23.4637 ns</td><td>54.5840 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point2 x100</td><td><strong>2.625 us</strong></td><td>2.701 us</td><td>2.801 us</td><td>2.837 us</td><td>3.109 us</td><td>4.918 us</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point3 x1</td><td>21.0932 ns</td><td><strong>16.1782 ns</strong></td><td><strong>16.1052 ns</strong></td><td>20.6723 ns</td><td>61.8824 ns</td><td>330.1143 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry transform point3 x100</td><td>6.466 us</td><td><strong>4.598 us</strong></td><td><strong>4.515 us</strong></td><td>4.794 us</td><td>6.546 us</td><td>18.19 us</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry2 inverse</td><td>7.4879 ns</td><td><strong>7.0432 ns</strong></td><td>7.3004 ns</td><td>7.7692 ns</td><td>24.8090 ns</td><td>59.3838 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry2 mul isometry2</td><td>13.3355 ns</td><td><strong>10.5486 ns</strong></td><td>12.3278 ns</td><td>12.7816 ns</td><td>34.5714 ns</td><td>110.7837 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry3 inverse</td><td>29.6336 ns</td><td>19.3869 ns</td><td><strong>17.1929 ns</strong></td><td>21.4199 ns</td><td>63.9200 ns</td><td>212.2193 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>isometry3 mul isometry3</td><td>51.0123 ns</td><td>39.2781 ns</td><td><strong>28.5785 ns</strong></td><td>37.5971 ns</td><td>98.0279 ns</td><td>459.4930 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td></tr><tr><td>matrix2 determinant</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>16.0198 ns</td><td>N/A</td><td><strong>11.2070 ns</strong></td><td>15.8621 ns</td><td>16.0906 ns</td><td>N/A</td></tr><tr><td>matrix2 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>26.5165 ns</td><td>N/A</td><td><strong>18.9069 ns</strong></td><td>N/A</td><td>26.2478 ns</td><td>N/A</td></tr><tr><td>matrix2 mul matrix2</td><td>60.2594 ns</td><td><strong>10.6371 ns</strong></td><td>12.5352 ns</td><td><strong>10.7532 ns</strong></td><td>25.4533 ns</td><td>25.7148 ns</td><td>16.3060 ns</td><td>301.3775 ns</td><td>25.6988 ns</td><td>N/A</td></tr><tr><td>matrix2 mul vector2 x1</td><td>29.6210 ns</td><td>8.0023 ns</td><td><strong>7.1695 ns</strong></td><td>8.0907 ns</td><td>23.0932 ns</td><td>24.4506 ns</td><td>16.4141 ns</td><td>93.3601 ns</td><td>25.0774 ns</td><td>N/A</td></tr><tr><td>matrix2 mul vector2 x100</td><td>3.5 us</td><td><strong>2.591 us</strong></td><td>2.684 us</td><td>2.698 us</td><td>3.137 us</td><td>3.174 us</td><td>2.828 us</td><td>9.558 us</td><td>3.122 us</td><td>N/A</td></tr><tr><td>matrix2 transpose</td><td>6.8152 ns</td><td>7.4080 ns</td><td><strong>6.4984 ns</strong></td><td>N/A</td><td>11.0205 ns</td><td>N/A</td><td>10.9890 ns</td><td>10.8180 ns</td><td>10.3812 ns</td><td>N/A</td></tr><tr><td>matrix3 determinant</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>33.1252 ns</td><td>N/A</td><td><strong>22.2592 ns</strong></td><td>31.8128 ns</td><td>31.7086 ns</td><td>N/A</td></tr><tr><td>matrix3 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>26.7493 ns</strong></td><td>92.8270 ns</td><td>284.1032 ns</td><td>93.5328 ns</td><td>N/A</td><td>82.3820 ns</td><td>N/A</td></tr><tr><td>matrix3 mul matrix3</td><td>0.1494 us</td><td>0.03354 us</td><td>0.02883 us</td><td><strong>0.02638 us</strong></td><td>0.09077 us</td><td>0.08728 us</td><td>0.0474 us</td><td>1.005 us</td><td>0.08579 us</td><td>N/A</td></tr><tr><td>matrix3 mul vector3 x1</td><td>52.3315 ns</td><td>14.0998 ns</td><td><strong>13.7548 ns</strong></td><td><strong>13.6309 ns</strong></td><td>46.4205 ns</td><td>46.5016 ns</td><td>21.5466 ns</td><td>317.8168 ns</td><td>47.3542 ns</td><td>N/A</td></tr><tr><td>matrix3 mul vector3 x100</td><td>10.68 us</td><td>5.033 us</td><td><strong>4.835 us</strong></td><td><strong>4.917 us</strong></td><td>6.138 us</td><td>6.261 us</td><td>6.633 us</td><td>32.93 us</td><td>6.297 us</td><td>N/A</td></tr><tr><td>matrix3 transpose</td><td>20.9653 ns</td><td><strong>15.7305 ns</strong></td><td><strong>15.7501 ns</strong></td><td><strong>15.4925 ns</strong></td><td>52.7300 ns</td><td>53.0845 ns</td><td>24.1975 ns</td><td>55.4793 ns</td><td>52.0874 ns</td><td>N/A</td></tr><tr><td>matrix4 determinant</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>690.7027 ns</td><td>N/A</td><td><strong>85.5778 ns</strong></td><td>176.1770 ns</td><td>110.6990 ns</td><td>174.6754 ns</td></tr><tr><td>matrix4 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>0.08342 us</strong></td><td>0.5282 us</td><td>0.3953 us</td><td>0.257 us</td><td>3.792 us</td><td>0.5096 us</td><td>0.651 us</td></tr><tr><td>matrix4 mul matrix4</td><td>0.4467 us</td><td>0.08671 us</td><td><strong>0.06897 us</strong></td><td><strong>0.07068 us</strong></td><td>0.1285 us</td><td>0.1493 us</td><td>0.07653 us</td><td>2.024 us</td><td>0.1185 us</td><td>0.1152 us</td></tr><tr><td>matrix4 mul vector4 x1</td><td>84.1744 ns</td><td><strong>20.9291 ns</strong></td><td><strong>21.1243 ns</strong></td><td><strong>20.6690 ns</strong></td><td>31.5352 ns</td><td>30.3570 ns</td><td>24.7876 ns</td><td>512.0570 ns</td><td>30.9776 ns</td><td>N/A</td></tr><tr><td>matrix4 mul vector4 x100</td><td>10.32 us</td><td><strong>7.592 us</strong></td><td><strong>7.595 us</strong></td><td><strong>7.662 us</strong></td><td>8.472 us</td><td>8.379 us</td><td>7.823 us</td><td>51.42 us</td><td>8.366 us</td><td>N/A</td></tr><tr><td>matrix4 transpose</td><td>103.5080 ns</td><td>32.5330 ns</td><td><strong>26.2948 ns</strong></td><td>27.1962 ns</td><td>103.0829 ns</td><td>101.3104 ns</td><td>29.2236 ns</td><td>105.6003 ns</td><td>98.1151 ns</td><td>N/A</td></tr><tr><td>quaternion conjugate</td><td><strong>6.7367 ns</strong></td><td>7.6066 ns</td><td><strong>6.6130 ns</strong></td><td><strong>6.6179 ns</strong></td><td>24.5468 ns</td><td>25.5657 ns</td><td>11.1447 ns</td><td>24.2229 ns</td><td>25.7246 ns</td><td>24.9413 ns</td></tr><tr><td>quaternion mul quaternion</td><td>20.0365 ns</td><td>16.6831 ns</td><td><strong>14.6380 ns</strong></td><td>16.6299 ns</td><td>39.3908 ns</td><td>274.4676 ns</td><td>27.3533 ns</td><td>62.0697 ns</td><td>35.0299 ns</td><td>59.5286 ns</td></tr><tr><td>quaternion mul vector3</td><td>19.3629 ns</td><td><strong>14.7722 ns</strong></td><td><strong>14.7579 ns</strong></td><td>18.5064 ns</td><td>52.7303 ns</td><td>170.8328 ns</td><td>44.1336 ns</td><td>81.1243 ns</td><td>52.5011 ns</td><td>54.1958 ns</td></tr><tr><td>transform point2 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>36.6350 ns</td><td>N/A</td><td><strong>25.6516 ns</strong></td><td>337.3442 ns</td><td>30.5781 ns</td><td>28.5532 ns</td></tr><tr><td>transform point2 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>5.475 us</td><td>N/A</td><td>5.732 us</td><td>33.81 us</td><td>5.118 us</td><td><strong>4.003 us</strong></td></tr><tr><td>transform point3 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>66.3694 ns</td><td>N/A</td><td><strong>24.0601 ns</strong></td><td>517.9224 ns</td><td>67.8205 ns</td><td>68.0836 ns</td></tr><tr><td>transform point3 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>9.403 us</td><td>N/A</td><td><strong>7.824 us</strong></td><td>52.5 us</td><td>9.559 us</td><td>10.07 us</td></tr><tr><td>transform vector2 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>32.5667 ns</td><td>N/A</td><td><strong>21.3971 ns</strong></td><td>330.5713 ns</td><td>N/A</td><td>23.5693 ns</td></tr><tr><td>transform vector2 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>5.392 us</td><td>N/A</td><td>5.579 us</td><td>33.45 us</td><td>N/A</td><td><strong>3.909 us</strong></td></tr><tr><td>transform vector3 x1</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>55.3600 ns</td><td>N/A</td><td><strong>24.3628 ns</strong></td><td>515.1730 ns</td><td>59.1129 ns</td><td>47.9383 ns</td></tr><tr><td>transform vector3 x100</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>9.185 us</td><td>N/A</td><td><strong>7.958 us</strong></td><td>52.39 us</td><td>8.992 us</td><td>8.665 us</td></tr><tr><td>transform2 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>87.2060 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>45.0272 ns</strong></td></tr><tr><td>transform2 mul transform2</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>87.5702 ns</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>40.1995 ns</strong></td></tr><tr><td>transform3 inverse</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>542.8401 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td>748.2648 ns</td></tr><tr><td>transform3 mul transform3d</td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>118.0659 ns</strong></td><td>N/A</td><td>N/A</td><td>N/A</td><td>N/A</td><td><strong>115.3294 ns</strong></td></tr><tr><td>vector3 cross</td><td>5.9052 ns</td><td><strong>5.7307 ns</strong></td><td>6.4232 ns</td><td>6.2395 ns</td><td>25.0006 ns</td><td>36.5961 ns</td><td>15.0303 ns</td><td>28.6082 ns</td><td>28.6343 ns</td><td>29.5467 ns</td></tr><tr><td>vector3 dot</td><td><strong>5.7524 ns</strong></td><td><strong>5.8113 ns</strong></td><td>6.6820 ns</td><td>6.3391 ns</td><td>25.5593 ns</td><td>26.1824 ns</td><td>13.6831 ns</td><td>25.4740 ns</td><td>25.9099 ns</td><td>26.1271 ns</td></tr><tr><td>vector3 length</td><td><strong>5.3441 ns</strong></td><td>5.4417 ns</td><td>5.3741 ns</td><td><strong>5.2332 ns</strong></td><td>20.5369 ns</td><td>34.2988 ns</td><td>20.5652 ns</td><td>20.6259 ns</td><td>20.9281 ns</td><td>20.6052 ns</td></tr><tr><td>vector3 normalize</td><td><strong>15.6224 ns</strong></td><td><strong>15.3854 ns</strong></td><td><strong>15.5892 ns</strong></td><td><strong>15.6585 ns</strong></td><td>59.1804 ns</td><td>60.9510 ns</td><td>35.7763 ns</td><td>61.3666 ns</td><td>36.7304 ns</td><td>61.3199 ns</td></tr></tbody></table>
<h2 class="anchor anchorWithHideOnScrollNavbar_jgva" id="conclusion">Conclusion<a href="https://dimforge.com/blog/2020/03/23/simd-aosoa-in-nalgebra#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>The use of SIMD&nbsp;AoSoA is extremely promising for doing efficiently lots of linear algebra on large arrays of entities with the same types.
This will be possible in <strong>nalgebra</strong> in its next version 0.21.0 and will perform as efficiently as the current implementation in <strong>ultraviolet</strong>
when using <code>f32x4</code> and will also be compatible with other SIMD types as well (e.g. <code>f32x16</code>, <code>f64x2</code>, <code>i32x4</code>, <code>u8x4</code>, etc.) Those types are newtypes wrapping
the types from <strong>packed_simd</strong>. Those newtypes will come from a new crate named <a href="https://crates.io/crates/simba" target="_blank" rel="noopener noreferrer">simba</a>
which I will present in more depth in the next edition of the <code>This month in Rustsim</code> blog posts.</p>
<p>Finaly here are two elements to keep in mind:</p>
<ul>
<li>Compilation flags matter a lot when measuring performance. <code>-C target-cpu</code> or <code>codegen-units=1</code> can have significant
impacts on your release performance.</li>
<li>SIMD&nbsp;AoSoA comes with a price: algorithms must be carefully designed to obtain as much gain as possible compared to an
AoS approach.</li>
</ul>
<hr>
<p><strong>Thank you all for reading, and for your support on <a href="https://www.patreon.com/sebcrozet" target="_blank" rel="noopener noreferrer">patreon</a> or <a href="https://github.com/sponsors/sebcrozet" target="_blank" rel="noopener noreferrer">GitHub sponsor</a>!</strong></p>
<p><strong>Don't hesitate to share your thoughts on this topic, or to correct me if something seems off to you.</strong></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This month in rustsim \#9 (November 2019 to February 2020)]]></title>
            <link>https://dimforge.com/blog/2020/03/01/this-month-in-rustsim</link>
            <guid>https://dimforge.com/blog/2020/03/01/this-month-in-rustsim</guid>
            <pubDate>Sun, 01 Mar 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the ninth edition of This month in rustsim! This newsletter will provide you with a]]></description>
            <content:encoded><![CDATA[<p>Welcome to the ninth 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/alga" target="_blank" rel="noopener noreferrer"><strong>alga</strong></a> (for abstract algebra) crates. This ninth edition will actually contain updates for the past
<strong>four</strong> months.</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><a href="https://salva.rs/" target="_blank" rel="noopener noreferrer"><img decoding="async" loading="lazy" src="https://www.salva.rs/img/logo_salva_full.svg" alt="salva logo" class="img_XsDP"></a></p></center>
<p>I am thrilled to announce that the release of massive improvements of <strong>salva2d</strong> and <strong>salva3d</strong> v0.2!</p>
<p>Recall that <strong>salva</strong> is our new project introduced a few months ago dedicated to <strong>fluid simulation</strong>.
The goal of <strong>salva</strong> is to provide CPU-based, particle-based, 2D and 3D, fluid simulation libraries that can be used for interactive
and offline applications like animation. The version 0.2.0 now contains several new features for both pressure resolution as well
as nonpressure forces:</p>
<ul>
<li><strong>Pressure resolution:</strong> <a href="https://animation.rwth-aachen.de/media/papers/2015-SCA-DFSPH.pdf" target="_blank" rel="noopener noreferrer">DFSPH</a>
and <a href="https://cg.informatik.uni-freiburg.de/publications/2013_TVCG_IISPH.pdf" target="_blank" rel="noopener noreferrer">IISPH</a>. Unfortunately we removed
our implementation of PBF because it is patented.</li>
<li><strong>Viscosity:</strong> <a href="https://animation.rwth-aachen.de/media/papers/2016-TVCG-ViscousDFSPH.pdf" target="_blank" rel="noopener noreferrer">DFSPH viscosity</a>,
<a href="http://www.astro.lu.se/~david/teaching/SPH/notes/annurev.aa.30.090192.pdf" target="_blank" rel="noopener noreferrer">Artificial viscosity</a>, and XSPH viscosity.</li>
<li><strong>Surface tension:</strong> <a href="https://cg.informatik.uni-freiburg.de/publications/2007_SCA_SPH.pdf" target="_blank" rel="noopener noreferrer">WCSPH</a> surface tension, and
methods from <a href="http://peridynamics.com/publications/2014-He-RSS.pdf" target="_blank" rel="noopener noreferrer">He et al. 2014</a>,
and <a href="https://cg.informatik.uni-freiburg.de/publications/2013_SIGGRAPHASIA_surfaceTensionAdhesion.pdf" target="_blank" rel="noopener noreferrer">Akinci et al. 2013</a>.</li>
<li><strong>Elasticity:</strong> method from <a href="https://cg.informatik.uni-freiburg.de/publications/2009_NP_corotatedSPH.pdf" target="_blank" rel="noopener noreferrer">Becker et al. 2009</a>.</li>
</ul>
<p>With the addition of new traits, it is also possible to define your own pressure resolution scheme as well as your own
nonpressure forces. You can see those features in action in the following video:</p>
<center><iframe width="560" height="315" src="https://www.youtube.com/embed/NBoSEanWHE4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe></center>
<p>You can also play with those examples in the <a href="https://www.salva.rs/all_examples2/" target="_blank" rel="noopener noreferrer">2D WASM version</a> and the
<a href="https://www.salva.rs/all_examples3/" target="_blank" rel="noopener noreferrer">3D WASM version</a>. However, for better performance, you are encouraged to compile
and run the examples on the <code>examples2d</code> and <code>examples3d</code> folders while enabling the <code>parallel</code> feature. For example:</p>
<div class="language-bash codeBlockContainer_U1jY theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_vtuI"><pre tabindex="0" class="prism-code language-bash codeBlock_m3N_ thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines__l0x"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/rustsim/salva</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cd salva/examples3d</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cargo run --release --bin all_examples3 --features parallel</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 to those features it is now possible to:</p>
<ul>
<li>Remove fluids, boundaries, and collider couplings.</li>
<li>Add/remove fluid particles after the fluid has been created. This is useful to simulate, e.g., sources of water. You
can for example see the <a href="https://www.salva.rs/all_examples3d/?faucet" target="_blank" rel="noopener noreferrer">faucet demo</a>.</li>
<li>Enable the <code>parallel</code> feature to benefit from the parallelism (based on the <code>rayon</code> crate) of most stages of the fluid
simulation. This includes parallel collision detection between particles, parallel pressure forces computation,
and parallel non-pressure forces computation.</li>
</ul>
<p>The most important feature that is missing now is a working implementation of adaptive time-stepping. While there
is an implementation of the CFL condition, it sometimes breaks the simulation for a reason that has yet to be determined.</p>
<h1>What's next for 2020</h1>
<p>As mentioned in my previous post <a href="https://www.patreon.com/posts/28917514" target="_blank" rel="noopener noreferrer">about the future of nphysics</a>, the main goal
2020 is to focus on performance. Including (not necessarily in that order):</p>
<ul>
<li>Performing fine-grained performance optimizations, both in term of algorithms (for example rewriting a more efficient
broad-phase approach) and in term of implementation (for example writing a SIMD-powered constraints solver).</li>
<li>Performance improvements on nalgebra itself (the linear-algebra crate nphysics is based on).</li>
<li>Adding parallelism to nphysics and ncollide.</li>
</ul>
<p>Because I already focused a lot on parallelism on <strong>salva</strong>, I will start with the third objective: adding parallelism
to nphysics and ncollide. This will likely affect the API of low-level components (like the body and collider storages).</p>
<h1>Thanks</h1>
<p>We would like to thank the whole community and contributors. In particular, thanks to the contributors from the past three months<sup><a href="https://dimforge.com/blog/2020/03/01/this-month-in-rustsim#user-content-fn-1-376cc6" id="user-content-fnref-1-376cc6" data-footnote-ref="true" aria-describedby="footnote-label">1</a></sup>:</p>
<ul>
<li><a href="https://github.com/alvinhochun" target="_blank" rel="noopener noreferrer">alvinhochun</a></li>
<li><a href="https://github.com/cedric-h" target="_blank" rel="noopener noreferrer">cedric-h</a></li>
<li><a href="https://github.com/DasEtwas" target="_blank" rel="noopener noreferrer">DasEtwas</a></li>
<li><a href="https://github.com/james-rms" target="_blank" rel="noopener noreferrer">james-rms</a></li>
<li><a href="https://github.com/MJohnson459" target="_blank" rel="noopener noreferrer">MJohnson459</a></li>
<li><a href="https://github.com/NickMolloy" target="_blank" rel="noopener noreferrer">NickMolloy</a></li>
<li><a href="https://github.com/sebcrozet" target="_blank" rel="noopener noreferrer">sebcrozet</a></li>
<li><a href="https://github.com/SiegeLord" target="_blank" rel="noopener noreferrer">SiegeLord</a></li>
<li><a href="https://github.com/wsuchy" target="_blank" rel="noopener noreferrer">wsuchy</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 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/03/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-376cc6">
<p><em>The list of contributors is automatically generated from the past four 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/03/01/this-month-in-rustsim#user-content-fnref-1-376cc6" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
        </item>
    </channel>
</rss>